Subversion Repositories DevTools

Rev

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

Rev Author Line No. Line
267 dpurdie 1
########################################################################
1348 dpurdie 2
# Copyright (C) 1998-2012 Vix Technology, All rights reserved
267 dpurdie 3
#
4
# Module name   : jats_svnrelease.pl
5
# Module type   : Jats Utility
6
# Compiler(s)   : Perl
7
# Environment(s): Jats
8
#
9
# Description   : A script to build a package from a SubVersion
10
#                 The script will:
11
#                   Create a workspace
12
#                   Checkout the files
13
#                   Locate the build file
14
#                   Build the packages
15
#                   Install packages
16
#                   Remove the view
17
#
18
#               The script can do a lot of other things too.
19
#
2652 dpurdie 20
#               Defined exit code for automation
21
#                   10 - No files in extracted view
22
#                        Root directory not found
23
#                   11 - Label not found
24
#                   1  - Everything else
25
#
267 dpurdie 26
# Notes         : A lot of this code is common to jats_ccrelease.pl
27
#                 Will need to refactor if both are to be used
28
#
29
#......................................................................#
30
 
31
require 5.006_001;
32
use strict;
33
use warnings;
34
use JatsError;
35
use JatsSystem;
36
use FileUtils;
37
use JatsBuildFiles;
38
use ArrayHashUtils;
39
use JatsSvn;
40
 
41
use Pod::Usage;                             # required for help support
42
use Getopt::Long;
43
use File::Find;
44
use File::Copy;
45
use File::Path;
46
use Cwd;
47
 
48
my $VERSION = "1.0.0";                      # Update this
49
 
50
#
51
#   Options
52
#
53
my $opt_debug   = $ENV{'GBE_DEBUG'};        # Allow global debug
54
my $opt_verbose = $ENV{'GBE_VERBOSE'};      # Allow global verbose
55
my $opt_help = 0;                           # User help level
56
my @opt_spec;                               # Labels used as a base for the view
57
my $opt_dpkg = 1;                           # Transfer built package to dpkg_archive
58
my $opt_copy = 0;                           # Copy built package to user
59
my $opt_reuse = 0;                          # Re-user view if it exists
60
my $opt_viewname;                           # View Name
1348 dpurdie 61
my $opt_extract = 0;                        # Just create a static view
267 dpurdie 62
my $opt_extract_files;                      # Just extract files to user - no view
1348 dpurdie 63
my $opt_devModeStr;                         # Development mode string
64
my $opt_devMode = '';                       # Development mode (cleaned up)
267 dpurdie 65
my $opt_delete = 0;                         # Just delete the view. 2 to force
66
my @opt_build;                              # build files to use (kludge)
67
my $opt_test;                               # Test the build process - no copy
68
my $opt_cache;                              # Cache external packages
69
my $opt_keep = 0;                           # Keep view if successful
70
my $opt_beta;                               # Create beta release
71
my $opt_merge;                              # Merge release
72
my $opt_path;                               # Path for view spec
73
my $opt_runtests = 1;                       # Run unit tests after build
74
my $opt_branch;                             # Create config spec with branch
2029 dpurdie 75
my $opt_mkbranch;                           # Create branch
267 dpurdie 76
my $opt_debug_build = 0;                    # Build Debug Only
77
my $opt_prod_build = 0;                     # Build ion Only
78
my $opt_view_root = $ENV{'GBE_VIEWBASE'};   # Root of the view
79
my $opt_prefix = 1;                         # Prefix the view tag with user-name
351 dpurdie 80
my $opt_tag;                                # View tag insert (build or export or user)
341 dpurdie 81
my $bad_label_name = 0;                     # Badly formed label
2426 dpurdie 82
my $opt_escrow = 0;                         # Escrow Mode
267 dpurdie 83
 
84
#
85
#   Globals - Provided by the JATS environment
86
#
87
my $USER            = $ENV{'USER'};
88
my $UNIX            = $ENV{'GBE_UNIX'};
89
my $GBE_SANDBOX     = $ENV{'GBE_SANDBOX'};
90
my $GBE_ABT         = $ENV{'GBE_ABT'} || '0';
279 dpurdie 91
my $MACHINENAME     = $ENV{'GBE_HOSTNAME'};
343 dpurdie 92
my $GBE_VIEWBASE    = $ENV{'GBE_VIEWBASE'};   # Root of the view
267 dpurdie 93
 
94
#
95
#   Globals
96
#
343 dpurdie 97
my $VIEWDIR_ROOT;                           # Root of the static view
267 dpurdie 98
my $VIEWDIR;                                # Absolute path to the view
99
my $VIEWPATH;                               # Path relative to clearcase
1348 dpurdie 100
my $view_prefix     = "${USER}_";           # Default WorkSpace prefix
101
my $user_cwd;                               # Initial User Directory
102
my $error = 0;                              # Build Error Flag/Counter
267 dpurdie 103
my $label_count = 0;                        # Number of labels to create the view
104
my @label_not_pegged;                       # List of unpegged labels
1348 dpurdie 105
my @messageText;                            # Messages to be displayed AFTER extraction
106
my $workSpace;                              # Path to created workspace (or extact)
107
my $svnSession;                             # Primary Subversion Session
1356 dpurdie 108
my $noReleaseWs = 0;                        # Do not officially release from this
1348 dpurdie 109
my $checkDelta = 1;                         # Check Diffs between Tag and Head
110
                                            #   0 - Don't do anything
111
                                            #   1 - Warn about diffs
112
                                            #   2 - Error if diffs
1357 dpurdie 113
my $traceBack = 2;                          # Trace Back error control. As above
2652 dpurdie 114
my $needDevBranch = 1;                      # DevBranch error control. As above
267 dpurdie 115
 
1348 dpurdie 116
#
117
#   Data about the package-version
118
#
119
my $srcPathPkg;                             # Root of the package
120
my $devBranch;                              # Development Branch - within the package
121
my $devBranchPeg;                           # May be pegged
122
my $devBranchHead;                          # Revision of the HEAD of the development branch
123
my $tagLabel;                               # Label in 'tags'
124
my $tagPeg;                                 # May be pegged
125
my $tagLabelBranch;                         # Tagged from this branch: Discovered
126
my $tagLabelBranchPeg;                      # Tagged from this branch at this peg: Discovered
127
my $ttbType;                                # trunk, tags or branches
128
my $urlType;                                # 'jats' or 'url'
129
my $initialUrl;                             # Initial URL of target
267 dpurdie 130
 
131
#-------------------------------------------------------------------------------
132
# Function        : Mainline Entry Point
133
#
1348 dpurdie 134
# Description     : Main entry point
267 dpurdie 135
#
1348 dpurdie 136
# Inputs          : ARGV[]      - See documentation below
267 dpurdie 137
#
138
 
139
#
140
#   Alter some option defaults if we are creating a view within a sandbox
141
#
142
if ( $GBE_SANDBOX )
143
{
343 dpurdie 144
   $GBE_VIEWBASE = $GBE_SANDBOX;
267 dpurdie 145
   $opt_prefix = 0;
146
}
147
 
148
#
149
#   Parse the user options
150
#
151
my $result = GetOptions (
1348 dpurdie 152
                'help:+'        => \$opt_help,                  # flag, multiple use allowed
153
                'manual:3'      => \$opt_help,                  # flag
154
                'v|verbose:+'   => \$opt_verbose,               # flag, multiple use allowed
155
                'label=s'       => \@opt_spec,                  # Array of build specs
156
                'view=s'        => \$opt_viewname,              # String
157
                'dpkg!'         => \$opt_dpkg,                  # [no]flag
158
                'copy!'         => \$opt_copy,                  # [no]flag
159
                'reuse!'        => \$opt_reuse,                 # [no]flag
160
                'extract:+'     => \$opt_extract,               # flag
161
                'extractfiles'  => \$opt_extract_files,         # flag
162
                'delete:+'      => \$opt_delete,                # flag
163
                'build=s'       => \@opt_build,                 # An array of build
164
                'test!'         => \$opt_test,                  # [no]flag
165
                'cache'         => \$opt_cache,                 # flag
166
                'keep!'         => \$opt_keep,                  # [no]flag
167
                'beta!'         => \$opt_beta,                  # [no]flag
168
                'merge'         => \$opt_merge,                 # [no]flag
169
                'path=s'        => \$opt_path,                  # string
170
                'runtests!'     => \$opt_runtests,              # [no]flag
171
                'branch=s'      => \$opt_branch,                # String
2029 dpurdie 172
                'mkbranch=s'    => \$opt_mkbranch,              # String
1348 dpurdie 173
                'prodOnly'      => \$opt_prod_build,            # flag
174
                'debugOnly'     => \$opt_debug_build,           # flag
175
                'root=s'        => \$GBE_VIEWBASE,              # string
176
                'prefix!'       => \$opt_prefix,                # flag
177
                'tag=s'         => \$opt_tag,                   # string
178
                'devMode=s'     => \$opt_devModeStr,            # string
267 dpurdie 179
                );
180
 
181
                #
182
                #   UPDATE THE DOCUMENTATION AT THE END OF THIS FILE !!!
183
                #
184
 
185
#
186
#   Process help and manual options
187
#
188
pod2usage(-verbose => 0, -message => "Version: $VERSION")  if ($opt_help == 1  || ! $result);
189
pod2usage(-verbose => 1)  if ($opt_help == 2 );
190
pod2usage(-verbose => 2)  if ($opt_help > 2 );
191
 
192
InitFileUtils();
193
#
194
#   Configure the error reporting process now that we have the user options
195
#
196
ErrorConfig( 'name'    => 'SVNRELEASE',
197
             'verbose' => $opt_verbose );
198
 
199
#
200
#   Validate user options
201
#   Use either -label or one command line argument
202
#
1348 dpurdie 203
Error ("Cannot mix -extractfiles and -branch")
204
    if ( $opt_branch && $opt_extract_files );
