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