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