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