Subversion Repositories DevTools

Rev

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