Subversion Repositories DevTools

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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