Subversion Repositories DevTools

Rev

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

Rev Author Line No. Line
267 dpurdie 1
########################################################################
2
# Copyright ( C ) 2008 ERG Limited, All rights reserved
3
#
4
# Module name   : jats_svnasave_build.pl
5
# Module type   : JATS Utility
6
# Compiler(s)   : Perl
7
# Environment(s): jats
8
#
9
# Description   : Build Daemon Support Utility
10
#                 This utility will:
11
#                   +   Assume the CWD is the root-dir of a package
12
#                       within a versioned control view
13
#                   +   Determine a suitable label for the package
14
#                   +   Save the build file in the view
15
#                   +   Label the resultant view
16
#
17
# Note          : Intended to be identical to jats_asave.pl
18
#                 except that it support SubVersion
19
#
20
# Usage:        : See POD at end of this file
21
#
22
#                 Preferred (new) usage:
23
#
24
#               jats etool  jats_svnasave_build
25
#                   -infile     auto.xml/auto.pl
26
#                   -outfile    xxxdepends.xml/build.pl
27
#                   -pname      package_name
28
#                   -pversion   package_version
29
#                   -infofile   path_to_info_file
30
#                   -wiplabel   Existing WIP label (optional)
31
#
32
#......................................................................#
33
 
34
use strict;
35
use warnings;
36
use JatsError;
37
use JatsBuildFiles;
38
use JatsSystem;
39
use JatsProperties;
40
use Getopt::Long;
41
use Pod::Usage;                             # required for help support
42
use File::Copy;
43
use JatsSvn;
44
use Cwd;
45
 
46
################################################################################
47
#   Option variables
48
#
49
 
50
my $VERSION = "2.0.0";                      # Update this
51
my $opt_debug   = $ENV{'GBE_DEBUG'};        # Allow global debug
52
my $opt_verbose = $ENV{'GBE_VERBOSE'};      # Allow global verbose
53
my $opt_infile  = "auto.pl";
54
my $opt_ofile = "build.pl";
55
my $opt_help = 0;
56
my $opt_infofile;
57
my $opt_pname;
58
my $opt_pversion;
59
my $opt_wiplabel;
60
my $opt_locate;
61
 
62
#
63
#   Globals
64
#
65
my $root_dir;
66
my $pkg_label;
67
my $tag_label;
68
 
69
my $ws_root;
70
my $pkg_root;
71
 
72
#
73
#   Configuration options
74
#
75
my $result = GetOptions (
76
                "help:+"        => \$opt_help,              # flag, multiple use allowed
77
                "manual:3"      => \$opt_help,              # flag
78
                "verbose:+"     => \$opt_verbose,           # flag
79
 
80
                "outfile=s"     => \$opt_ofile,             # string
81
                "infile=s"      => \$opt_infile,            # string
82
 
83
                "infofile=s"    => \$opt_infofile,          # string
84
                "pname=s"       => \$opt_pname,             # string
85
                "pversion=s"    => \$opt_pversion,          # string
86
                "wiplabel=s"    => \$opt_wiplabel,          # string
87
                "locatepkg=s"   => \$opt_locate,            # string
88
 
89
                #
90
                #   Update documentation at the end of the file
91
                #
92
                );
93
 
94
#
95
#   Process help and manual options
96
#
97
pod2usage(-verbose => 0, -message => "Version: $VERSION")  if ($opt_help == 1  || ! $result);
98
pod2usage(-verbose => 1)  if ( $opt_help == 2 );
99
pod2usage(-verbose => 2)  if ( $opt_help > 2 );
100
 
101
#
102
#   Configure the error reporting process now that we have the user options
103
#
104
ErrorConfig( 'name'    =>'SVNABTSAVE',
105
             'verbose' => $opt_verbose,
106
           );
107
 
108
Error ("Input and output file are the same: $opt_infile" )
109
    if ( $opt_infile eq $opt_ofile );
110
 
111
Error ("Package Name not provided")
112
    unless ( $opt_pname );
113
 
114
Error ("Package Version not provided")
115
    unless ( $opt_pversion );
116
 
117
Warning("Path to info file not provided")
118
    unless ( $opt_infofile );
119
 
120
unlink ($opt_infofile) if $opt_infofile;
121
 