267 dpurdie 205
Error ("Unexpected command line arguments present.","Cannot mix -label and command line label" )
206
    if ( $#opt_spec >= 0 && $#ARGV >= 0);
2029 dpurdie 207
Error ("Cannot specify both '-mkbranch' and '-branch'")
208
    if ( $opt_mkbranch && $opt_branch );
267 dpurdie 209
 
210
push @opt_spec, @ARGV;
211
 
212
unless(  @opt_spec  )
213
{
1348 dpurdie 214
    Error ("Need a workspace or a label. -help for options") if ( $opt_delete  && ! $opt_viewname );
215
    Error ("Need a Subversion Reference or URL. -help for options") unless $opt_delete;
267 dpurdie 216
}
217
 
2029 dpurdie 218
#
219
#   Set up branching values
220
#       mkbranck    - Create if not exists. Error if it exists
221
#       branch      - Error if not exists
222
#
223
if ( $opt_mkbranch ) {
224
    $opt_branch = $opt_mkbranch;
225
    $opt_mkbranch = 1;
226
}
227
$opt_branch = SvnIsaSimpleLabel($opt_branch) if ( $opt_branch );
228
 
1348 dpurdie 229
#   Determine extraction mode
230
#       Working- Default
231
#               Extract point on development branch were tag was taken
232
#               Update build files
233
#               Warn about files that have changed
267 dpurdie 234
#
1348 dpurdie 235
#       Tag   - Extract point on development branch were tag was taken
236
#               Update build files
237
#               Error if tag is not the tip
267 dpurdie 238
#
1348 dpurdie 239
#       Tip   - Extact tip of the development branch
240
#               Warn about files that have changed between head and tagPoint
241
#
242
#       Exact - What the user specified
243
#               May be a tag and thus not usable
244
#
245
if ( $opt_devModeStr )
267 dpurdie 246
{
1348 dpurdie 247
    if ( $opt_devModeStr =~ m/^(Tip)|(BranchTip)$/i) {
248
        $opt_devMode = 'tip';
249
        $checkDelta = 1;
1356 dpurdie 250
        $noReleaseWs = 1;
2652 dpurdie 251
        $needDevBranch = 2;
1348 dpurdie 252
    } elsif ( $opt_devModeStr =~ m/^(Tag)|(TagPoint)$/i) {
253
        $opt_devMode = 'tag';
254
        $checkDelta = 2;
255
        $checkDelta = 1 if ( $opt_branch );
256
        $noReleaseWs = 0;
2652 dpurdie 257
        $needDevBranch = 2 unless ( $opt_branch );;
1348 dpurdie 258
    } elsif ( $opt_devModeStr =~ m/^(Work)|(Working)$/i) {
259
        $opt_devMode = '';
260
        $checkDelta = 1;
1356 dpurdie 261
        $noReleaseWs = 0;
1348 dpurdie 262
    } elsif ( $opt_devModeStr =~ m/^Exact$/i) {
263
        $opt_devMode = 'exact';
264
        $checkDelta = 1;
265
        $noReleaseWs = 0;
2029 dpurdie 266
        Error ('Cannot mix -[mk]branch and -devMode=' . $opt_devModeStr ) if ( $opt_branch );
1360 dpurdie 267
    } elsif ( $opt_devModeStr =~ m/^escrow$/i) {
268
        # JATS internal use only. Not advertised
1357 dpurdie 269
        $opt_devMode = 'exact';
2426 dpurdie 270
        $opt_escrow = 1;
1357 dpurdie 271
        $checkDelta = 0;
272
        $noReleaseWs = 0;
273
        $traceBack = 1;
2029 dpurdie 274
        Error ('Cannot mix -[mk]branch and -devMode=' . $opt_devModeStr ) if ( $opt_branch );
1348 dpurdie 275
    } else {
276
        Error ("Unknown development mode: $opt_devModeStr");
277
    }
267 dpurdie 278
}
279
 
280
#
1348 dpurdie 281
#   The buildtool works in a known environment
282
#
283
if ( $GBE_ABT )
284
{
1360 dpurdie 285
    $noReleaseWs = 0;       # Can always release
286
    $checkDelta = 0;        # Do not care. Often expected to have changes.
287
    $traceBack = 2;         # Must check traceback. Validate RM data
1348 dpurdie 288
}
289
 
290
#
267 dpurdie 291
#   Limit the user to ONE label/tag/
292
#   Reason: Under Subversion its not possible to 'pinch' files from another
293
#           package. Don't need to create a workspace with multiple labels
294
#
295
#           It was a bad practice under clearcase
296
#
297
if ( $#opt_spec >= 1 )
298
{
299
    Error ("Multiple labels not supported",
300
           "Use one label to describe a package" );
301
}
1348 dpurdie 302
parseSubversionRef($opt_spec[0]);
303
Error ("INTERNAL: initialUrl not set") unless ( $initialUrl );
304
Error ("Cannot interprete the URL or Subversion Reference: $opt_spec[0]") unless ( $srcPathPkg  );
267 dpurdie 305
 
306
#
307
#   User has specified both debug and production
308
#   Then set both to 0 : ie default
309
#
310
if ( $opt_debug_build + $opt_prod_build > 1 )
311
{
312
    $opt_debug_build = 0;
313
    $opt_prod_build = 0;
314
}
315
 
316
#
317
#   User has requested test mode
318
#       - Don't copy
1348 dpurdie 319
#       - Don't package
267 dpurdie 320
#
321
if ( $opt_test )
322
{
323
    $opt_dpkg = 0;
324
    $opt_copy = 0;
325
}
326
 
327
#
328
#   Determine the machine type
329
#
330
Verbose ("Machine Type: UNIX=$UNIX");
331
 
332
Error ("Machine Name not determined")
333
    unless ( $MACHINENAME );
334
$user_cwd = getcwd;
335
 
336
Error ("USER name not determined" )
337
    unless ( $USER );
338
 
339
#
343 dpurdie 340
#   Clean up the view root directory
267 dpurdie 341
#
343 dpurdie 342
$VIEWDIR_ROOT = Realpath($GBE_VIEWBASE) || $GBE_VIEWBASE;
267 dpurdie 343
 
344
Verbose ("Viewpath: $VIEWDIR_ROOT");
345
Error ("Cannot locate view root directory: $VIEWDIR_ROOT" ) unless (-d $VIEWDIR_ROOT);
346
 
347
#
348
#   Remove any user name from the front of the view name
349
#   Simplifies the deletion process as the user can provide
350
#   the directory name
351
#
1348 dpurdie 352
$view_prefix = '' unless ( $opt_prefix );
267 dpurdie 353
 
354
#
355
#   Create a class to describe the complete SVN label
1348 dpurdie 356
#   This will parse the label and create a number of nice elements that will
357
#   be used in determing the name of the workspace
267 dpurdie 358
#
1348 dpurdie 359
$svnSession = NewSessionByUrl ( $initialUrl, 1 );
360
#DebugDumpData("New Session", $svnSession );
267 dpurdie 361
 
362
#
1348 dpurdie 363
#   Test for a pegged label
364
#
365
push @label_not_pegged, $svnSession->Full
366
    unless ( $svnSession->Peg );
367
 
368
#
267 dpurdie 369
#   Setup user specified workspace
370
#   Include the user name to ensure that the view name is unique-ish
371
#   Keep the name as short as possible as some compilers display a fixed
372
#   length filename in error messages and this name is part of the path
373
#
374
#   Base the viewname on the view label. This will simplify the creation
375
#   of multiple views and reduce the risk of unexpected deletion
376
#
1454 dpurdie 377
$opt_viewname = calcViewName();
267 dpurdie 378
$opt_viewname =~ s~^$view_prefix~~ if (defined($opt_viewname) && $view_prefix && $opt_delete );
379
 
380
#
381
#   Create a clearcase view to be used for the view
382
#
383
$VIEWPATH = "$view_prefix$opt_viewname";
384
$VIEWDIR = "$VIEWDIR_ROOT/$VIEWPATH";
299 dpurdie 385
$VIEWDIR =~ tr~\\/~/~s;
267 dpurdie 386
Verbose( "Hostname: $MACHINENAME" );
387
Verbose( "Viewpath: $VIEWPATH" );
388
Verbose( "Viewdir : $VIEWDIR" );
389
 
390
#
391
#   If the user has specified a "source path", then we must ensure that it is
392
#   valid. It will be used to create the WorkSpace
393
#
394
#   Ensure that the path is a defined variable. If used prepend a / to simplify
395
#   concatenation.
396
#
397
Verbose("Validate Source Path");
398
if ( $opt_path )
399
{
400
    $opt_path =~ tr~\\/~/~s;
401
    $opt_path =~ s~/$~~;
402
    $opt_path =~ s~^/~~;
403
 
404
    Error( "Source Path has drive specifier" ) if ( $opt_path =~ m~^[A-Za-z]\:~ );
405
    $opt_path = '/'.$opt_path ;
406
}
407
else
408
{
409
    $opt_path = '';
410
}
1348 dpurdie 411
$workSpace = $VIEWDIR . $opt_path;
412
Verbose( "workSpace : $workSpace" );
267 dpurdie 413
 
414
#
2029 dpurdie 415
#   Operation
416
#   If all we are doing is deleting the view then do it now
417
#   If we are going to extract stuff, then we will delay the deletion
418
#   as long as possible - incase we decide we can't
267 dpurdie 419
#
2029 dpurdie 420
if ( $opt_delete )
421
{
422
    delete_view()
423
        unless ( $opt_reuse );
424
    exit 0;
425
}
267 dpurdie 426
 
427
#
1348 dpurdie 428
#   Ensure that the label is present within the specified Repository
267 dpurdie 429
#
430
Verbose("Ensure Labels can be found in a Repository");
1348 dpurdie 431
Verbose ("Testing label: ". $svnSession->Full );
267 dpurdie 432
$label_count++;
433
 
2652 dpurdie 434
unless ( $svnSession->SvnValidateTarget (
267 dpurdie 435
                    'cmd'    => 'SvnRelease',
1348 dpurdie 436
                    'target' => $svnSession->Full,
2652 dpurdie 437
                    'test' => 1,
438
                    )
439
        )
440
{
441
    Error ('ExitCode=11', "SvnRelease: Tag/Reference not found in repository", "Reference: " . $svnSession->Full)
442
}
1348 dpurdie 443
 
267 dpurdie 444
#
1348 dpurdie 445
#   If the user did not provide a peg then examine
446
#   the 'tag' in the repo and determine when it was created
447
#   This will not work to well if the user is allowed to move the tag
267 dpurdie 448
#
1348 dpurdie 449
unless ( $svnSession->Peg() )
450
{
451
    $svnSession->SvnInfo( $svnSession->Full, 'InfoRepo' );
452
    my $peg = $svnSession->{'InfoRepo'}{'Last Changed Rev'};
267 dpurdie 453
 
1348 dpurdie 454
    $svnSession->{'PEG'} = '@' . $peg;
455
    if ( $tagLabel ) {
456
        $tagPeg = $peg;
457
    } elsif ( $devBranch ) {
458
        $devBranchPeg = $peg;
459
    }
460
}
461
#debugDumpRefInfo('Get Peg');
462
 
267 dpurdie 463
#
1348 dpurdie 464
#   Trace back from the tag to the point at which it was copied
465
#   This should be the same as the user provided development branch
466
#   but it may not be the same if the user is changing the branch
467
#
1357 dpurdie 468
if ( $tagLabel && $traceBack )
1348 dpurdie 469
{
470
    my $btData;
1349 dpurdie 471
    my $labelBranch = $svnSession->backTrackSvnLabel(
472
                            join ('@', $tagLabel, $tagPeg)
473
                          , 'data' => \$btData
474
                          , 'onlysimple' => 0,
475
                          , 'printdata' => 0 );
476
    $svnSession->{SavedBackTrack} = $btData;
477
    unless ( $btData->{isaBranch} )
1348 dpurdie 478
    {
2652 dpurdie 479
        my $text = "Cannot trace package label back to a development branch";
480
        Error ($text) if ( $needDevBranch == 2 );
481
        Warning ($text);
1348 dpurdie 482
    }
483
    else
484
    {
485
        Error ("INTERNAL: Cannot parse result of backTrackSvnLabel: $labelBranch")
1349 dpurdie 486
            unless ($btData->{devBranch} =~ m~^(.*)@(\d+)$~);
1348 dpurdie 487
        $tagLabelBranch = $1;
488
        $tagLabelBranchPeg = $2;
489
 
490
        #
1349 dpurdie 491
        #   Verify that the Development Branch matches that provided by the user
1348 dpurdie 492
        #
493
        if ( $devBranch && ($devBranch ne $tagLabelBranch) )
494
        {
495
            # If the user is creating a branch, then allow this mismatch
496
            #
497
            unless ( $opt_branch && ($devBranch =~ m~/$opt_branch$~) )
498
            {
1357 dpurdie 499
                my @msgText;
500
                push ( @msgText,
501
                        "The package Tag was not taken from the development branch",
502
                        "Development Branch: $devBranch\@$tagPeg",
503
                        "Tag traced back to: $tagLabelBranch\@$tagLabelBranchPeg" );
504
                if ( $traceBack == 1) {
505
                    push @messageText, @msgText;
506
                } else {
507
                    Error ( @msgText );
508
                }
1348 dpurdie 509
            }
510
        }
511
        $devBranchPeg = $tagLabelBranchPeg unless ( $devBranchPeg );
512
 
513
        #   Ensure that the TAG has not been modified since it was taken
514
        #   The extraction algorithm assumes that the tag directory is
515
        #   immutable.
516
        #
1349 dpurdie 517
        #   The build daemon will actually modify the build file during
518
        #   a ripple - this is catered for.
519
        #
520
        #   If other files have been modifed then it should be an error
521
        #
522
        if ( $btData->{changeSets} > 1 )
1348 dpurdie 523
        {
524
            Error ("Tag has been modified since created") if ( $GBE_ABT );
525
            Warning ("Tag has been modified since created");
1349 dpurdie 526
            $noReleaseWs = 1;
1348 dpurdie 527
        }
528
    }
529
}
530
#debugDumpRefInfo('BackTrack Label');
531
 
532
#
533
#   Examine the HEAD of the development branch and determine if there
534
#   have been any changes since the tag was taken
535
#
536
determineChangedFiles();
537
 
538
################################################################################
539
#   Create a workspace based on the tag
540
#   It will be back tracked to the branch that was tagged:
541
#       - Ripple build tags look better in version tree
542
#       - User can develop in the workspace as its not linked to an immutable 'tags'
543
#
544
#   So far we have:
545
#       $initialUrl         - Url to the version that the user specified
546
#       $initialUrlBranch   - Url to the branch from which the initialUrl was taken
547
#                             Iff based on a Tag
548
#       $urlDevBranchHead   - Head of the Development Branch
549
#
550
 
551
$initialUrl = substr( $initialUrl, 1 + length($srcPathPkg));
552
 
553
my $initialUrlBranch;
554
if ( $tagLabelBranch )
555
{
556
    $initialUrlBranch  = $tagLabelBranch;
557
    $initialUrlBranch .= '@' . $tagLabelBranchPeg;
558
}
559
 
560
my $urlDevBranchHead;
561
if ( $devBranch )
562
{
563
    $urlDevBranchHead  = $devBranch;
564
}
565
else
566
{
567
    $urlDevBranchHead  = $tagLabelBranch;
568
}
569
 
570
#
571
#   Debug information
572
#
573
if ( IsVerbose(1) ) {
574
    debugDumpRefInfo('Creating workspaces');
575
    Verbose ('------------');
576
    Verbose ("initialUrl       :", $initialUrl);
577
    Verbose ("initialUrlBranch :", $initialUrlBranch );
578
    Verbose ("urlDevBranchHead :", $urlDevBranchHead );
579
    Verbose ("opt_viewname     :", $opt_viewname );
580
#    DebugDumpData("svn_label", $svnSession );
581
}
582
 
583
#
267 dpurdie 584
#   If we are only extracting files then ...
585
#
586
if ( $opt_extract_files )
587
{
1357 dpurdie 588
    Warning(@messageText );
267 dpurdie 589
    extract_files_from_view();
590
    exit (0);
591
}
592
 
593
#
594
#   Create a new workspace
1348 dpurdie 595
#       This is not done if the user is reusing an existing workspace
596
#       AND the existing workspace exists.
267 dpurdie 597
#
598
if (! -d $VIEWDIR || ! $opt_reuse )
599
{
1348 dpurdie 600
    Message( "Create the workspace" . ($GBE_SANDBOX ? " in a SANDBOX" : ''));
267 dpurdie 601
 
1348 dpurdie 602
    my $branch;
603
    my $view_tag;
604
    my $update_tagsChanges;
605
    if ( $opt_devMode eq 'tip' ) {
606
        $view_tag =  $urlDevBranchHead;
607
    } elsif ( $opt_devMode eq 'exact' ) {
608
        $view_tag =  $initialUrl;
609
    } else {
610
        $view_tag = $initialUrlBranch || $initialUrl;
611
        $update_tagsChanges = 1;
612
    }
613
    Message ("Creating Workspace based on: $view_tag");
614
    $view_tag = $svnSession->FullPath() . '/' .$view_tag;
615
    Verbose("Creating Workspace:", $view_tag);
616
 
267 dpurdie 617
    #
1270 dpurdie 618
    #   If a branch is required ...
2029 dpurdie 619
    #   Two modes:
620
    #       mkbranch    - Ensure that the branch does not exist
621
    #                     Make a new one
622
    #       branch      - Ensure that the branch does exist
623
    #                     Use existing branch
1348 dpurdie 624
    #   Ensure that the branch is NOT in the Repository
267 dpurdie 625
    #
626
    if ( $opt_branch )
627
    {
1348 dpurdie 628
        $branch = $svnSession->BranchName($opt_branch, 'branches' );
629
        $svnSession->SvnValidateTarget (
630
                        'cmd'    => 'SvnRelease: Validate Branch',
1270 dpurdie 631
                        'target' => $branch,
2029 dpurdie 632
                        'require' =>   (! $opt_mkbranch),
633
                        'available' => (  $opt_mkbranch),
1270 dpurdie 634
                        );
2029 dpurdie 635
 
636
        #
637
        #   If using an existing branch, then set up the name
638
        #   of the source.
639
        #
640
        $view_tag = $branch if ( ! $opt_mkbranch );
267 dpurdie 641
    }
2029 dpurdie 642
 
1270 dpurdie 643
    #
2029 dpurdie 644
    #   Perform delayed delete of any existign view
645
    #   The process has been delayed as much as possible - incase other tests
646
    #   fail
647
    #
648
    delete_view();
649
 
650
    #
1270 dpurdie 651
    #   Create the workspace
652
    #
2426 dpurdie 653
    $svnSession->SvnCo ( $view_tag, $workSpace , 'escrow' => $opt_escrow );
267 dpurdie 654
    Error ("Cannot locate the created Workspace")
1348 dpurdie 655
        unless ( -d $workSpace);
656
    importTagChanges()
657
        if ($update_tagsChanges);
267 dpurdie 658
 
659
    #
1348 dpurdie 660
    #   If we need to create a branch then
661
    #       Copy the WS to URL
662
    #       Switch to new URL
663
    #   The bulk of the copy will be done on the server-side
664
    #   and not over the network. This is  good.
665
    #
2029 dpurdie 666
    if ( $opt_mkbranch )
1348 dpurdie 667
    {
668
        #
669
        #   Branch does not exist
670
        #   Create it be copying the base view
671
        #
672
        Message ("Creating branch: $opt_branch");
673
        my $branch_tag = $svnSession->SvnCopy (
674
                        'old' => $workSpace,
675
                        'new' => $branch,
676
                        'comment' => 'Created by Jats SvnRelease branch request',
677
                        'replace' => 0 );
678
 
679
        Verbose ("Switching to new branch: $opt_branch");
680
        $branch_tag = SvnPath2Url($branch_tag);
681
        $svnSession->SvnSwitch ($branch_tag,
682
                               $workSpace,
683
                               '--NoPrint' );
684
    }
685
 
686
    #
267 dpurdie 687
    #   Create a local package archive
688
    #   May be needed for multipackage builds and it will prevent JATS from
689
    #   finding any outside the view
690
    #
691
    mkdir ( $VIEWDIR . '/local_dpkg_archive')
692
        unless ($GBE_SANDBOX);
1348 dpurdie 693
 
694
    #
695
    #   Display messages AFTER the extraction text
1357 dpurdie 696
    #   Will ensure that the user has a chance to see them
1348 dpurdie 697
    #
698
    Warning(@messageText );
699
 
267 dpurdie 700
}
701
 
285 dpurdie 702
#   Place a tag-file in the user-specified source path
703
#   This will be used by the build-tool to locate the 'source-path' of the
704
#   view, primarily for determining metrics.
267 dpurdie 705
#
1348 dpurdie 706
#   Calculate where the dynamic view will be
285 dpurdie 707
#   This differ between UNIX/WINDOWS
708
#
351 dpurdie 709
if ( $GBE_ABT)
285 dpurdie 710
{
1348 dpurdie 711
    Message("Create Build tagfile");
712
    TouchFile ( "$workSpace/.jats.packageroot" )
713
        if ( -d $workSpace )
285 dpurdie 714
}
715
 
716
#
267 dpurdie 717
#   Locate the JATS build files within the populated view
718
#
1348 dpurdie 719
chdir ($VIEWDIR) or Error("Cannot chdir to $VIEWDIR");
267 dpurdie 720
Message( "Locating build files");
721
 
722
my $bscanner = BuildFileScanner( $VIEWDIR, 'build.pl', '--LocateAll' );
723
$bscanner->scan();
724
my @build_list = $bscanner->getInfo();
725
foreach my $be ( @build_list )
726
{
1348 dpurdie 727
    Message(DisplayPath ("Build file: $be->{dir} Name: $be->{file}"));
267 dpurdie 728
}
729
 
730
#
731
#   If we are extracting the view then we are done
732
#   Display useful information for the user
733
#
734
if ( $opt_extract )
735
{
736
    Message  DisplayPath "View in: $VIEWDIR";
737
    Warning ("No build files found" )   if ( $#build_list < 0 );
738
    Warning( "Multiple build files found" )if ( $#build_list > 0 );
739
    Message ("Not all labels are pegged") if ( @label_not_pegged  );
740
    Message ("All labels are pegged") unless ( @label_not_pegged  );
741
    Message ("Badly formed label name" ) if ( $bad_label_name );
1348 dpurdie 742
    Message ("Development Mode: $opt_devModeStr") if ( $opt_devModeStr );
267 dpurdie 743
    Message ("Development Sandbox") if ( $GBE_SANDBOX );
1349 dpurdie 744
    Message ("Cannot release from this workspace") if ($noReleaseWs);
267 dpurdie 745
 
746
    exit 0;
747
}
748
 
749
Error ("No build files found")  if ( $#build_list < 0 );
750
 
751
#
752
#   Determine the list of builds to perform
753
#   Ensure that the user-requested build files are present
754
#
755
#   The user specifies the build file, via the mangled package name
756
#   This is package_name . project extension (daf_utils.cr)
757
#
758
if ( $#opt_build  >= 0)
759
{
760
    Verbose( "Check and locate the build files");
761
    @build_list = ();
762
    foreach my $bentry ( @opt_build )
763
    {
764
        if ($bscanner->match( $bentry) )
765
        {
766
            UniquePush (\@build_list, $bscanner->getMatchList() );
767
            Verbose ("Found: $bentry");
768
        }
769
        else
770
        {
771
            Error ("Cannot locate requested build files for: $bentry")
772
        }
773
    }
774
}
775
 
776
#
777
#   Sanity test if we will transfer the generated package to dpkg_archive
778
#   There are some limits
779
#       1) Must have built from one label
780
#       2) That label must be locked
781
#       3) Only one build file
782
#       4) The view must not have been reused
783
#       5) The view has a branch rule
784
#       6) Cannot release from a sandbox
785
#
786
my @elist;
787
push @elist, "Package built from multiple labels" unless ( $label_count == 1 );
788
push @elist, "Package built from an unpegged label" if ( @label_not_pegged  );
789
push @elist, "Package built with multiple build files" if ( scalar @build_list > 1 );
790
push @elist, "Package from a reused view" if ( $opt_reuse && ! $opt_beta );
791
push @elist, "Package from a development sandbox" if ( $GBE_SANDBOX );
1348 dpurdie 792
push @elist, "Package from a development workspace" if ($noReleaseWs);
267 dpurdie 793
push @elist, "View contains a branch" if ( $opt_branch );
794
push @elist, "User has specified build files" if ( $#opt_build > 0 );
795
push @elist, "Badly formed label name" if ( $bad_label_name );
796
 
797
if ( @elist )
798
{
799
    Warning ("Cannot officially release the package.", @elist);
800
    Error ("Build terminated as it cannot be released") if ($opt_dpkg && ! $opt_beta);
801
}
802
Warning ("Beta Release") if $opt_beta;
803
 
804
#
805
#   Process each of the build files in the specified order
806
#
807
foreach my $be (@build_list)
808
{
809
 
810
    #
811
    #   We need to change to the build directory
812
    #   Moreover we need the local name of the build directory.
813
    #   Windows does not handle a UNC pathname to well (at all)
814
    #
815
    my $build_dir = $be->{dir};
816
    chdir ("$build_dir") or Error( "Cannot chdir to build directory: $build_dir");
817
 
818
    if ( $be->{file} =~ m/^build.pl$/ )
819
    {
820
        Message ("Using JATS: $build_dir");
821
        #
822
        #   Invoke JATS to build the package and make the package
823
        #
824
        my @build_args = qw(--expert --cache);
825
        push @build_args, '--cache' if $opt_cache;
826
 
827
        my $make_type = 'all';
828
        $make_type = 'all_prod'  if ( $opt_prod_build );
829
        $make_type = 'all_debug' if ( $opt_debug_build );
830
 
831
 
832
        JatsCmd('build', @build_args)               and Error("Package did not build");
833
        JatsCmd('make', $make_type, 'NODEPEND=1')   and Error("Package did not make");
834
        JatsCmd('install');
835
 
836
        if ( $opt_runtests )
837
        {
321 dpurdie 838
            JatsCmd('make', 'run_unit_tests')      and Error("Tests did not run correctly");
267 dpurdie 839
        }
840
    }
841
    else
842
    {
843
        #
844
        #   Ant build files
845
        #
846
        my $pname =  $be->{file};
847
        Message ("Using ANT: $build_dir, $pname");
848
        $pname =~ s~depends.xml$~.xml~;
849
        copy($be->{file}, "auto.xml");
850
        JatsCmd('-buildfile', $pname, 'ant', 'build')        and Error("Package did not build");
851
        JatsCmd('-buildfile', $pname, 'ant', 'make_package') and Error("Package did not make_package");
852
    }
853
}
854
 
855
#
856
#   Copy the generated packages
857
#       1) dpkg_archive
858
#       2) Users local directory
859
#
860
foreach my $be (@build_list)
861
{
862
    my $build_dir = $be->{dir};
863
    chdir ("$build_dir") or Error( "Cannot chdir to build directory: $build_dir");
864
    if ( $opt_dpkg )
865
    {
866
        Message ("Using: $build_dir");
279 dpurdie 867
        my @create_opts = "-o";
868
        push @create_opts ,"-m" if ( $opt_merge );
869
        JatsCmd('-here', 'create_dpkg', @create_opts, '-pname', $be->{name}, '-pversion', $be->{version}) and $error++;
267 dpurdie 870
    }
871
 
872
    if ( $opt_copy )
873
    {
874
        Message ("Copy package to $user_cwd");
875
        copy_directory( 'pkg', $user_cwd, '' );
876
    }
877
 
878
    #
879
    #   Test structure of the package
880
    #   Ensure that it has a descpkg file
881
    #   Validate the package name and version
882
    #   More important for ANT projects than JATS as JATS has a sanity test
883
    #
884
    if ( $opt_test )
885
    {
886
        JatsCmd('-here', 'create_dpkg', '-test', '-pname', $be->{name}, '-pversion', $be->{version}) and $error++;
887
    }
888
 
889
}
890
Error ("Package not transferred")
891
    if ( $error );
892
 
1348 dpurdie 893
chdir ($user_cwd) or Error( "Cannot chdir to $user_cwd");
267 dpurdie 894
 
895
#
896
#   Delete the view
897
#
898
if ( ! $opt_reuse && ! $error && ! $opt_keep )
899
{
900
    delete_view();
901
}
902
else
903
{
904
    Message( "View left in: $VIEWDIR" );
905
}
906
 
907
Message ("End program");
908
exit 0;
909
 
910
#-------------------------------------------------------------------------------
911
# Function        : delete_view
912
#
913
# Description     : Delete a view
914
#
915
# Inputs          : None
916
#                   $VIEWDIR - path of the view
917
#
918
# Returns         :
919
#
920
sub delete_view
921
{
922
    my $cofound = 0;
923
    my $uuid;
924
    #
299 dpurdie 925
    #   Simple delete
267 dpurdie 926
    #
299 dpurdie 927
    if ( $opt_extract_files )
267 dpurdie 928
    {
299 dpurdie 929
        if ( -d $VIEWDIR )
930
        {
931
            Message("Remove extracted files: $VIEWDIR");
361 dpurdie 932
            RmDirTree( $VIEWDIR );
299 dpurdie 933
        }
934
    }
935
    else
936
    {
267 dpurdie 937
        #
1348 dpurdie 938
        #   If the view physically exists then attempt to physically remove it
267 dpurdie 939
        #
299 dpurdie 940
        if ( -d $VIEWDIR )
941
        {
942
            #
943
            #   Determine if there are any checked out files in the view
944
            #
945
            Message("Remove the view: $VIEWDIR");
946
            Verbose("Look for checked out files");
267 dpurdie 947
 
948
 
1348 dpurdie 949
            SvnRmView ('path'     => $workSpace,
950
                       'force'    => ($opt_delete > 1) || ($opt_extract > 1),
299 dpurdie 951
                       'modified' => [ 'local_dpkg_archive' ] );
952
        }
2029 dpurdie 953
        Warning ("View was not deleted. Will Delete view directory")
1348 dpurdie 954
            if ( -d $workSpace );
361 dpurdie 955
        RmDirTree( $VIEWDIR ) if $opt_path;
267 dpurdie 956
    }
299 dpurdie 957
 
267 dpurdie 958
    Error ("View was not deleted")
299 dpurdie 959
        if ( -d $VIEWDIR );
267 dpurdie 960
}
961
 
962
#-------------------------------------------------------------------------------
963
# Function        : copy_directory
964
#
965
# Description     : Copy a directory tree
966
#
967
# Inputs          : Source directory
968
#                   Target directory
969
#                   Strip
970
#
971
#                   Should be full pathnames
972
#
973
# Returns         :
974
#
975
my $copy_error;
976
my $copy_count;
977
sub copy_directory
978
{
979
    our ($src_dir, $dest_dir, $strip) = @_;
980
    our $slength = length ($strip);
981
 
982
    #
983
    #   Prevent File::Find from generating warnings
984
    #
985
    no warnings 'File::Find';
986
 
987
 
988
    #
989
    #   Helper routine to copy files
990
    #
991
    sub copy_file_wanted
992
    {
993
        #
994
        #   Do not copy directories
995
        #   Just make the directory entry. May result in empty directories
996
        #
997
        if ( -d $_ )
998
        {
999
            my $tdir = "$dest_dir/" . substr( $File::Find::dir, $slength);
1000
            $tdir .= "/$_";
1001
            File::Path::mkpath( $tdir )
1002
                unless ( -d $tdir);
1003
            return;
1004
        }
1005
 
1006
        #
1007
        #   When used to copy file from within a clearcase dynamic view the
1008
        #   files may not actually exist. This will generate an error later
1348 dpurdie 1009
        #   so check for existence of file file now.
267 dpurdie 1010
        #
1011
        return unless ( -e $_ );
1012
 
1013
        #
1014
        #   Have been chdir'ed to the source directory
1015
        #   when invoked
1016
        #
1017
        my $tdir = "$dest_dir/" . substr( $File::Find::dir, $slength);
1018
        my $tfile = "$tdir/$_";
1019
        my $sfile = "$File::Find::dir/$_";
1020
        Verbose ("Copy: $sfile -> $tfile");
1021
 
1022
        File::Path::mkpath( $tdir )
1023
            unless ( -d $tdir);
1024
 
1025
        unlink ( $tfile )
1026
            if ( -f $tfile );
1027
 
1028
        if( ! File::Copy::copy ( $_ , $tfile ) )
1029
        {
1030
            $copy_error++;
1031
            Message "Error copying $sfile";
1032
        }
1033
        else
1034
        {
1035
            my $perm = (stat $_)[2] & 07777;
1036
            chmod($perm, $tfile);
1037
 
1038
            $copy_count++;
1039
        }
1040
    }
1041
 
1042
    #
1043
    #   Locate all files to copy
1044
    #
1045
    $copy_error = 0;
1046
    $copy_count = 0;
1047
    File::Find::find ( \&copy_file_wanted, $src_dir );
1048
    return $copy_error;
1049
}
1050
 
1051
#-------------------------------------------------------------------------------
1052
# Function        : count_files
1053
#
1054
# Description     : Count files in a workspace
1055
#                   Ignore .svn stuff
1056
#
1057
# Inputs          : Source directory
1058
#
1059
# Returns         :
1060
#
1061
sub count_files
1062
{
1063
    my ($src_dir) = @_;
1064
 
1065
    #
1066
    #   Prevent File::Find from generating warnings
1067
    #
1068
    no warnings 'File::Find';
1069
 
1070
 
1071
    #
1072
    #   Helper routine to copy files
1073
    #
1074
    sub count_file_wanted
1075
    {
1076
        #
1077
        #   Do not count dirs, only files
1078
        #
1079
        return if ( -d $_ );
1080
        $copy_count++;
1081
    }
1082
 
1083
    #
1084
    #   Locate all files
1085
    #
1086
    $copy_count = 0;
1087
    File::Find::find ( \&count_file_wanted, $src_dir );
1088
}
1089
 
1090
 
1091
#-------------------------------------------------------------------------------
1092
# Function        : extract_files_from_view
1093
#
1094
# Description     : This function will
1348 dpurdie 1095
#                       Extract the files from the required source
1096
#                       This is a simple operation under subversion
267 dpurdie 1097
#
1098
#                   Its used in the creation of escrow directories
1099
#
1100
# Inputs          : None
1101
#                   All done via globals
1102
#
1103
# Returns         : 
1104
#
1105
sub extract_files_from_view
1106
{
1107
    #
1108
    #   Determine the target directory for the extracted files
1109
    #       Delete the output subdir
1110
    #       Create the config spec in that directory
1111
    #
1112
    Verbose("Extracting files into $VIEWDIR");
1113
    if ( -d $VIEWDIR )
1114
    {
1115
        Verbose "Delete Directory: $VIEWDIR\n";
361 dpurdie 1116
        RmDirTree( $VIEWDIR );
267 dpurdie 1117
    }
1118
 
1348 dpurdie 1119
    #
1120
    #   Determine URL to extract
1121
    #       work : Same as exact
1122
    #       exact: Use user provided tag
1123
    #              No need to backtrack to the branch and then
1124
    #              Update files
1125
    #
1126
    #       tag:   Don't update build files
1127
    #              This is different normal mode
1128
    #              Perhaps should change to be the same as exact - just extract
1129
    #              the user provided tag
1130
    #
1131
    #       tip:   Don't update build files
1132
    #
1133
    my $view_tag;
1134
    if ( $opt_devMode eq 'tip' ) {
1135
        $view_tag =  $urlDevBranchHead;
1136
    } elsif ( $opt_devMode eq 'tag' ) {
1137
        $view_tag = $initialUrlBranch;
1138
    } else {
1139
        $view_tag = $initialUrl;
1140
    }
267 dpurdie 1141
 
1348 dpurdie 1142
    $svnSession->SvnCo ( $svnSession->FullPath() . '/' . $view_tag,
1143
                        $VIEWDIR,
1356 dpurdie 1144
                        'export' => 1,
2426 dpurdie 1145
                        'escrow' => $opt_escrow,
1356 dpurdie 1146
                        'print' => 0 );
1348 dpurdie 1147
 
267 dpurdie 1148
    #
1149
    #   Count this files in the view
1348 dpurdie 1150
    #   Done so that its clear when we have a empty workspace in escrow extractions
267 dpurdie 1151
    #
1152
    Verbose ("Examine View contents");
1153
    count_files ( $VIEWDIR );
2652 dpurdie 1154
    Error ('ExitCode=10', DisplayPath("View files in: $VIEWDIR, but no files were extracted"))
1155
        unless ($copy_count);
267 dpurdie 1156
    Message ("View files in: $VIEWDIR, Files: $copy_count" );
1348 dpurdie 1157
}
267 dpurdie 1158
 
1348 dpurdie 1159
#-------------------------------------------------------------------------------
1160
# Function        : importTagChanges
1161
#
1162
# Description     : import changes from a 'tag' into the target workspace
1163
#                   Use with a workspace as well as an exported target
1164
#
1165
# Background      :
1166
#   The workspace has been created on the branch from which the tag was taken
1167
#   BUT this may not be the same as the tag because:
1168
#       1) Developer is not respecting the use of tags
1169
#       2) The automated build system will place the rippled build files
1170
#          within the tag.
1171
#   The most effective way that I have found of getting the modified build
1172
#   files into the workspace is to:
1173
#       Parse the log of the tag
1174
#       Determine files that have been modified as a part of the tag
1175
#       export them into the workspace
1176
#
1177
#   If we are creating a workspace that we are about to branch, then
1178
#   we use 'switch' to copy in the new file
1179
#   Otherwise, use a 'co -export'. If we use a switch, then the files
1180
#   that have been switched in cannot be commit if changed as they will
1181
#   be within the 'tags' area.
1182
#
1183
# Inputs          : None
1184
#                   Globals
1185
#
1186
# Returns         : Error code
1187
#
1188
sub importTagChanges
1189
{
1190
    return unless ( $tagLabel );
1349 dpurdie 1191
    my $data = $svnSession->{SavedBackTrack};
1192
    Error ("Internal: importTagChanges expects backtracking to have been performed")
1193
        unless (defined $data);
1194
 
1348 dpurdie 1195
#    DebugDumpData("importTagChanges", $svnSession );
1196
#    DebugDumpData("Data", $data );
1197
 
1198
    #
1199
    #   Process the data from the backtrack log and determine the files
1200
    #   that we need to transfer.
1349 dpurdie 1201
    #       Should only be one - but if the users have been bad
1202
    #       then there may be more.
1348 dpurdie 1203
    #
1356 dpurdie 1204
    if ( $data->{files} )
1348 dpurdie 1205
    {
1356 dpurdie 1206
        foreach my $srcFile ( reverse @{$data->{files}} )
1348 dpurdie 1207
        {
1356 dpurdie 1208
            Verbose("importTagChanges: $srcFile");
1209
            my $sfile = $svnSession->FullPath() . '/' . $srcFile;
1451 dpurdie 1210
 
1211
            #
2489 dpurdie 1212
            #   Calculate path within the repo of the target file
1451 dpurdie 1213
            #
2489 dpurdie 1214
            unless($srcFile =~ m~tags/.*?(/.*)@\d+~)
1215
            {
1216
                #
1217
                #   Only seen this error under a condition where the user
1218
                #   tagged a parent directory. ie:
1219
                #       aaa/bbbb/tags/badTag was a copy of aaa
1220
                #
1221
                Error ("importTagChanges. Unexpected format of filename: $srcFile",
1222
                       "Possible cause: Incorrect tag placement");
1223
            }
1451 dpurdie 1224
            my $tfile = $workSpace . $1;
1225
 
1356 dpurdie 1226
            if ( $opt_branch )
1227
            {
1451 dpurdie 1228
                $svnSession->SvnSwitch ($sfile, $tfile);
1356 dpurdie 1229
            }
1230
            else
1231
            {
1451 dpurdie 1232
                $svnSession->SvnCo ($sfile, $tfile,
1356 dpurdie 1233
                                        'export' => 1,
1234
                                        'force' => 1,
2426 dpurdie 1235
                                        'escrow' => $opt_escrow,
1356 dpurdie 1236
                                        'pretext' => 'Replacing ' );
1237
            }
1348 dpurdie 1238
        }
1239
    }
267 dpurdie 1240
}
1241
 
1242
#-------------------------------------------------------------------------------
1348 dpurdie 1243
# Function        : determineChangedFiles
1244
#
1245
# Description     : Display a list of files that have been changed between
1246
#                   the tagPoint and the head of the branch
1247
#
1248
# Inputs          : Only Globals
1249
#
1250
# Returns         : Will not return if changes are not allowed
1251
#
1252
sub determineChangedFiles
1253
{
1254
    my @msgText;
2028 dpurdie 1255
    my $onlyWarn = ($checkDelta == 1);
267 dpurdie 1256
 
1348 dpurdie 1257
    #
1258
    #   No checking required
1259
    #   Skip the hard bit if running on a build machine
1260
    #
1261
    return unless ( $checkDelta );
2652 dpurdie 1262
    return if ( $onlyWarn && ! $devBranch && ! $tagLabelBranch );
267 dpurdie 1263
 
1348 dpurdie 1264
    Debug ('determineChangedFiles');
1265
#debugDumpRefInfo('determineChangedFiles');
1266
 
1267
    #
1268
    #   Examine the HEAD of the development branch and determine if there
1269
    #   have been any changes since the tag was taken
1270
    #
1271
    #   Determine the Repo Revision for the HEAD of the devBranch
1272
    #
1273
    Error ("Internal: No devBranch calculated") unless ( $devBranch || $tagLabelBranch );
1274
 
1275
    my $basePeg = $tagLabelBranchPeg || $devBranchPeg;
1276
    my $baseBranch = $tagLabelBranch || $devBranch;
1277
    Error ("Internal logic. Expecting tagLabelBranchPeg or devBranchPeg to be defined") unless ( $basePeg );
1278
    Error ("Internal logic. Expecting tagLabelBranch or devBranch to be defined") unless ( $baseBranch );
1279
 
1280
    my $svn_check = NewSessionByUrl ( join( '/', $srcPathPkg, $baseBranch), 1 );
1281
    my $rv = $svn_check->SvnInfo( $svn_check->Full, 'InfoRepo' );
1282
    if ( $rv )
1283
    {
1284
        push (@msgText, "Cannot read information for the head of the development branch",
1285
                        "Branch may not exist: $baseBranch");
2028 dpurdie 1286
        $onlyWarn = 1;
1348 dpurdie 1287
    }
1288
    else
1289
    {
1290
        $devBranchHead = $svn_check->{'InfoRepo'}{'Last Changed Rev'};
1291
        Verbose2("devBranchHead: $devBranchHead");
1292
    #debugDumpRefInfo('Dev Branch Head');
1293
 
1294
 
1295
        #
1296
        #   If the Rev of the HEAD is greater than the point at which we
1297
        #   are interested then changes may have occured. Otherwise we know
1298
        #   that changes cannot have occured
1299
        #
1300
        if ( $devBranchHead <= $basePeg )
1301
        {
1302
            return;
1303
        }
1304
 
1305
        if ( $tagLabelBranchPeg )
1306
        {
1307
            push @msgText,  "Development Branch has changed since Tag was taken",
1308
                            "Head last changed in Rev: $devBranchHead",
1309
                            "Tag traced back to Rev  : $basePeg";
1310
        } else
1311
        {
1312
            push @msgText,  "Development Branch has changed since specified version",
1313
                            "Head last changed in Rev: $devBranchHead",
1314
                            "Specified branch Rev    : $basePeg";
1315
        }
1316
 
1317
 
1318
        my $diffBase = $svn_check->FullPath() . '/' . $baseBranch;
1319
        $svn_check->{tmp}{path_length} = length($diffBase);
1320
        $svn_check->{tmp}{count}  = 0;
1321
        @{$svn_check->{tmp}{files}}  = ();
1322
 
1323
        $rv = $svn_check->SvnCmd ( 'diff', '--summarize',
1324
                                   $diffBase,
1325
                                   '--revision', $basePeg . ':HEAD',
1326
                                   {
1327
                                        'process' => \&ProcessDiff,
1328
                                        'credentials' => 1,
1329
                                        'nosavedata' => 1,
1330
                                   }
1331
                                );
1332
        #
1333
        #   Prepare message to be displayed
1334
        #   Prepend text to the list of files
1335
        #
1336
 
1337
        $rv = $svn_check->{tmp}{count};
1338
        return unless ( $rv );
1339
        push (@msgText, "No files changed") unless ( $rv );
1340
        push (@msgText, "Changed file count: $rv") if ( $rv );
1341
        push (@msgText, "More than 10 files have changed. First 10 are:") if ( $rv > 10);
1342
        push (@msgText, @{$svn_check->{tmp}{files}} );
1343
    }
1344
 
2028 dpurdie 1345
    if ($onlyWarn) {
1348 dpurdie 1346
        push @messageText, @msgText;
1347
    } else {
1348
        Error ( @msgText );
1349
    }
1350
}
1351
 
1352
sub ProcessDiff
1353
{
1354
    my $self = shift;
1355
    my $data = shift;
1356
 
1357
    #
1358
    #   Extract filename from line
1359
    #       First 8 chars are status
1360
    #       Remove WS path too
1361
    #
1362
    my $path_length = $self->{tmp}{path_length} + 1 + 8;
1363
    if ( length $data >= $path_length )
1364
    {
1365
        my $file = substr ( $data, $path_length );
1366
        push @{$self->{tmp}{files}}, '  Changed: ' .  $file
1367
            if ( $self->{tmp}{count}++ < 10 );
1368
    }
1369
 
1370
    return 0;
1371
}
1372
 
267 dpurdie 1373
#-------------------------------------------------------------------------------
1348 dpurdie 1374
# Function        : parseSubversionRef
1375
#
1376
# Description     : Parse the user-provided Subversion Ref
1377
#
1378
#                   Convert label with embedded VCS information into a 'normal' form.
1379
#                   Form:
1380
#                       SVN::<SourcePath>::<Label>
1381
#                       SVN::<SourcePath>::<Peg>
1382
#                   
1383
#                   Allow optional 'SVN::' prefix
1384
#                   Allow Full or Symbolic URL
1385
#                       [SVN::]<SourcePath>::<Label>
1386
#                       [SVN::]<SourcePath>::<Peg>
1387
#                       [SVN::]<URL>
1388
#
1389
# Inputs          : $opt_spec               - User Provided Ref
1390
#
1391
# Returns         : Will not retirn on gross error
1392
#                   Values return in global variables
1393
#
1394
sub parseSubversionRef
1395
{
1396
    my ($opt_spec) = @_;
1397
 
1398
    $opt_spec =~ s~^SVN::~~;
1399
    if ( $opt_spec =~ m~(.+)::(.+)~ )
1400
    {
1401
        my $sourcePath = $1;
1402
        my $label = $2;
1403
        $urlType = 'jats';
1404
 
1405
        #
1406
        #   Sanity test of sourcePath
1407
        #
1408
        Error ("Invalid use of a peg: $opt_spec[0]")
1409
            if ( $sourcePath =~ m~\@\d+$~ );
1410
 
1411
        #
1412
        #   Remove anything after a ttb (truck, tags, branch) element
1413
        #   This will be the root of the package within the repo
1414
        #
1415
        if (  $sourcePath =~ m~(.*)/((tags|branches|trunk)(/|$)(.*))~ )
1416
        {
1417
            Error ("Source Path has insufficient items")
1418
                if ( $1 eq '' );
1419
 
1420
            Error ("SourcePath contains invalid items after '$3': '$5'")
1421
                if ( ($3 eq 'tags' || $3 eq 'trunk') && $5 ne '' );
1422
 
1423
            Error ("SourcePath must contain items after 'branches'")
1424
                if ( $3 eq 'branches' && $5 eq '');
1425
 
1426
            $srcPathPkg = $1;
1427
            $ttbType = $3;
1428
            $devBranch = $3;
1429
            $devBranch .= '/' . $5 if ( $5 ne '' );
1430
        }
1431
        else
1432
        {
1433
            Error ("Source Path does not contain tags or trunk or branches component");
1434
        }
1435
 
1436
        #
1437
        #   Pull apart the 2nd argument
1438
        #   May be a raw peg - on the development branch
1439
        #   May be a tag and a peg
1440
        #
1441
        $initialUrl = $srcPathPkg;
1442
        if ( $label =~ m~^@*(\d+)$~ )
1443
        {
1444
            # Full numeric label - is a peg on the development branch
1445
            $devBranchPeg = $1;
1446
            $initialUrl .= '/' . $devBranch . '@' . $devBranchPeg;
1447
        }
1448
        elsif ( $label =~ m~^([^@]+)@(\d+)$~ )
1449
        {
1450
            $tagLabel = 'tags/' . $1;
1451
            $tagPeg = $2;
1452
            $initialUrl .= '/tags/' . $label;
1453
 
1454
        }
1455
        elsif ( $label !~ m~@~ )
1456
        {
1457
            $tagLabel = 'tags/' . $label;
1458
            $initialUrl .= '/tags/' . $label;
1459
        }
1460
        else
1461
        {
1462
            Error ("Subversion Tag badly formed: $label");
1463
        }
1464
    } elsif ($opt_spec =~ m~::~) {
1465
        Error ("Badly formed Subversion Reference: $opt_spec[0]");
1466
 
1467
    }
1468
    else
1469
    {
1470
        # Have a full URL and not a JATS enhanced spec
1471
        # Cannot determine the development branch and the tag
1472
        #
1473
        $urlType = 'url';
1474
        $initialUrl = $opt_spec;
1475
 
1476
        # Extact any peg
1477
        my $peg;
1478
        if ( $opt_spec =~ m~(.*)@(\d+)$~ )
1479
        {
1480
            $opt_spec = $1;
1481
            $peg = $2;
1482
        }
1483
 
1484
        if (  $opt_spec =~ m~(.*)/((tags|branches|trunk)(/|$)(.*))~ )
1485
        {
1486
            Error ("Subversion URL has insufficient items")
1487
                if ( $1 eq '' );
1488
            $srcPathPkg = $1;
1489
            $ttbType = $3;
1490
 
1491
            if ( $ttbType eq 'trunk' ) {
1492
                Error ("Subversion URL must NOT contain items after '$ttbType'")
1493
                    if ( $5 ne '' );
1494
                $devBranch = $2;
1495
                $devBranchPeg = $peg;
1496
 
1497
            } elsif ( $ttbType eq 'tags' ) {
1498
                Error ("Subversion URL must contain items after '$ttbType'")
1499
                    unless ( $5 ne '' );
1500
                $tagLabel = $2;
1501
                $tagPeg = $peg;
1502
 
1503
            } else {
1504
                Error ("Subversion URL must contain items after '$ttbType'")
1505
                    unless ( $5 ne '' );
1506
                $devBranch = $2;
1507
                $devBranchPeg = $peg;
1508
            }
1509
        }
1510
        else
1511
        {
1512
            Error ("Subversion URL does not contain tags or trunk or branches component");
1513
        }
1514
    }
1515
    #debugDumpRefInfo('First Parse');
1516
}
1517
 
1518
#-------------------------------------------------------------------------------
1454 dpurdie 1519
# Function        : calcViewName
1520
#
1521
# Description     : Calculate a nice name for the view
1522
#                   Try to base the name on the tag
1523
#
1524
#                   If the URL looks like a TTB then we can make some guesses
1525
#                   as to the package name and version.
1526
#
1527
#                   Add indication for the Dev Mode
1528
#                   Add indication for a branch
1529
 
1530
#
1531
# Inputs          : Nothing
1532
#
1533
# Returns         : A nice View name
1534
#                   Will not retirn on error
1535
#
1536
sub calcViewName
1537
{
1538
    #
1539
    #   Use the user provided view name if its valid
1540
    #
1541
    if ( $opt_viewname )
1542
    {
1543
        Error ("View Name contains invalid characters" )
1544
            unless ( $opt_viewname =~ m~^[0-9a-z]([-.:0-9a-z_]*[0-9a-z])?$~i );
1545
        return $opt_viewname ;
1546
    }
1547
 
1548
    #
1549
    #   Create a view name based on the provide URL or SVN Reference
1550
    #
1551
    my $version;
1552
    my $name = $srcPathPkg;
1553
    $name =~ s~.*/~~;
1554
 
1555
    if ( $tagLabel )
1556
    {
1557
        $version = $tagLabel;
1558
        $version =~ s~.*/~~;
1559
        $version = $1 if ( $version =~ m~^${name}_(.*)~ );
1560
    }
1561
    elsif ( $devBranch )
1562
    {
1563
        $version = $devBranch;
1564
        $version =~ s~.*/~~;
1565
    }
1566
 
1567
    if ( $version && $name )
1568
    {
1569
        $opt_viewname = join( '_', $name, $version);
1570
    }
1571
    elsif ( $svnSession->Type )
1572
    {
1573
        $opt_viewname = $svnSession->Path;
1574
        $opt_viewname .= '_' . ($svnSession->Version || 'trunk') unless $opt_branch;
1575
 
1576
        #
1577
        #   Tags and Branches 'should' include the package name
1578
        #   This will lead to a duplication of the package name
1579
        #   ie: aaaaa/package/tags/package_version
1580
        #   Attempt to remove these
1581
        #
1582
        if ( $opt_viewname =~ s~[_/]([\-.:0-9a-zA-Z]+)_\1_~_$1_~ )
1583
        {
1584
            Verbose ("Removed duplicate package name: $1 from $opt_viewname");
1585
        }
1586
    }
1587
    else
1588
    {
1589
        $opt_viewname = $svnSession->Path;
1590
        $bad_label_name = 1;
1591
    }
1592
 
1593
    #
1594
    #   Append the peg if provided
1595
    #   Not if creating a 'tip' as its a bit meaningless
1596
    #
1597
    if ( my $peg = $tagPeg || $devBranchPeg )
1598
    {
1599
        unless( $opt_devMode eq 'tip' )
1600
        {
1601
            $opt_viewname .= '_' . $peg;
1602
        }
1603
    }
1604
 
1605
    #
1606
    #   Append information to indicate the exact type of the WorkSpace
1607
    #   Normally mutually exclusive
1608
    #
1609
    $opt_viewname .= '_Tip' if ( $opt_devMode eq 'tip' );
1610
    $opt_viewname .= '_Tag' if ( $opt_devMode eq 'tag' );
1611
    $opt_viewname .= '_Exact' if ( $opt_devMode eq 'exact' );
1612
    $opt_viewname .= '_' . $opt_branch if ( $opt_branch );
1613
 
1614
    #
1615
    #   Create a simple dir name
1616
    #       Remove path sep characters and replace with _
1617
    #       Remove Peg marker (@) as this breaks svn
1618
    #       Replace multiple _ with a single _
1619
    #       Remove trailing _ - caused by URL with a trailing /
1620
    #
1621
    $opt_viewname =~ s~[^\-.:0-9a-zA-Z_]~_~g;
1622
    $opt_viewname =~ tr~_~_~s;
1623
    $opt_viewname =~ s~_+$~~;
1624
    return $opt_viewname;
1625
}
1626
 
1627
#-------------------------------------------------------------------------------
1348 dpurdie 1628
# Function        : debugDumpRefInfo
1629
#
1630
# Description     : Dump the current Ref Information
1631
#
1632
# Inputs          : $text
1633
#
1634
# Returns         : 
1635
#
1636
sub debugDumpRefInfo
1637
{
1638
    Verbose0 ('-' x 40);
1639
    Verbose0 ('debugDumpRefInfo:' , @_ );
1640
    Verbose0 ('ttbType           :', $ttbType);
1641
    Verbose0 ('urlType           :', $urlType);
1642
    Verbose0 ('Base              :', $svnSession->FullPath() ) if $svnSession;
1643
    Verbose0 ('initialUrl        :', $initialUrl);
1644
    Verbose0 ('srcPathPkg        :', $srcPathPkg);
1645
    Verbose0 ('devBranch         :', $devBranch);
1646
    Verbose0 ('devBranchPeg      :', $devBranchPeg);
1647
    Verbose0 ('devBranchHead     :', $devBranchHead);
1648
    Verbose0 ('tagLabel          :', $tagLabel);
1649
    Verbose0 ('tagPeg            :', $tagPeg);
1650
    Verbose0 ('tagLabelBranch    :', $tagLabelBranch);
1651
    Verbose0 ('tagLabelBranchPeg :', $tagLabelBranchPeg);
1652
}
1653
 
1654
#-------------------------------------------------------------------------------
1655
 
1656
 
1657
#-------------------------------------------------------------------------------
267 dpurdie 1658
#   Documentation
1659
#
1660
 
1661
=pod
1662
 
361 dpurdie 1663
=for htmltoc    GENERAL::Subversion::
1664
 
267 dpurdie 1665
=head1 NAME
1666
 
1667
jats_svnrelease - Build a package given a SubVersion label
1668
 
1669
=head1 SYNOPSIS
1670
 
1671
  jats svnrelease [options] [-label=]label
1672
 
1673
 Options:
1674
    -help              - brief help message
1675
    -help -help        - Detailed help message
1676
    -man               - Full documentation
1677
    -label=xxx         - Subversion label
1678
    -spec=xxx          - Same as -label=xxx
1679
    -path=xxx          - Source Path
1680
    -view=xxx          - Modify the name of the created view
1681
    -build=xxx         - Package Name to build
1682
    -root=xxx          - Root directory for generated view
2029 dpurdie 1683
    -[mk]branch=xxx    - Will create/use a branch
1348 dpurdie 1684
    -tag=xxx           - Compatibility. Not used
267 dpurdie 1685
    -extract           - Extract the view and exit
1686
    -extractfiles      - Extract files, without a view
1348 dpurdie 1687
    -devMode=xxx       - Create Workspace suitable for development.(Tip,Tag,...)
267 dpurdie 1688
    -cache             - Refresh local dpkg_archive cache
361 dpurdie 1689
    -delete[=n]        - Remove any existing view and exit
267 dpurdie 1690
    -debugOnly         - Make only the debug version
1691
    -prodOnly          - Make only the production version
1692
    -[no]dpkg          - Transfer package into dpkg_archive
1693
    -[no]copy          - Transfer pkg directory to the current user directory
1694
    -[no]reuse         - Reuse the view
1695
    -[no]test          - Test package build. Implies nocopy and nodpkg
1696
    -[no]keep          - Keep the view after the build
1697
    -[no]beta          - Release a beta package
1698
    -[no]merge         - Merge packages into dpkg_archive
1699
    -[no]runtests      - Run units tests. Default is runtests
1348 dpurdie 1700
    -[no]prefix        - Suppress user prefix in view name. Default prefix is USER
267 dpurdie 1701
 
1702
=head1 OPTIONS
1703
 
1704
=over 8
1705
 
1706
=item B<-help>
1707
 
1708
Print a brief help message and exits.
1709
 
1710
=item B<-help -help>
1711
 
1712
Print a detailed help message with an explanation for each option.
1713
 
1714
=item B<-man>
1715
 
1716
Prints the manual page and exits.
1717
 
1718
=item B<-label> or B<-spec>
1719
 
1348 dpurdie 1720
The Subversion label to use as the base for the workspace. The utility will
1721
accept the following forms of label identifier, each with an optional 'SVN::' prefix.
267 dpurdie 1722
 
1348 dpurdie 1723
=over 4
267 dpurdie 1724
 
1348 dpurdie 1725
=item Full URL
1726
 
1727
This form is identified by the complete lack of the '::' subfield delimiter. The
1728
URL is used as provided. It is not modified.
1729
 
1730
 Eg: AUPERASVN01/DPG_SWBASE/daf_utils_math/tags/daf_utils_math_3.2.1@12345
1731
 Eg: https://auperasvn01.aupera.erggroup.com/svn/DPG_SWBASE/daf_utils_math/tags/daf_utils_math_3.2.1@12345
1732
 
1733
 
1734
=item SourcePath::Tag
1735
 
1736
The SourcePath component is used to calculate the root of the package directory.
1737
The source path is then caclulated assuming that the 'Tag' exists within a
1738
'/tags' subdirectory of the root of the package.
1739
 
1740
This is the form preferred by Release Manager and the VIX build system.
1741
 
1742
 Eg: AUPERASVN01/DPG_SWBASE/daf_utils_math/trunk::daf_utils_math_3.2.1@12345
1743
 
1744
=item SourcePath::Peg
1745
 
1746
A special case of of the 'SourcePath::Tag' form is invoked if the 'Tag' component
1747
is numeric. It will be treated as a peg of the Base Path.
1748
 
1749
 Eg: AUPERASVN01/DPG_SWBASE/daf_utils_math/trunk::12345
1750
 
1751
=back
1752
 
267 dpurdie 1753
=item B<-view name>
1754
 
1755
Specified an alternate view name and tag to be used. This option does not provide the
1756
full name of the view.
1757
 
361 dpurdie 1758
The view path will be: "${USER}_${NAME}"
267 dpurdie 1759
 
1760
The default "NAME" is the first label specified with the repository and tag removed.
1761
 
1762
If the user provides a view "name" that is prefixed with their user name
1763
('${USER}_'), then the username will be stripped of for internal processing.
1764
This allows a user to provide a view path when deleting a view.
1765
 
1766
=item B<-path=xxx>
1767
 
1768
Specifies the source path to the root of the extracted file tree. This option is
1348 dpurdie 1769
not mandatory and is only used to maintain toolset compatibility with other
267 dpurdie 1770
,similar, tools.
1771
 
1772
If provided, then the Workspace will be created within the named subdirectory
1773
tree within the base of the view.
1774
 
1775
=item B<-build=xxx>
1776
 
1777
This option allows the user to specify the packages to be built and the
1778
order in which the packages are to be built.
1779
This is useful if the extracted view contains multiple build files
1780
 
1781
This option may be used multiple times.
1782
 
1783
There are two forms in which the build target can be specified. It can be
1348 dpurdie 1784
specified as a full package name and version, or as a package name and the
267 dpurdie 1785
project suffix.
1786
 
1787
By default the program will assume that there is only one build file in the
1788
view and will not build if multiple files are present, unless the package to be
1789
built can be resolved.
1790
 
1791
The location mechanism operates for both JATS and ANT build files.
1792
 
1793
Example: -build=jats-api.1.0.0000.cr
1794
 
1795
This will locate the build file that builds version 1.0.0000.cr of the jats-api
1796
package. The version numbers must match exactly.
1797
 
1798
Example: -build=jats-api.cr -build=jats-lib.cr
1799
 
1800
This will located the build files that build the jats_api (cr) package and the
1801
jats-lib (cr) package. The version of the packages will not be considered.
1802
 
1803
=item B<-root=xxx>
1804
 
1805
This option allows the location of the generated view to be specified on the
1348 dpurdie 1806
command line. It overrides the value of GBE_VIEWBASE.
267 dpurdie 1807
 
1348 dpurdie 1808
If the command is invoked within a development sandbox, then the default
267 dpurdie 1809
location will be the root directory of the development sandbox.
1810
 
2029 dpurdie 1811
=item B<-mkbranch=xxx>
267 dpurdie 1812
 
1270 dpurdie 1813
This option will create a workspace associated with a branch within the
1814
repository. This is intended to facilitate the maintenance of existing packages
2029 dpurdie 1815
and the creation of project or development branches.
267 dpurdie 1816
 
2029 dpurdie 1817
The named branch must not exist. It is an error for the branch to exist.
267 dpurdie 1818
 
2029 dpurdie 1819
This tool will copy the specified source version to the branch, create a
1820
workspace based on the branch and then switch to the branch.
267 dpurdie 1821
 
2029 dpurdie 1822
This option is intended to create a development thread, for project or private
1823
use.
1824
 
383 dpurdie 1825
A branch name of TIMESTAMP will be treated in special manner. The name will be
1826
replaced with a unique name based on the users name and the current date time.
1827
 
2029 dpurdie 1828
=item B<-branch=xxx>
1829
 
1830
This option will create a workspace associated with a branch within the
1831
repository. This is intended to facilitate the maintenance of existing packages
1832
and the creation of project or development branches in a manner similar to
1833
ClearCase.
1834
 
1835
The named branch must exist. It is an error for the branch to not exist.
1836
 
1837
If the named branch does exist, then this tool will create a workspace based
1838
on the head of the branch.
1839
 
1840
This option is intended to extract the tip of a development thread.
1841
 
351 dpurdie 1842
=item B<-tag=text>
1843
 
1844
This option is not used.
1348 dpurdie 1845
It is present to maintain compatibility with the buildtool interface.
351 dpurdie 1846
 
267 dpurdie 1847
=item B<-extract>
1848
 
1849
With this option the view is created and the left in place. The user may then
1850
access the files within the view. The view should not be used for a
1851
production release.
1852
 
1853
=item B<-extractfiles>
1854
 
1855
With this option the utility will create a dynamic view and transfer files from
1348 dpurdie 1856
the view to the user's target. The dynamic view is then removed.
267 dpurdie 1857
 
1858
This command is intended to simplify the process of creating an escrow.
1859
 
1348 dpurdie 1860
=item B<-devMode=mode>
1861
 
1862
This option controls the exact form of the Workspace create. The svnRelease
1863
command supports the following modes (default is working):
1864
 
1865
=over 4
1866
 
1867
=item   Tag or TagPoint
1868
 
1869
The workspace will contain the point on the packages development branch from
1870
which the specified tag was copied.
1871
 
1872
The extraction process will highlight file differences between the specified tag
1873
and the tip. If any differences are found then these will be treated as an error.
1874
 
1875
The user B<should> resolve this error by selecting, in Release Manager, a
1876
version of the package based on the tip of the Development Branch.
1877
 
1878
This is the preferred Development Mode for working on a package as it provides
1879
checks to ensure that the Meta Data held in Release Manager is consistient.
1880
 
1881
=item   Work or Working
1882
 
1883
The workspace will contain the point on the packages development branch from
1884
which the specified tag was copied.
1885
 
1886
The extraction process will highlight file differences between the specified tag
1887
and the tip of the Development Branch. Unlike the 'Tag' Mode, such differences
1888
are not treated as an error.
1889
 
1890
This mode of WorkSpace has several features and constraints:
1891
 
1892
=over 4
1893
 
1894
=item *
1895
 
1896
The build files from the 'tagged' version will be transferred into the
1897
WorkSpace. These will be seen as modified files.
1898
 
1899
=item *
1900
 
1901
This style of workspace can be converted into a 'Tip' style through the use of the
1902
Subversion 'update' command.
1903
 
1904
=item *
1905
 
1906
If there have been changes to the Development Branch, then it not be possible to
1907
'commit' the workspace. It may need to be branched first.
1908
 
1909
=back
1910
 
1911
=item Tip or BranchTip
1912
 
1913
The workspace will contain the 'tip' of the Packages Development Branch.
1914
 
1915
The extraction process will highlight file differences between the specified tag
1916
and the tip.
1917
 
1918
=item Exact
1919
 
1920
The workspace will be directly based on the Tag or URL provided by the user.
1921
 
1922
The resultant workspace may not be suitable for development.
1923
 
1924
The extraction process will highlight file differences between the specified tag
1925
and the tip of any associated Development Branch.
1926
 
1927
=back
1928
 
1929
The four extraction points are shouwn in the following image:
1930
 
1931
     /branches/...    /tags/...
1932
            v            v
1933
            |
1934
        +---+---+
1935
  [Tag] | Work  |    +-------+
1936
        +---+---+----+ Exact |
1937
            |        +-------+
1938
        +---+---+
1939
        |       |
1940
        +---+---+
1941
            |
1942
        +---+---+
1943
        |  Tip  |
1944
        +---+---+
1945
 
267 dpurdie 1946
=item B<-cache>
1947
 
1948
Forces external packages to be placed in the local dpkg_archive cache.
1949
 
1950
The normal operation is to copy the packages, only if they do not already exist
1951
in the local cache. This option may be used to ensure that the local copy is
1952
correct and up to date.
1953
 
361 dpurdie 1954
=item B<-delete[=level]>
267 dpurdie 1955
 
1956
Delete the view used by the program, if it exists. This option may be used to
1957
cleanup after an error.
1958
 
361 dpurdie 1959
The default 'level' is 1.
267 dpurdie 1960
 
361 dpurdie 1961
If the delete level is 1, then ensure that no files are open in the view and
1962
that the users current working directory is not in the view as these will
1963
prevent the view from being deleted.
1964
 
1965
If the delete level is greater than one, then the view will be deleted, even
1966
if there are checkout out files.
1967
 
267 dpurdie 1968
=item B<-debugOnly>
1969
 
1970
Make only the debug version of the package. The default it to create both the
1971
debug and production version of the package. The type of build may be  further
1972
limited by options within the package.
1973
 
1974
=item B<-prodOnly>
1975
 
1976
Make only the production version of the package. The default it to create both the
1977
debug and production version of the package. The type of build may be  further
1978
limited by options within the package.
1979
 
1980
=item B<-[no]dpkg>
1981
 
1982
Copy the generated package into dpkg_archive. This is the default mode of
1983
operation.
1984
 
1985
=item B<-[no]copy>
1986
 
1987
Copy the built "pkg" directory to the users current directory. The entire
1988
"pkg" subdirectory includes the full package named directory for the package
1989
that has been built.
1990
 
1991
=item B<-[no]reuse>
1992
 
1993
This flag allows the view created by the program to be re-used.
1994
 
1995
=over 8
1996
 
361 dpurdie 1997
=item *
267 dpurdie 1998
 
361 dpurdie 1999
The view is not deleted before being populated.
267 dpurdie 2000
 
361 dpurdie 2001
=item *
267 dpurdie 2002
 
361 dpurdie 2003
The view will not be populated if it does exist.
2004
 
2005
=item *
2006
 
2007
The view will not be deleted at the end the process.
2008
 
267 dpurdie 2009
=back
2010
 
2011
This option is useful for debugging a build process.
2012
 
2013
=item B<-[no]test>
2014
 
2015
Test the building of the package. This option implies "nocopy" and "nodpkg".
2016
 
2017
=item B<-[no]keep>
2018
 
361 dpurdie 2019
Keep the workspace after the build. The default option is "nokeep"
267 dpurdie 2020
 
2021
This option is different to the "reuse" in that the view will be deleted, if
2022
it exists, before the build, but will be retained at the completion of the
2023
process. The user may then manually extract the created package.
2024
 
2025
The view may be deleted with the the "delete" option; taking care to ensure that
2026
no files are open in the view and that the users current working directory is
2027
not in the view.
2028
 
2029
=item B<-[no]beta>
2030
 
2031
This option overrides many of the package release tests to allow a beta package
2032
to be released.
2033
 
2034
=item B<-[no]merge>
2035
 
2036
This option will merge packages being built on multiple machines into
2037
dpkg_archive. By default, if a package already exists in the archive it will be
2038
deleted and replaced. With this option the package will be merged. The merge
2039
process does not over write files found in the archive.
2040
 
2041
=item B<-[no]runtests>
2042
 
2043
This option will allow the suppression of the running of the unit tests included
2044
with the component. By default the tests are run. This can be suppressed
2045
without affecting the release process.
2046
 
2047
=back
2048
 
2049
=head1 DESCRIPTION
2050
 
2051
This program is the primary tool for the creation, recreation and release of
1270 dpurdie 2052
packages within the B<VIX> build environment, although the program can perform a
267 dpurdie 2053
number of very useful operations required during normal development and
2054
maintenance.
2055
 
2056
This program will build a system containing one or more inter-related build
2057
files using the JATS build tools.
2058
 
2059
In normal operation the program will:
2060
 
2061
=over 8
2062
 
2063
=item Remove Workspace
2064
 
2065
Remove any existing workspace of the same name. The workspace will not be
2066
removed if it contains checked-out files.
2067
 
2068
The workspace removal may fail if there are any files B<open> within the view or if
2069
any shell has a subdirectory of the view set as a B<current working directory>.
2070
 
2071
=item Create the workspace
2072
 
2073
Create a workspace to contain the files described by the Subversion
2074
label being processed.
2075
 
2076
=item Populate the workspace
2077
 
2078
Loads files into the workspace.
2079
 
2080
I<Note:> If the workspace files are simply being extracted, then this is the end
2081
of the program. The extracted workspace is left in place.
2082
 
2083
=item Sanity Test
2084
 
2085
If the build is being used as a release into dpkg_archive then
2086
various tests are performed to ensure the repeatability of the view and the
2087
build. These tests include:
2088
 
2089
=over 8
2090
 
361 dpurdie 2091
=item   *
267 dpurdie 2092
 
361 dpurdie 2093
The view must be constructed from one label
267 dpurdie 2094
 
361 dpurdie 2095
=item   *
267 dpurdie 2096
 
361 dpurdie 2097
That label must be pegged
267 dpurdie 2098
 
361 dpurdie 2099
=item   *
2100
 
2101
The labelled view must contain exactly one build file
2102
 
2103
=item   *
2104
 
2105
The view cannot have been re-used.
2106
 
267 dpurdie 2107
=back
2108
 
2109
=item Locate build files
2110
 
2111
Locate the build file within the view.
2112
 
2113
It is an error to have multiple build files within the workspace, unless the
2114
B<-build> option is used. By default, only one package will be built.
2115
 
2116
=item Package the results
2117
 
2118
Use JATS to build and make the package.
2119
 
2120
The resultant package may be copied to a numbers of locations. These include
2121
 
2122
=over 8
2123
 
2124
=item 1
2125
 
2126
The master dpkg_archive as an official release. This is the default operation.
2127
 
2128
=item 2
2129
 
2130
The users current directory. The package directory from the built package is
2131
copied locally. The "pkg" directory is copied. This is only performed with the
2132
B<-copy> option.
2133
 
2134
=back
2135
 
2136
=item Delete the workspace
2137
 
2138
Delete the workspace and all related files.
2139
 
2140
The workspace will not be deleted if an error was detected in the build process, or
2141
the "reuse" or "keep" options are present.
2142
 
2143
=back
2144
 
2145
=cut
2146