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