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