122
#
123
#   Locate the build directory and chdir to that directory
124
#
125
locate_build_directory();
126
 
127
#
128
#   Have changed to the directory with build files
129
#   Continue with user argument sanity check
130
#
131
Error ("Input file not found: $opt_infile" )
132
    unless ( -f $opt_infile );
133
 
134
Error ("Output file not found: $opt_ofile" )
135
    unless ( -f $opt_ofile );
136
 
137
 
138
#
139
#   Create a SubVersion Session using the current workspace
140
#   as a basis. Error if not a workspace
141
#
142
my $session = NewSessionByWS( '.' );
143
 
144
Verbose ("Determine the current workspace root" );
145
$ws_root = $session->SvnLocateWsRoot(1) || '';
146
$pkg_root = $session->Full;
147
 
148
Verbose ("Workspace root: $ws_root");
149
Verbose ("Package root  : $pkg_root");
150
 
151
#
152
#   Determine the desired label for the package
153
#   May need to pick an unassigned label
154
#
155
determine_package_label();
156
 
157
#
158
#   Update the build file
159
#   Under subversion this is a simple 'copy'
160
#
161
Verbose ("Update build files");
162
unlink $opt_ofile;
163
unless ( File::Copy::copy($opt_infile, $opt_ofile) )
164
{
165
    Error("Failed to copy file [$opt_infile] to [$opt_ofile]: $!");
166
    Error ("Updating build files","Reason: $!");
167
}
168
 
169
#
170
#   Change back to original directory
171
#
172
if ( $root_dir )
173
{
174
    chdir $root_dir || Error ("Cannot change directory: $root_dir");
175
}
176
 
177
#
178
#   Label the view
179
#
180
label_build_view();
181
 
182
exit 0;
183
 
184
#-------------------------------------------------------------------------------
185
# Function        : locate_build_directory
186
#
187
# Description     : Locate the build directory that contains the build files
188
#                   In an ANT build, this will e the root of the package
189
#                   Otherwise the build files may not be in the root directory
190
#
191
#
192
# Inputs          : Globals
193
#
194
# Returns         : Globals
195
#
196
sub locate_build_directory
197
{
198
    return unless ( $opt_locate );
199
 
200
    my $bscanner = BuildFileScanner ( '.', $opt_infile );
201
    my $count = $bscanner->locate();
202
 
203
    Error ("Autolocate. Build file not found: $opt_infile" )
204
        if ( $count <= 0 );
205
 
206
    #
207
    #   If multiple build files have been found
208
    #   Scan the buildfiles and determine the names of the packages that will
209
    #   be built. This can be used to generate nice error messages
210
    if ( $count > 1 )
211
    {
212
        $bscanner->scan();
213
        $count = $bscanner->match( $opt_locate );
214
 
215
        my $errmess;
216
        if ( $count <= 0 ) {
217
            $errmess = "None found that build package: $opt_locate";
218
 
219
        } elsif ( $count > 1 ) {
220
            $errmess = "Multiple build files build the required package: $opt_locate";
221
        }
222
 
223
        #
224
        #   Pretty error display
225
        #   Display build directory and the package name (mangled)
226
        #
227
        if ( $errmess )
228
        {
229
            Error ("Autolocate. Multiple build files found.",
230
                   $errmess,
231
                   "Build files found in:", $bscanner->formatData() );
232
        }
233
    }
234
 
235
    #
236
    #   Extract the required build file directory
237
    #
238
    my $dir = $bscanner->getMatchDir() || '';
239
    Verbose ("Autolocate. Found $count build files: $dir");
240
 
241
    #
242
    #   Select the one true build directory
243
    #
244
    if ( $dir ne '.' )
245
    {
246
        #
247
        #   Save the current directory for later
248
        #
249
        $root_dir = getcwd();
250
        chdir $dir || Error ("Cannot change directory: $dir");
251
    }
252
}
253
 
