Subversion Repositories DevTools

Rev

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