Subversion Repositories DevTools

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
267 dpurdie 1
########################################################################
2
# Copyright (C) 1998-2008 ERG Limited, All rights reserved
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
#
20
# Notes         : A lot of this code is common to jats_ccrelease.pl
21
#                 Will need to refactor if both are to be used
22
#
23
#......................................................................#
24
 
25
require 5.006_001;
26
use strict;
27
use warnings;
28
use JatsError;
29
use JatsSystem;
30
use FileUtils;
31
use JatsBuildFiles;
32
use ArrayHashUtils;
33
use JatsSvn;
34
 
35
use Pod::Usage;                             # required for help support
36
use Getopt::Long;
37
use File::Find;
38
use File::Copy;
39
use File::Path;
40
use Cwd;
41
 
42
my $VERSION = "1.0.0";                      # Update this
43
 
44
#
45
#   Options
46
#
47
my $opt_debug   = $ENV{'GBE_DEBUG'};        # Allow global debug
48
my $opt_verbose = $ENV{'GBE_VERBOSE'};      # Allow global verbose
49
my $opt_help = 0;                           # User help level
50
my @opt_spec;                               # Labels used as a base for the view
51
my $opt_dpkg = 1;                           # Transfer built package to dpkg_archive
52
my $opt_copy = 0;                           # Copy built package to user
53
my $opt_reuse = 0;                          # Re-user view if it exists
54
my $opt_viewname;                           # View Name
55
my $opt_extract;                            # Just create a static view
56
my $opt_extract_files;                      # Just extract files to user - no view
57
my $opt_delete = 0;                         # Just delete the view. 2 to force
58
my @opt_build;                              # build files to use (kludge)
59
my $opt_test;                               # Test the build process - no copy
60
my $opt_cache;                              # Cache external packages
61
my $opt_keep = 0;                           # Keep view if successful
62
my $opt_beta;                               # Create beta release
63
my $opt_merge;                              # Merge release
64
my $opt_path;                               # Path for view spec
65
my $opt_runtests = 1;                       # Run unit tests after build
66
my $opt_branch;                             # Create config spec with branch
67
my $opt_debug_build = 0;                    # Build Debug Only
68
my $opt_prod_build = 0;                     # Build ion Only
69
my $opt_view_root = $ENV{'GBE_VIEWBASE'};   # Root of the view
70
my $opt_prefix = 1;                         # Prefix the view tag with user-name
351 dpurdie 71
my $opt_tag;                                # View tag insert (build or export or user)
341 dpurdie 72
my $bad_label_name = 0;                     # Badly formed label
267 dpurdie 73
 
74
#
75
#   Globals - Provided by the JATS environment
76
#
77
my $USER            = $ENV{'USER'};
78
my $UNIX            = $ENV{'GBE_UNIX'};
79
my $GBE_SANDBOX     = $ENV{'GBE_SANDBOX'};
80
my $GBE_ABT         = $ENV{'GBE_ABT'} || '0';
279 dpurdie 81
my $MACHINENAME     = $ENV{'GBE_HOSTNAME'};
343 dpurdie 82
my $GBE_VIEWBASE    = $ENV{'GBE_VIEWBASE'};   # Root of the view
267 dpurdie 83
 
84
#
85
#   Globals
86
#
343 dpurdie 87
my $VIEWDIR_ROOT;                           # Root of the static view
267 dpurdie 88
my $VIEWDIR;                                # Absolute path to the view
89
my $VIEWPATH;                               # Path relative to clearcase
90
my $user_cwd;
91
my $error = 0;
92
my $label_count = 0;                        # Number of labels to create the view
93
my @label_not_pegged;                       # List of unpegged labels
94
 
95
my $view_prefix     = "${USER}_";
96
 
97
#-------------------------------------------------------------------------------
98
# Function        : Mainline Entry Point
99
#
100
# Description     :
101
#
102
# Inputs          :
103
#
104
 
105
#
106
#   Alter some option defaults if we are creating a view within a sandbox
107
#
108
if ( $GBE_SANDBOX )
109
{
343 dpurdie 110
   $GBE_VIEWBASE = $GBE_SANDBOX;
267 dpurdie 111
   $opt_prefix = 0;
112
}
113
 
114
#
115
#   Parse the user options
116
#
117
my $result = GetOptions (
118
                "help:+"        => \$opt_help,              # flag, multiple use allowed
119
                "manual:3"      => \$opt_help,              # flag
120
                "v|verbose:+"     => \$opt_verbose,           # flag, multiple use allowed
121
                "label=s"       => \@opt_spec,              # Array of build specs
122
                "view=s"        => \$opt_viewname,          # String
123
                "dpkg!"         => \$opt_dpkg,              # [no]flag
124
                "copy!"         => \$opt_copy,              # [no]flag
125
                "reuse!"        => \$opt_reuse,             # [no]flag
126
                "extract"       => \$opt_extract,           # flag
127
                "extractfiles"  => \$opt_extract_files,     # flag
128
                "delete:+"      => \$opt_delete,            # flag
129
                "build=s"       => \@opt_build,             # An array of build
130
                "test!"         => \$opt_test,              # [no]flag
131
                "cache"         => \$opt_cache,             # flag
132
                "keep!"         => \$opt_keep,              # [no]flag
133
                "beta!"         => \$opt_beta,              # [no]flag
134
                "merge"         => \$opt_merge,             # [no]flag
135
                "path=s"        => \$opt_path,              # string
136
                "runtests!"     => \$opt_runtests,          # [no]flag
137
                "branch=s"      => \$opt_branch,            # String
138
                "mkbranch=s"    => \$opt_branch,            # String
139
                "prodOnly"      => \$opt_prod_build,        # flag
140
                "debugOnly"     => \$opt_debug_build,       # flag
343 dpurdie 141
                "root=s"        => \$GBE_VIEWBASE,          # string
267 dpurdie 142
                "prefix!"       => \$opt_prefix,            # flag
351 dpurdie 143
                "tag=s"         => \$opt_tag,               # string
267 dpurdie 144
                );