254
#-------------------------------------------------------------------------------
255
# Function        : determine_package_label
256
#
257
# Description     : Determine the label that is to be applied to the package
258
#                   There are several cases to consider
259
#                       1) Compatability mode: User provides label
260
#                       2) WIP Mode. Determine name of label to use in rename
261
#                       3) Create a new label
262
#
263
# Inputs          : Globals
264
#
265
# Returns         : Globals
266
#                       $pkg_label
267
#
268
sub determine_package_label
269
{
270
 
271
    #
272
    #   Determine the desired label for the package
273
    #   This is a function of the package name and the package version
274
    #   The two are joined with a '.'
275
    #
276
    $tag_label = $opt_pname . '_' . $opt_pversion;
277
 
278
    #
279
    #   Ensure that desired label is "free", if not then hunt for a new one
280
    #   Determine the name of a 'new' label
281
    #
282
    my $base_label = $tag_label;
283
    my $index = 0;
284
 
285
    while ( ++$index )
286
    {
287
        if ( $index > 20 )
288
        {
289
            Error ("Cannot determine new label. Retry limit exceeded");
290
        }
291
        Verbose2 ("Trying $tag_label");
292
 
293
        if ( $session->SvnValidateTarget (
294
                    'target' => $session->BranchName($tag_label, 'tags' ),
295
                    'test' => 1,
296
                    ))
297
        {
298
            #
299
            #   Label found - so try another
300
            #
301
            Verbose2("Label found. Try another");
302
            $tag_label = $base_label . '.' . $index;
303
            next;
304
        }
305
 
306
        #
307
        #   Warn about non standard label
308
        #
309
        Verbose ("Package will be labeled: $tag_label");
310
        Warning ("Labeling with a non-standard label: $tag_label" )
311
            if ( $index > 1 );
312
        last;
313
    }
314
 
315
    #
316
    #   Free label has been found
317
    #
318
    unless ( $opt_wiplabel )
319
    {
320
        $pkg_label = $tag_label;
321
    }
322
    else
323
    {
324
        $pkg_label = $opt_wiplabel;
325
    }
326
}
327
 
328
#-------------------------------------------------------------------------------
329
# Function        : label_build_view
330
#
331
# Description     : Label the view
332
#
333
#                   Either:
334
#                       Rename the WIP label to required name
335
#                       Label all files in the view
336
#                   
337
#                   Use JATS to do the hard work
338
#
339
#
340
# Inputs          : Globals
341
#
342
# Returns         : 
343
#
344
sub label_build_view
345
{
346
    #
347
    #   Save the current workspace - with its modified build file
348
    #
349
    Verbose ("Apply new label to package: $tag_label");
350
    $session->SvnCopyWs (
351
               'target'   => $session->BranchName($tag_label, 'tags' ),
352
               'modified' => $opt_ofile,
353
               'noswitch' => 1,
354
               'replace'  => 0,
355
               'comment'  => 'Created by Jats SaveBuild',
356
               );
357
    Message ("Repository Ref: " . $session->RmRef);
358
 
359
    if ( $opt_wiplabel )
360
    {
361
        #
362
        #   If the build is based on a WIP, then we can delete the
363
        #   WIP if its based on a branch
364
        #
365
        if ( $session->WsType eq 'branches' )
366
        {
367
            $session->SvnDelete(
368
                    'target'  => $session->FullWs,
369
                    'comment' => ["Deleted by Jats SaveBuild","Replaced by: $tag_label"],
370
                    'noerror' => 1,
371
                     );
372
        }
373
        else
374
        {
375
            Message ("WIP not deleted.","Will not delete WIPS based on a :" . $session->WsType );
376
        }
377
    }
378
 
379
    #
380
    #   Write the label out to the specified file so that the user
381
    #   can do something with it
382
    #
383
    if ( $opt_infofile )
384
    {
385
 
386
        my $data = JatsProperties::New();
387
 
388
        $data->setProperty('Label', $tag_label);
389
        $data->setProperty('WipLabel', $opt_wiplabel ) if $opt_wiplabel;
390
        $data->setProperty('PackageName', $opt_pname);
391
        $data->setProperty('PackageVersion', $opt_pversion);
392
        $data->setProperty('subversion.tag', $session->RmRef);
393
 
394
        $data->Dump('InfoFile') if ($opt_verbose);
395
        $data->store( $opt_infofile );
396
    }
397
}
398
 
399
#-------------------------------------------------------------------------------
400
#   Documentation
401
#
402
 
403
=pod
404
 
405
=head1 NAME
406
 
407
jats_svnsave_build - Save a build view to version control system
408
 
409
=head1 SYNOPSIS
410
 
411
  jats etool jats_save_build [options]
