Subversion Repositories DevTools

Rev

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