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