412
 
413
 Options:
414
    -help[=n]           - brief help message
415
    -help -help         - Detailed help message
416
    -man[=n]            - Full documentation
417
    -verbose[=n]        - Verbose operation
418
    -infile=xxx         - Input file (auto.pl)
419
    -outfile=xxx        - Output file (build.pl)
420
    -infofile=path      - Save label information in 'path'
421
    -pname=name         - Name of the package
422
    -pversion=text      - Package version
423
    -locatepkg=text     - Package locator string
424
    -wiplabel=text      - Current package WIP label
425
 
426
=head1 OPTIONS
427
 
428
=over 8
429
 
430
=item B<-help[=n]>
431
 
432
Print a brief help message and exits.
433
 
434
The verbosity of the help text can be controlled by setting the help level to a
435
number in the range of 1 to 3, or by invoking the option multiple times.
436
 
437
=item B<-man[=n]>
438
 
439
Without a numeric argument this is the same as -help=3. Full help will be
440
displayed.
441
 
442
With a numeric argument, this option is the same as -help=n.
443
 
444
=item B<-verbose[=n]>
445
 
446
This option will increase the level of verbosity of the utility.
447
 
448
If an argument is provided, then it will be used to set the level, otherwise the
449
existing level will be incremented. This option may be specified multiple times.
450
 
451
=item B<-infile=xxxx>
452
 
453
This option specifies the name of the generated build configuration file that
454
will be used as a data-source for the check-in build file.
455
 
456
The default file name is 'auto.pl'.
457
 
458
=item B<-outfile=xxxx>
459
 
460
This option specifies the name of the target build configuration file that
461
will be checked in to version-control. Data from from file specifies with '-
462
infile' will be used to update the file.
463
 
464
The default file name is 'build.pl'.
465
 
466
=item B<-infofile=path>
467
 
468
This option specifies a file that this utility will use to communicate with a
469
user script. It will write the new label text into the file.
470
 
471
The file path is relative to the current working directory.
472
 
473
The file will be deleted, and only created if the utility is successful.
474
 
475
=item B<-pname=name>
476
 
477
This option specifies the package name. It will be used to construct a new
478
label for the package.
479
 
480
=item B<-pversion=xxx>
481
 
482
This option specifies the package version. It will be used to construct a new
483
label for the package.
484
 
485
=item B<-locatepkg=text>
486
 
487
This option specifies a name, by which the package's build files may be located.
488
This is only needed for JATS builds and will only be used to resolve the
489
location of build files when a package contains multiple build files.
490
 
491
=item B<-wiplabel=text>
492
 
493
This option controls the manner in which this utility will label the build view.
494
 
495
If present, the label specifies a 'Work In Progress' label. The label will be
496
renamed. At the end of the process the wip label will be deleted from the
497
the repository.
498
 
499
If not present, then the view will be labeled with a new label.
500
 
501
=back
502
 
503
=head1 DESCRIPTION
504
 
505
This utility is used by the automated build system to place build view under
506
version control. The utility will:
507
 
508
=over 8
509
 
510
=item * Determine a suitable label for the package
511
 
512
The label is constructed from the package name and the package version. The
513
utility will ensure that the label does not already exist. If it does it will
514
use an alternate form of the label.
515
 
516
=item * Locate the build files within the package
517
 
518
JATS build files do not need to be at the root of the package. The utility
519
will locate the JATS build files.
520
 
521
=item * Update the build files and save them into the version control system
522
 
523
The build file will be updated with new version information as provided by a
524
secondary configuration file.
525
 
526
The updated file will be checked into version control.
527
 
528
=item * Ensure that the package is labeled
529
 
530
The build view will be labeled (tagged).
531
 
532
If a WIP label is provided then the WIP label will be removed if it is a branch.
533
 
534
=item * Return the label to the user
535
 
536
The label used to label the package will be returned to the user in an 'info'
537
file. This is a 'properties' file. The following properties are defined:
538
 
539
=over 8
540
 
541
=item   1) Label - The label used to tag the file
542
 
543
=item   3) WipLabel - The WIP label provided (optional)
544
 
545
=item   4) PackageName - The package name
546
 
547
=item   5) PackageVersion - The package version
548
 
549
=back
550
 
551
=back
552
 
553
=cut
554