145
 
146
                #
147
                #   UPDATE THE DOCUMENTATION AT THE END OF THIS FILE !!!
148
                #
149
 
150
#
151
#   Process help and manual options
152
#
153
pod2usage(-verbose => 0, -message => "Version: $VERSION")  if ($opt_help == 1  || ! $result);
154
pod2usage(-verbose => 1)  if ($opt_help == 2 );
155
pod2usage(-verbose => 2)  if ($opt_help > 2 );
156
 
157
InitFileUtils();
158
 
159
#
160
#   Configure the error reporting process now that we have the user options
161
#
162
ErrorConfig( 'name'    => 'SVNRELEASE',
163
             'verbose' => $opt_verbose );
164
 
165
#
166
#   Validate user options
167
#   Use either -label or one command line argument
168
#
169
Error ("Unexpected command line arguments present.","Cannot mix -label and command line label" )
170
    if ( $#opt_spec >= 0 && $#ARGV >= 0);
171
 
172
push @opt_spec, @ARGV;
173
 
174
unless(  @opt_spec  )
175
{
176
    Error ("Need a view or a label. -help for options") if ( $opt_delete  && ! $opt_viewname );
177
    Error ("Need a label or config_spec. -help for options") unless $opt_delete;
178
}
179
 
180
#
181
#   Convert label with embedded VCS information into a 'normal' form.
182
#   Form:
183
#       SVN::<URL>
184
#
185
foreach ( @opt_spec )
186
{
187
    s~^SVN::~~;
188
    Error ("Label contains invalid Version Control Identifier: $_")
189
        if ( m~^(.+)::.+~ );
190
    Verbose ("Clean URL: $_");
191
}
192
 
193
#
194
#   Limit the user to ONE label/tag/
195
#   Reason: Under Subversion its not possible to 'pinch' files from another
196
#           package. Don't need to create a workspace with multiple labels
197
#
198
#           It was a bad practice under clearcase
199
#
200
#
201
if ( $#opt_spec >= 1 )
202
{
203
    Error ("Multiple labels not supported",
204
           "Use one label to describe a package" );
205
}
206
 
207
#
208
#   User has specified both debug and production
209
#   Then set both to 0 : ie default
210
#
211
if ( $opt_debug_build + $opt_prod_build > 1 )
212
{
213
    $opt_debug_build = 0;
214
    $opt_prod_build = 0;
215
}
216
 
217
#
218
#   User has requested test mode
219
#       - Don't copy
220
#       - Don't packgae
221
#
222
if ( $opt_test )
223
{
224
    $opt_dpkg = 0;
225
    $opt_copy = 0;
226
}
227
 
228
#
229
#   Determine the machine type
230
#
231
Verbose ("Machine Type: UNIX=$UNIX");
232
 
233
Error ("Machine Name not determined")
234
    unless ( $MACHINENAME );
235
$user_cwd = getcwd;
236
 
237
Error ("USER name not determined" )
238
    unless ( $USER );
239
 
343 dpurdie 240
 
267 dpurdie 241
#
343 dpurdie 242
#   Clean up the view root directory
267 dpurdie 243
#
343 dpurdie 244
$VIEWDIR_ROOT = Realpath($GBE_VIEWBASE) || $GBE_VIEWBASE;
267 dpurdie 245
 
246
Verbose ("Viewpath: $VIEWDIR_ROOT");
247
Error ("Cannot locate view root directory: $VIEWDIR_ROOT" ) unless (-d $VIEWDIR_ROOT);
248
 
249
#
250
#   Remove any user name from the front of the view name
251
#   Simplifies the deletion process as the user can provide
252
#   the directory name
253
#
254
$view_prefix = "" unless ( $opt_prefix );
255
 
256
#
257
#   Create a class to describe the complete SVN label
258
#   This will parse the label and create a number of nice elements
259
#
260
my $svn_label = NewSessionByUrl ( $opt_spec[0] );
261
 
262
#
263
#   Setup user specified workspace
264
#   Include the user name to ensure that the view name is unique-ish
265
#   Keep the name as short as possible as some compilers display a fixed
266
#   length filename in error messages and this name is part of the path
267
#
268
#   Base the viewname on the view label. This will simplify the creation
269
#   of multiple views and reduce the risk of unexpected deletion
270
#
271
if ( $opt_viewname )
272
{
273
    Error ("View Name contains invalid characters" )
274
        unless ( $opt_viewname =~ m~^[-.:0-9a-zA-Z_]+$~ )
275
}
276
else
277
{
278
    #
279
    #   Create a view name based on the provide 'label'
280
    #
281
    if ( $svn_label->Type )
282
    {
341 dpurdie 283
        $opt_viewname = $svn_label->Path;
267 dpurdie 284
        $opt_viewname .= '_' . ($svn_label->Version || 'trunk');
285
    }
286
    else
287
    {
288
        $opt_viewname = $svn_label->Path;
289
        $bad_label_name = 1;
290
    }
291
 
292
    #
293
    #   If creating a branch, then insert the branch name
294
    #   into the workspace name
295
    #
296
    $opt_viewname .= '_' . $opt_branch if ( $opt_branch );
297
 
298
    #
351 dpurdie 299
    #   Create a simple dir name
300
    #       Remove path sep characters and replace with _
301
    #       Remove Peg marker (@) as this breaks svn
302
    #       Replace multiple _ with a single _
267 dpurdie 303
    #
351 dpurdie 304
    $opt_viewname =~ s~[^\-.:0-9a-zA-Z_]~_~g;
305
    $opt_viewname =~ tr~_~_~s;
267 dpurdie 306
}
307
$opt_viewname =~ s~^$view_prefix~~ if (defined($opt_viewname) && $view_prefix && $opt_delete );
308
 
309
#
310
#   Create a clearcase view to be used for the view
311
#
312
$VIEWPATH = "$view_prefix$opt_viewname";
313
$VIEWDIR = "$VIEWDIR_ROOT/$VIEWPATH";
299 dpurdie 314
$VIEWDIR =~ tr~\\/~/~s;
267 dpurdie 315
Verbose( "Hostname: $MACHINENAME" );
316
Verbose( "Viewpath: $VIEWPATH" );
317
Verbose( "Viewdir : $VIEWDIR" );
318
 
319
#
320
#   If the user has specified a "source path", then we must ensure that it is
321
#   valid. It will be used to create the WorkSpace
322
#
323
#   Ensure that the path is a defined variable. If used prepend a / to simplify
324
#   concatenation.
325
#
326
Verbose("Validate Source Path");
327
if ( $opt_path )
328
{
329
    $opt_path =~ tr~\\/~/~s;
330
    $opt_path =~ s~/$~~;
331
    $opt_path =~ s~^/~~;
332
 
333
    Error( "Source Path has drive specifier" ) if ( $opt_path =~ m~^[A-Za-z]\:~ );
334
    $opt_path = '/'.$opt_path ;
335
}
336
else
337
{
338
    $opt_path = '';
339
}
340
 
341
#
342
#   If the view currently exists then it will be deleted if allowed
343
#
344
delete_view()
299 dpurdie 345
    unless ( $opt_reuse );
267 dpurdie 346
 
347
#
348
#   If the user is simply deleting the view then all has been done
349
#
350
exit 0
351
    if ( $opt_delete );
352
 
353
 
354
#
355
#   Ensure that the label is present within the specified VOB
356
#
357
Verbose("Ensure Labels can be found in a Repository");
358
Verbose ("Testing label: ". $svn_label->Full );
359
$label_count++;
360
 
361
$svn_label->SvnValidateTarget (
362
                    'cmd'    => 'SvnRelease',
363
                    'target' => $svn_label->Full,
364
                    'require' => 1,
365
                    );
366
#
367
#   Test for a pegged label
368
#
369
push @label_not_pegged, $svn_label->Full
370
    unless ( $svn_label->Peg );
371
 
372
#
373
#   If we are only extracting files then ...
374
#
375
if ( $opt_extract_files )
376
{
377
    extract_files_from_view();
378
    exit (0);
379
}
380
 
381
#
382
#   Create a new workspace
383
#
384
if (! -d $VIEWDIR || ! $opt_reuse )
385
{
386
    Message( "Create the workspace" . ($GBE_SANDBOX ? " in a SANDBOX" : ""));
387
 
388
    my $view_tag = $svn_label->Full;
389
    #
390
    #   If a branch is required then copy the source to the
391
    #   branch and then checkout the branch
392
    #
393
    if ( $opt_branch )
394
    {
395
        #
396
        #   Create the name of the branch
397
        #   Will be based on the current package
398
        #
399
        my $branch = $svn_label->BranchName($opt_branch, 'branches' );
400
 
401
        $view_tag = $svn_label->SvnCopy (
402
                            'old' => $view_tag,
403
                            'new' => $branch,
404
                            'comment' => 'Created by Jats SvnRelease branch request',
405
                            'replace' => 0 );
406
 
407
        $view_tag = $svn_label->Url( $view_tag);
408
    }
409
 
410
    $svn_label->SvnCo ( $view_tag, $VIEWDIR . $opt_path );
411
    Error ("Cannot locate the created Workspace")
412
        unless ( -d $VIEWDIR . $opt_path);
413
 
414
    #
415
    #   Create a local package archive
416
    #   May be needed for multipackage builds and it will prevent JATS from
417
    #   finding any outside the view
418
    #
419
    mkdir ( $VIEWDIR . '/local_dpkg_archive')
420
        unless ($GBE_SANDBOX);
421
}
422
 
285 dpurdie 423
#   Place a tag-file in the user-specified source path
424
#   This will be used by the build-tool to locate the 'source-path' of the
425
#   view, primarily for determining metrics.
267 dpurdie 426
#
285 dpurdie 427
#   Calculate where the dynmaic view will be
428
#   This differ between UNIX/WINDOWS
429
#
351 dpurdie 430
if ( $GBE_ABT)
285 dpurdie 431
{
432
    Message( "Create Build tagfile");
287 dpurdie 433
    my $cpath = $VIEWDIR . $opt_path;
285 dpurdie 434
    if ( -d $cpath )
435
    {
436
        TouchFile ( "$cpath/.jats.packageroot" );
437
    }
438
}
439
 
440
#
267 dpurdie 441
#   Locate the JATS build files within the populated view
442
#
443
chdir ($VIEWDIR) or Error( "Cannot chdir to $VIEWDIR");
444
Message( "Locating build files");
445
 
446
my $bscanner = BuildFileScanner( $VIEWDIR, 'build.pl', '--LocateAll' );
447
$bscanner->scan();
448
my @build_list = $bscanner->getInfo();
449
foreach my $be ( @build_list )
450
{
451
    Message( DisplayPath ("Build file: $be->{dir} Name: $be->{file}"));
452
}
453
 
454
#
455
#   If we are extracting the view then we are done
456
#   Display useful information for the user
457
#
458
if ( $opt_extract )
459
{
460
    Message  DisplayPath "View in: $VIEWDIR";
461
    Warning ("No build files found" )   if ( $#build_list < 0 );
462
    Warning( "Multiple build files found" )if ( $#build_list > 0 );
463
    Message ("Not all labels are pegged") if ( @label_not_pegged  );
464
    Message ("All labels are pegged") unless ( @label_not_pegged  );
465
    Message ("Badly formed label name" ) if ( $bad_label_name );
466
    Message ("Development Sandbox") if ( $GBE_SANDBOX );
467
 
468
    exit 0;
469
}
470
 
471
Error ("No build files found")  if ( $#build_list < 0 );
472
 
473
#
474
#   Determine the list of builds to perform
475
#   Ensure that the user-requested build files are present
476
#
477
#   The user specifies the build file, via the mangled package name
478
#   This is package_name . project extension (daf_utils.cr)
479
#
480
if ( $#opt_build  >= 0)
481
{
482
    Verbose( "Check and locate the build files");
483
    @build_list = ();
484
    foreach my $bentry ( @opt_build )
485
    {
486
        if ($bscanner->match( $bentry) )
487
        {
488
            UniquePush (\@build_list, $bscanner->getMatchList() );
489
            Verbose ("Found: $bentry");
490
        }
491
        else
492
        {
493
            Error ("Cannot locate requested build files for: $bentry")
494
        }
495
    }
496
}
497
 
498
#
499
#   Sanity test if we will transfer the generated package to dpkg_archive
500
#   There are some limits
501
#       1) Must have built from one label
502
#       2) That label must be locked
503
#       3) Only one build file
504
#       4) The view must not have been reused
505
#       5) The view has a branch rule
506
#       6) Cannot release from a sandbox
507
#
508
my @elist;
509
push @elist, "Package built from multiple labels" unless ( $label_count == 1 );
510
push @elist, "Package built from an unpegged label" if ( @label_not_pegged  );
511
push @elist, "Package built with multiple build files" if ( scalar @build_list > 1 );
512
push @elist, "Package from a reused view" if ( $opt_reuse && ! $opt_beta );
513
push @elist, "Package from a development sandbox" if ( $GBE_SANDBOX );
514
push @elist, "View contains a branch" if ( $opt_branch );
515
push @elist, "User has specified build files" if ( $#opt_build > 0 );
516
push @elist, "Badly formed label name" if ( $bad_label_name );
517
 
518
if ( @elist )
519
{
520
    Warning ("Cannot officially release the package.", @elist);
521
    Error ("Build terminated as it cannot be released") if ($opt_dpkg && ! $opt_beta);
522
}
523
Warning ("Beta Release") if $opt_beta;
524
 
525
#
526
#   Process each of the build files in the specified order
527
#
528
foreach my $be (@build_list)
529
{
530
 
531
    #
532
    #   We need to change to the build directory
533
    #   Moreover we need the local name of the build directory.
534
    #   Windows does not handle a UNC pathname to well (at all)
535
    #
536
    my $build_dir = $be->{dir};
537
    chdir ("$build_dir") or Error( "Cannot chdir to build directory: $build_dir");
538
 
539
    if ( $be->{file} =~ m/^build.pl$/ )
540
    {
541
        Message ("Using JATS: $build_dir");
542
        #
543
        #   Invoke JATS to build the package and make the package
544
        #
545
        my @build_args = qw(--expert --cache);
546
        push @build_args, '--cache' if $opt_cache;
547
 
548
        my $make_type = 'all';
549
        $make_type = 'all_prod'  if ( $opt_prod_build );
550
        $make_type = 'all_debug' if ( $opt_debug_build );
551
 
552
 
553
        JatsCmd('build', @build_args)               and Error("Package did not build");
554
        JatsCmd('make', $make_type, 'NODEPEND=1')   and Error("Package did not make");
555
        JatsCmd('install');
556
 
557
        if ( $opt_runtests )
558
        {
321 dpurdie 559
            JatsCmd('make', 'run_unit_tests')      and Error("Tests did not run correctly");
267 dpurdie 560
        }
561
    }
562
    else
563
    {
564
        #
565
        #   Ant build files
566
        #
567
        my $pname =  $be->{file};
568
        Message ("Using ANT: $build_dir, $pname");
569
        $pname =~ s~depends.xml$~.xml~;
570
        copy($be->{file}, "auto.xml");
571
        JatsCmd('-buildfile', $pname, 'ant', 'build')        and Error("Package did not build");
572
        JatsCmd('-buildfile', $pname, 'ant', 'make_package') and Error("Package did not make_package");
573
    }
574
}
575
 
576
#
577
#   Copy the generated packages
578
#       1) dpkg_archive
579
#       2) Users local directory
580
#
581
foreach my $be (@build_list)
582
{
583
    my $build_dir = $be->{dir};
584
    chdir ("$build_dir") or Error( "Cannot chdir to build directory: $build_dir");
585
    if ( $opt_dpkg )
586
    {
587
        Message ("Using: $build_dir");
279 dpurdie 588
        my @create_opts = "-o";
589
        push @create_opts ,"-m" if ( $opt_merge );
590
        JatsCmd('-here', 'create_dpkg', @create_opts, '-pname', $be->{name}, '-pversion', $be->{version}) and $error++;
267 dpurdie 591
    }
592
 
593
    if ( $opt_copy )
594
    {
595
        Message ("Copy package to $user_cwd");
596
        copy_directory( 'pkg', $user_cwd, '' );
597
    }
598
 
599
    #
600
    #   Test structure of the package
601
    #   Ensure that it has a descpkg file
602
    #   Validate the package name and version
603
    #   More important for ANT projects than JATS as JATS has a sanity test
604
    #
605
    if ( $opt_test )
606
    {
607
        JatsCmd('-here', 'create_dpkg', '-test', '-pname', $be->{name}, '-pversion', $be->{version}) and $error++;
608
    }
609
 
610
}
611
Error ("Package not transferred")
612
    if ( $error );
613
 
614
 
615
#
616
#   Delete the view
617
#
618
if ( ! $opt_reuse && ! $error && ! $opt_keep )
619
{
620
    delete_view();
621
}
622
else
623
{
624
    Message( "View left in: $VIEWDIR" );
625
}
626
 
627
Message ("End program");
628
exit 0;
629
 
630
#-------------------------------------------------------------------------------
631
# Function        : delete_view
632
#
633
# Description     : Delete a view
634
#
635
# Inputs          : None
636
#                   $VIEWDIR - path of the view
637
#
638
# Returns         :
639
#
640
sub delete_view
641
{
642
    my $cofound = 0;
643
    my $uuid;
644
 
645
    #
299 dpurdie 646
    #   Simple delete
267 dpurdie 647
    #
299 dpurdie 648
    if ( $opt_extract_files )
267 dpurdie 649
    {
299 dpurdie 650
        if ( -d $VIEWDIR )
651
        {
652
            Message("Remove extracted files: $VIEWDIR");
653
            rmtree( $VIEWDIR );
654
        }
655
    }
656
    else
657
    {
267 dpurdie 658
        #
299 dpurdie 659
        #   If the view physically exists then attempt to phyically remove it
267 dpurdie 660
        #
299 dpurdie 661
        if ( -d $VIEWDIR )
662
        {
663
            #
664
            #   Determine if there are any checked out files in the view
665
            #
666
            Message("Remove the view: $VIEWDIR");
667
            Verbose("Look for checked out files");
267 dpurdie 668
 
669
 
299 dpurdie 670
            SvnRmView ('path'     => $VIEWDIR . $opt_path,
671
                       'force'    => $opt_delete > 1,
672
                       'modified' => [ 'local_dpkg_archive' ] );
673
        }
674
        Error ("View was not deleted")
675
            if ( -d $VIEWDIR . $opt_path );
676
        rmtree( $VIEWDIR ) if $opt_path;
267 dpurdie 677
    }
299 dpurdie 678
 
267 dpurdie 679
    Error ("View was not deleted")
299 dpurdie 680
        if ( -d $VIEWDIR );
267 dpurdie 681
}
682
 
683
#-------------------------------------------------------------------------------
684
# Function        : copy_directory
685
#
686
# Description     : Copy a directory tree
687
#
688
# Inputs          : Source directory
689
#                   Target directory
690
#                   Strip
691
#
692
#                   Should be full pathnames
693
#
694
# Returns         :
695
#
696
my $copy_error;
697
my $copy_count;
698
sub copy_directory
699
{
700
    our ($src_dir, $dest_dir, $strip) = @_;
701
    our $slength = length ($strip);
702
 
703
    #
704
    #   Prevent File::Find from generating warnings
705
    #
706
    no warnings 'File::Find';
707
 
708
 
709
    #
710
    #   Helper routine to copy files
711
    #
712
    sub copy_file_wanted
713
    {
714
        #
715
        #   Do not copy directories
716
        #   Just make the directory entry. May result in empty directories
717
        #
718
        if ( -d $_ )
719
        {
720
            my $tdir = "$dest_dir/" . substr( $File::Find::dir, $slength);
721
            $tdir .= "/$_";
722
            File::Path::mkpath( $tdir )
723
                unless ( -d $tdir);
724
            return;
725
        }
726
 
727
        #
728
        #   When used to copy file from within a clearcase dynamic view the
729
        #   files may not actually exist. This will generate an error later
730
        #   so check for existance of file file now.
731
        #
732
        return unless ( -e $_ );
733
 
734
        #
735
        #   Have been chdir'ed to the source directory
736
        #   when invoked
737
        #
738
        my $tdir = "$dest_dir/" . substr( $File::Find::dir, $slength);
739
        my $tfile = "$tdir/$_";
740
        my $sfile = "$File::Find::dir/$_";
741
        Verbose ("Copy: $sfile -> $tfile");
742
 
743
        File::Path::mkpath( $tdir )
744
            unless ( -d $tdir);
745
 
746
        unlink ( $tfile )
747
            if ( -f $tfile );
748
 
749
        if( ! File::Copy::copy ( $_ , $tfile ) )
750
        {
751
            $copy_error++;
752
            Message "Error copying $sfile";
753
        }
754
        else
755
        {
756
            my $perm = (stat $_)[2] & 07777;
757
            chmod($perm, $tfile);
758
 
759
            $copy_count++;
760
        }
761
    }
762
 
763
    #
764
    #   Locate all files to copy
765
    #
766
    $copy_error = 0;
767
    $copy_count = 0;
768
    File::Find::find ( \&copy_file_wanted, $src_dir );
769
    return $copy_error;
770
}
771
 
772
#-------------------------------------------------------------------------------
773
# Function        : count_files
774
#
775
# Description     : Count files in a workspace
776
#                   Ignore .svn stuff
777
#
778
# Inputs          : Source directory
779
#
780
# Returns         :
781
#
782
sub count_files
783
{
784
    my ($src_dir) = @_;
785
 
786
    #
787
    #   Prevent File::Find from generating warnings
788
    #
789
    no warnings 'File::Find';
790
 
791
 
792
    #
793
    #   Helper routine to copy files
794
    #
795
    sub count_file_wanted
796
    {
797
        #
798
        #   Do not count dirs, only files
799
        #
800
        return if ( -d $_ );
801
        $copy_count++;
802
    }
803
 
804
    #
805
    #   Locate all files
806
    #
807
    $copy_count = 0;
808
    File::Find::find ( \&count_file_wanted, $src_dir );
809
}
810
 
811
 
812
#-------------------------------------------------------------------------------
813
# Function        : extract_files_from_view
814
#
815
# Description     : This function will
816
#                       Create a dynamic view
817
#                       Copy all the files out of the view
818
#                       Delete the view
819
#
820
#                   Its used in the creation of escrow directories
821
#
822
# Inputs          : None
823
#                   All done via globals
824
#
825
# Returns         : 
826
#
827
sub extract_files_from_view
828
{
829
    #
830
    #   Determine the target directory for the extracted files
831
    #       Delete the output subdir
832
    #       Create the config spec in that directory
833
    #
834
    Verbose("Extracting files into $VIEWDIR");
835
    if ( -d $VIEWDIR )
836
    {
837
        Verbose "Delete Directory: $VIEWDIR\n";
838
        rmtree( $VIEWDIR );
839
    }
840
 
271 dpurdie 841
    $svn_label->SvnCo ( $svn_label->Full, $VIEWDIR, '--Export' );
267 dpurdie 842
 
843
    #
844
    #   Count this files in the view
845
    #   Done so that its clear when we have a empty workspace
846
    #
847
    Verbose ("Examine View contents");
848
    count_files ( $VIEWDIR );
849
    Message ("View files in: $VIEWDIR, Files: $copy_count" );
850
 
851
}
852
 
853
#-------------------------------------------------------------------------------
854
 
855
 
856
#-------------------------------------------------------------------------------
857
#   Documentation
858
#
859
 
860
=pod
861
 
862
=head1 NAME
863
 
864
jats_svnrelease - Build a package given a SubVersion label
865
 
866
=head1 SYNOPSIS
867
 
868
  jats svnrelease [options] [-label=]label
869
 
870
 Options:
871
    -help              - brief help message
872
    -help -help        - Detailed help message
873
    -man               - Full documentation
874
    -label=xxx         - Subversion label
875
    -spec=xxx          - Same as -label=xxx
876
    -path=xxx          - Source Path
877
    -view=xxx          - Modify the name of the created view
878
    -build=xxx         - Package Name to build
879
    -root=xxx          - Root directory for generated view
880
    -[mk]branch=xxx    - Will create a view with a branch rule
351 dpurdie 881
    -tag=xxx           - Compatability. Not used
267 dpurdie 882
    -extract           - Extract the view and exit
883
    -extractfiles      - Extract files, without a view
884
    -cache             - Refresh local dpkg_archive cache
885
    -delete            - Remove any existing view and exit
886
    -debugOnly         - Make only the debug version
887
    -prodOnly          - Make only the production version
888
    -[no]dpkg          - Transfer package into dpkg_archive
889
    -[no]copy          - Transfer pkg directory to the current user directory
890
    -[no]reuse         - Reuse the view
891
    -[no]test          - Test package build. Implies nocopy and nodpkg
892
    -[no]keep          - Keep the view after the build
893
    -[no]beta          - Release a beta package
894
    -[no]merge         - Merge packages into dpkg_archive
895
    -[no]runtests      - Run units tests. Default is runtests
896
    -[no]prefix        - Supress user prefix in view name. Default prefix is USER
897
 
898
=head1 OPTIONS
899
 
900
=over 8
901
 
902
=item B<-help>
903
 
904
Print a brief help message and exits.
905
 
906
=item B<-help -help>
907
 
908
Print a detailed help message with an explanation for each option.
909
 
910
=item B<-man>
911
 
912
Prints the manual page and exits.
913
 
914
=item B<-label> or B<-spec>
915
 
916
The Subversion label to use as the base for the workspace.
917
 
918
Eg: DPG_SWBASE/daf_utils_math/tags/3.2.1@12345
919
 
920
=item B<-view name>
921
 
922
Specified an alternate view name and tag to be used. This option does not provide the
923
full name of the view.
924
 
925
    The view path will be: "${USER}_${NAME}"
926
 
927
The default "NAME" is the first label specified with the repository and tag removed.
928
 
929
If the user provides a view "name" that is prefixed with their user name
930
('${USER}_'), then the username will be stripped of for internal processing.
931
This allows a user to provide a view path when deleting a view.
932
 
933
=item B<-path=xxx>
934
 
935
Specifies the source path to the root of the extracted file tree. This option is
936
not mandatory and is only used to mnaintain toolset compatability woth other
937
,similar, tools.
938
 
939
If provided, then the Workspace will be created within the named subdirectory
940
tree within the base of the view.
941
 
942
=item B<-build=xxx>
943
 
944
This option allows the user to specify the packages to be built and the
945
order in which the packages are to be built.
946
This is useful if the extracted view contains multiple build files
947
 
948
This option may be used multiple times.
949
 
950
There are two forms in which the build target can be specified. It can be
951
specified as a full package name and vesrion, or as a package name and the
952
project suffix.
953
 
954
By default the program will assume that there is only one build file in the
955
view and will not build if multiple files are present, unless the package to be
956
built can be resolved.
957
 
958
The location mechanism operates for both JATS and ANT build files.
959
 
960
Example: -build=jats-api.1.0.0000.cr
961
 
962
This will locate the build file that builds version 1.0.0000.cr of the jats-api
963
package. The version numbers must match exactly.
964
 
965
Example: -build=jats-api.cr -build=jats-lib.cr
966
 
967
This will located the build files that build the jats_api (cr) package and the
968
jats-lib (cr) package. The version of the packages will not be considered.
969
 
970
=item B<-root=xxx>
971
 
972
This option allows the location of the generated view to be specified on the
343 dpurdie 973
command line. It overides the value of GBE_VIEWBASE.
267 dpurdie 974
 
975
If the comamnd is invoked within a development sandbox, then the default
976
location will be the root directory of the development sandbox.
977
 
978
=back
979
 
980
=item B<-branch=xxx or -mkbranch=xxx>
981
 
982
This option will create workspace branch that is tagged with the named branch.
983
This is intended to facilitate the maintenance of existing packages - the
984
creation of a patch.
985
 
986
The named branch must NOT exist within the subversion repository. The script will
987
check for its existence.
988
 
989
The tool will copy the specified source version to the branch and then create a
990
workspace based on the branch.
991
 
351 dpurdie 992
=item B<-tag=text>
993
 
994
This option is not used.
995
It is present to maintain compatability with the buildtool interface.
996
 
267 dpurdie 997
=item B<-extract>
998
 
999
With this option the view is created and the left in place. The user may then
1000
access the files within the view. The view should not be used for a
1001
production release.
1002
 
1003
=item B<-extractfiles>
1004
 
1005
With this option the utility will create a dynamic view and transfer files from
1006
the view to the user's tararget. The dynamic view is then removed.
1007
 
1008
This command is intended to simplify the process of creating an escrow.
1009
 
1010
=item B<-cache>
1011
 
1012
Forces external packages to be placed in the local dpkg_archive cache.
1013
 
1014
The normal operation is to copy the packages, only if they do not already exist
1015
in the local cache. This option may be used to ensure that the local copy is
1016
correct and up to date.
1017
 
1018
=item B<-delete>
1019
 
1020
Delete the view used by the program, if it exists. This option may be used to
1021
cleanup after an error.
1022
 
1023
Note: Ensure that no files are open in the view and that the users current
1024
working directory is not in the view as these will prevent the view from being
1025
deleted.
1026
 
1027
=item B<-debugOnly>
1028
 
1029
Make only the debug version of the package. The default it to create both the
1030
debug and production version of the package. The type of build may be  further
1031
limited by options within the package.
1032
 
1033
=item B<-prodOnly>
1034
 
1035
Make only the production version of the package. The default it to create both the
1036
debug and production version of the package. The type of build may be  further
1037
limited by options within the package.
1038
 
1039
=item B<-[no]dpkg>
1040
 
1041
Copy the generated package into dpkg_archive. This is the default mode of
1042
operation.
1043
 
1044
=item B<-[no]copy>
1045
 
1046
Copy the built "pkg" directory to the users current directory. The entire
1047
"pkg" subdirectory includes the full package named directory for the package
1048
that has been built.
1049
 
1050
=item B<-[no]reuse>
1051
 
1052
This flag allows the view created by the program to be re-used.
1053
 
1054
=over 8
1055
 
1056
=item 1. The view is not deleted before being populated.
1057
 
1058
=item 2. The view will not be populated if it does exist.
1059
 
1060
=item 3. The view will not be deleted at the end the process.
1061
 
1062
=back
1063
 
1064
This option is useful for debugging a build process.
1065
 
1066
=item B<-[no]test>
1067
 
1068
Test the building of the package. This option implies "nocopy" and "nodpkg".
1069
 
1070
=item B<-[no]keep>
1071
 
1072
Keep the clearcase view after the build. The default option is "nokeep"
1073
 
1074
This option is different to the "reuse" in that the view will be deleted, if
1075
it exists, before the build, but will be retained at the completion of the
1076
process. The user may then manually extract the created package.
1077
 
1078
The view may be deleted with the the "delete" option; taking care to ensure that
1079
no files are open in the view and that the users current working directory is
1080
not in the view.
1081
 
1082
=item B<-[no]beta>
1083
 
1084
This option overrides many of the package release tests to allow a beta package
1085
to be released.
1086
 
1087
=item B<-[no]merge>
1088
 
1089
This option will merge packages being built on multiple machines into
1090
dpkg_archive. By default, if a package already exists in the archive it will be
1091
deleted and replaced. With this option the package will be merged. The merge
1092
process does not over write files found in the archive.
1093
 
1094
=item B<-[no]runtests>
1095
 
1096
This option will allow the suppression of the running of the unit tests included
1097
with the component. By default the tests are run. This can be suppressed
1098
without affecting the release process.
1099
 
1100
=back
1101
 
1102
=head1 DESCRIPTION
1103
 
1104
This program is the primary tool for the creation, recreation and release of
1105
packages within the B<ERG> build environment, although the program can perform a
1106
number of very useful operations required during normal development and
1107
maintenance.
1108
 
1109
This program will build a system containing one or more inter-related build
1110
files using the JATS build tools.
1111
 
1112
In normal operation the program will:
1113
 
1114
=over 8
1115
 
1116
=item Remove Workspace
1117
 
1118
Remove any existing workspace of the same name. The workspace will not be
1119
removed if it contains checked-out files.
1120
 
1121
The workspace removal may fail if there are any files B<open> within the view or if
1122
any shell has a subdirectory of the view set as a B<current working directory>.
1123
 
1124
=item Create the workspace
1125
 
1126
Create a workspace to contain the files described by the Subversion
1127
label being processed.
1128
 
1129
=item Populate the workspace
1130
 
1131
Loads files into the workspace.
1132
 
1133
I<Note:> If the workspace files are simply being extracted, then this is the end
1134
of the program. The extracted workspace is left in place.
1135
 
1136
=item Sanity Test
1137
 
1138
If the build is being used as a release into dpkg_archive then
1139
various tests are performed to ensure the repeatability of the view and the
1140
build. These tests include:
1141
 
1142
=over 8
1143
 
1144
=item   * The view must be constructed from one label
1145
 
1146
=item   * That label must be pegged
1147
 
1148
=item   * The labelled view must contain exactly one build file
1149
 
1150
=item   * The view cannot have been re-used.
1151
 
1152
=back
1153
 
1154
=item Locate build files
1155
 
1156
Locate the build file within the view.
1157
 
1158
It is an error to have multiple build files within the workspace, unless the
1159
B<-build> option is used. By default, only one package will be built.
1160
 
1161
=item Package the results
1162
 
1163
Use JATS to build and make the package.
1164
 
1165
The resultant package may be copied to a numbers of locations. These include
1166
 
1167
=over 8
1168
 
1169
=item 1
1170
 
1171
The master dpkg_archive as an official release. This is the default operation.
1172
 
1173
=item 2
1174
 
1175
The users current directory. The package directory from the built package is
1176
copied locally. The "pkg" directory is copied. This is only performed with the
1177
B<-copy> option.
1178
 
1179
=back
1180
 
1181
=item Delete the workspace
1182
 
1183
Delete the workspace and all related files.
1184
 
1185
The workspace will not be deleted if an error was detected in the build process, or
1186
the "reuse" or "keep" options are present.
1187
 
1188
=back
1189
 
1190
=cut
1191