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-2004 ERG Limited, All rights reserved
3
#
4
# Module name   : jats_svnlabel.pl
5
# Module type   : Jats Utility
6
# Compiler(s)   : Perl
7
# Environment(s): Jats
8
#
9
# Description   : A script to perform a number of labeling operations
10
#                 The script will:
11
#                   label a workspace       - Create a tag
12
#                   delete a label          - Deletes a tag
13
#                   rename a label          - Renames a tag
14
#                   clone a label           - Clones a tag
15
#
16
#......................................................................#
17
 
18
require 5.006_001;
19
use strict;
20
use warnings;
21
use JatsError;
22
use JatsSvn;
23
 
24
use Pod::Usage;                             # required for help support
25
use Getopt::Long;
26
use Cwd;
27
 
28
my $VERSION = "1.0.0";                      # Update this
29
 
30
#
31
#   Options
32
#
33
my $opt_debug   = $ENV{'GBE_DEBUG'};        # Allow global debug
34
my $opt_verbose = $ENV{'GBE_VERBOSE'};      # Allow global verbose
35
my $opt_help = 0;
36
my $opt_check;
37
my $opt_avail;
38
my $opt_label;
39
my $opt_replace;
40
my $opt_delete;
41
my $opt_rename;
42
my $opt_clone;
43
my $opt_comment;
44
my $opt_workspace;
45
my $opt_packagebase;
46
my $opt_branch;
47
my $opt_list;
48
 
49
#
50
#   Globals
51
#
52
my $session;                                # Subversion Session
53
my $label;                                  # User argument - one label
54
my $src_label;                              # User specified source label
55
my $pkg_root;                               # Root of corresponding package
56
my $opr_done;                               # User has done something
57
 
58
#-------------------------------------------------------------------------------
59
# Function        : Mainline Entry Point
60
#
61
# Description     :
62
#
63
# Inputs          :
64
#
65
my $result = GetOptions (
66
                "help:+"        => \$opt_help,              # flag, multiple use allowed
67
                "manual:3"      => \$opt_help,              # flag
68
                "verbose:+"     => \$opt_verbose,           # flag, multiple use allowed
69
                "check"         => \$opt_check,             # Flag
70
                "available"     => \$opt_avail,             # Flag
71
                "label"         => \$opt_label,             # Flag
72
                "delete"        => \$opt_delete,            # Flag
73
                "replace!"      => \$opt_replace,           # Flag
74
                "rename=s"      => \$opt_rename,            # String
75
                "clone=s"       => \$opt_clone,             # String
76
                "comment=s"     => \$opt_comment,           # String
77
                "workspace=s"   => \$opt_workspace,         # String
78
                "packagebase=s" => \$opt_packagebase,       # String
79
                "branch"        => \$opt_branch,            # Flag
80
                "list"          => \$opt_list,              # Flag
81
 
82
                );
83
 
84
                #
85
                #   UPDATE THE DOCUMENTATION AT THE END OF THIS FILE !!!
86
                #
87
 
88
#
89
#   Process help and manual options
90
#
91
pod2usage(-verbose => 0, -message => "Version: $VERSION") if ($opt_help == 1 || ! $result);
92
pod2usage(-verbose => 1) if ($opt_help == 2 );
93
pod2usage(-verbose => 2) if ($opt_help > 2);
94
 
95
#
96
#   Configure the error reporting process now that we have the user options
97
#
98
ErrorConfig( 'name'    =>'SVNLABEL',
99
             'verbose' => $opt_verbose,
100
            );
101
 
102
#
103
#   Validate user options
104
#   Need one command line argument
105
#
106
Error ("No labels provided") if ( $#ARGV < 0 && !$opt_list );
107
Error ("Too many labels provided") if ( $#ARGV > 0);
108
Error ("Conflicting options") if ( $opt_clone && $opt_label );
109
$label = $ARGV[0];
110
 
111
#
112
#   Locate package and workspace roots
113
#
114
LocateRoots ();
115
 
116
################################################################################
117
#
118
#   Validate one or more labels
119
#   Intended to be used within scripts for testing
120
#
121
if ( $opt_check )
122
{
123
    $session->SvnValidateTarget
124
    (
125
        'target'    => make_src_label ($pkg_root, $label),
341 dpurdie 126
        'cmd'       => 'Validate Existence',
267 dpurdie 127
        'require'   => 1,
128
    );
129
    $opr_done = 1;
130
}
131
 
132
if ( $opt_avail )
133
{
134
    $session->SvnValidateTarget
135
    (
136
        'target'    => make_src_label ($pkg_root, $label),
137
        'cmd'       => 'Validate Availablility',
138
        'available' => 1,
139
    );
140
    $opr_done = 1;
141
}
142
 
143
################################################################################
144
#
145
#   List labels
146
#
147
if ( $opt_list )
148
{
149
    my $pList = $session->ListLabels (make_label ($pkg_root, '') );
150
 
151
    #
152
    #   REmove trailing / on all directory names
153
    #
154
    chop @{$pList};
155
 
156
    my $type = $opt_branch ? 'branch' : 'tag';
157
    Information ( "Package: " . $session->Path,
158
                    ,map ( $type . ': ' . $_, @{$pList})
159
                    );
160
    $opr_done = 1;
161
}
162
 
163
 
164
################################################################################
165
#
166
#   Rename a label
167
#   This has implications for stuff that is stored within release manager
168
#
169
#   Renaming a pegged version is problematical
170
#   At the moment we do a copy ( rename, without the delete)
171
#
172
if ( $opt_rename )
173
{
174
    #
175
    #   Create old and new paths for the full label
176
    #
177
    my $ws_label_old = make_src_label ($pkg_root, $label);
178
    my $ws_label_new = make_label ($pkg_root ,SvnIsaSimpleLabel($opt_rename));
179
 
180
    $session->SvnRename (
181
                'old' => $ws_label_old,
182
                'new' => $ws_label_new,
183
                'comment' => $opt_comment ? $opt_comment : 'Renamed by Jats Svnlabel',
184
                'replace' => $opt_replace ? 1 : 0,
185
                );
186
 
187
    Message ("Repository Ref: " . $session->RmRef);
188
    $opr_done = 1;
189
}
190
 
191
################################################################################
192
#   
193
#   The Svn Label need a package root
194
#   If we are in a WorkSpace, then we can determine the package root
195
#
196
if ( $opt_label )
197
{
198
    #
199
    #   Can now create a nice pathname for the label
200
    #
201
    my $ws_label = make_label( $pkg_root, SvnIsaSimpleLabel ($label));
202
 
203
    #
204
    #   Don't let the user create a tag from a workspace that is
205
    #   also created from a tag.
206
    #
207
    #   They should be using a branch.
208
    #   Can't stop them - but can make it difficult.
209
    #
210
    Error ("Cannot tag a Workspace based on a 'tag'",
211
           "You should be working in a branch",
212
           "WorkSpace: $session->{WSURL}" )
213
        if ( ($session->WsType) eq 'tags' );
214
 
215
    $session->SvnCopyWs (
216
                   target => $ws_label,
217
                   'noswitch' => 1,
218
                   'replace' => $opt_replace ? 1 : 0,
219
                   'comment' => $opt_comment ? $opt_comment : 'Created by Jats Svnlabel',
220
                   );
221
 
222
    Message ("Repository Ref: " . $session->RmRef);
223
    $opr_done = 1;
224
}
225
 
226
################################################################################
227
#
228
#   Delete a label
229
#   Can't really delete one, but we can remove it from the head
230
#   If SVN ever gets an 'obliterate' command then prehaps we could use it
231
#
232
if ( $opt_delete )
233
{
234
    #
235
    #   Calculate the label name to delete
236
    #
237
    my $ws_label = make_src_label( $pkg_root, $label );
238
    $session->SvnDelete ( 'target' => $ws_label,
239
                          'comment' => $opt_comment ? $opt_comment : 'Deleted by Jats Svnlabel',
240
                          'noerror' => 1 );
241
    $opr_done = 1;
242
}
243
 
244
################################################################################
245
#
246
#   Clone a label
247
#   Essentially a copy of a tag
248
#
249
#
250
if ( $opt_clone )
251
{
252
    #
253
    #   Create old and new paths for the full label
254
    #
255
    my $ws_label_old = make_src_label ($pkg_root, $label);
256
    my $ws_label_new = make_label ($pkg_root ,SvnIsaSimpleLabel($opt_clone));
257
    $session->SvnCopy (
258
                'old' => $ws_label_old,
259
                'new' => $ws_label_new,
260
                'comment' => $opt_comment ? $opt_comment : 'Copied by Jats Svnlabel',
261
                'replace' => $opt_replace ? 1 : 0,
262
                );
263
 
264
    Message ("Repository Ref: " . $session->RmRef);
265
    $opr_done = 1;
266
}
267
 
268
 
269
Error ("No valid operations specified. Try -h") unless ( $opr_done );
270
exit 0;
271
 
272
 
273
#-------------------------------------------------------------------------------
274
# Function        : make_label
275
#
276
# Description     : Create a label ( tag or branch )
277
#
278
# Inputs          : $base
279
#                   $name
280
#
281
# Returns         : Full label
282
#
283
sub make_label
284
{
285
    my ($base, $name) = @_;
286
    my $join = $opt_branch ? '/branches/' : '/tags/';
287
    return $base . $join . $name;
288
}
289
 
290
#-------------------------------------------------------------------------------
291
# Function        : make_src_label
292
#
293
# Description     : Create a source label ( tag or branch )
294
#
295
# Inputs          : $base
296
#                   $name
297
#
298
# Returns         : Full label
299
#
300
sub make_src_label
301
{
302
    return $src_label if ( $src_label );
303
 
304
    my ($base, $name) = @_;
305
    my $join = $opt_branch ? '/branches/' : '/tags/';
306
    return $base . $join . $name;
307
}
308
 
309
 
310
#-------------------------------------------------------------------------------
311
# Function        : LocateRoots
312
#
313
# Description     : Determine workspace root and associated
314
#                   package root
315
#
316
#                   Uses several hint to figure it out
317
#                       The default is the package in the current directory
318
#                       -workspace - may address a workspace
319
#                       -packagebase - may specify a package base
320
#                                      Does not work with -label
321
#                                      as we need a workspace
322
#
323
#
324
# Inputs          : None - uses globals
325
#
326
# Returns         : Setup global variables
327
#
328
sub LocateRoots
329
{
330
    #
331
    #   Use current directory as the workspace unless the user
332
    #   has specified a different one
333
    #
334
    $session = NewSessionByWS( $opt_workspace || '.', $opt_workspace ? 0 : 1 );
335
 
336
    Verbose ("Determine the current workspace root" );
337
    my $ws_root = $session->SvnLocateWsRoot(1) || '';
338
 
339
    #
340
    #   Only need a WS root for the label operation
341
    #   Every thing else can live without it
342
    #
343
    Error ("Cannot determine source Workspace") if ( $opt_label && !$ws_root );
344
 
345
    #
346
    #   Calculate the package base
347
    #       - User specified
348
    #       - Extacted from label
349
    #       - Extracted from WorkSpace
350
    #           - User specified Workspace
351
    #           - Current directory
352
    #
353
    if ( $opt_packagebase )
354
    {
355
        #
356
        #   User has given us the package base
357
        #
358
        $session = NewSessionByUrl ( $opt_packagebase, $session );
359
        $session->SvnValidatePackageRoot();
360
    }
361
    elsif ( $label && $label =~ m~(.+)(/(tags|branches|trunk)(/|@)(.+))~ )
362
    {
363
        #
364
        #   Attempt to extract it from the label
365
        #   Remove it from the label
366
        #
367
        $src_label = $2;
368
        $label = $5;
369
        $session = NewSessionByUrl ( $1, $session );
370
        $session->SvnValidatePackageRoot();
371
        $src_label = $session->Full . $src_label;
372
    }
373
    elsif ( $ws_root )
374
    {
375
        # $s2 = $session;
376
    }
377
    else
378
    {
379
        Error ("Cannot determine the Package Base");
380
    }
381
    $pkg_root = $session->Full;
382
 
383
    #
384
    #   Everything needs a $pkg_root
385
    #
386
    Error ("Cannot determine Package Base") unless ( $pkg_root  );
387
 
388
    Verbose ("Workspace root: $ws_root");
389
    Verbose ("Package root  : $pkg_root");
390
#DebugDumpData ("Session", $session );
391
}
392
 
393
#-------------------------------------------------------------------------------
394
#   Documentation
395
#
396
 
397
=pod
398
 
399
=head1 NAME
400
 
401
jats_svnlabel - Subversion label operations
402
 
403
=head1 SYNOPSIS
404
 
405
jats label [options] C<label>
406
 
407
 Options:
408
    -help                  - brief help message
409
    -help -help            - Detailed help message
410
    -man                   - Full documentation
411
    -available             - Check for label availablility
412
    -check                 - Check for label existence
413
    -clone=xxx             - Clone a package version
414
    -delete                - Delete label from the repository
415
    -label                 - Labels a Package
416
    -list                  - List lables in a package
417
    -rename=xxx            - Rename a label
418
 
419
 Modifiers
420
    -branch                - Use branches, not tags
421
    -replace               - Replace existing labels. Use with -label
422
    -comment=text          - Comment to add to repository operations
423
    -workspace=path        - Path to a workspace to label
424
    -packagebase=path      - Repostory path to package base
425
 
426
=head1 OPTIONS
427
 
428
=over 8
429
 
430
=item B<-help>
431
 
432
Print a brief help message and exits.
433
 
434
=item B<-help -help>
435
 
436
Print a detailed help message with an explanation for each option.
437
 
438
=item B<-man>
439
 
440
Prints the manual page and exits.
441
 
442
=item B<-clone=xxx>
443
 
444
This option will copy a labled version of a package to a new label.
445
 
446
=item B<-delete>
447
 
448
This option will delete the specified label from the repository
449
 
450
=item B<-available>
451
 
452
This option will check for the lables non-existence. An error will be reported
453
if the label exists.
454
 
455
=item B<-check>
456
 
457
This option will check for the lables existence. An error will be reported
458
if the label does not exist.
459
 
460
=item B<-label>
461
 
462
This option will label a workspace.
463
 
464
The -replace option may be used to force labels to be moved.
465
 
466
=item B<-rename=xxx>
467
 
468
This option will rename a label. The new name of the label is provided as the
469
argument after the option. If any further operation are to be performed the
470
new label name will be used.
471
 
472
=item B<-list>
473
 
474
This option will case all lables for the related package to be shown. The
475
command assumes that the repository is in a trunk/tags/branches format.
476
 
477
By default tags are shown. Branches may be shown with the -branches option.
478
 
479
=item B<-replace>
480
 
481
This option may be used with the -label command to allow existing labels to
482
be replaced.
483
 
484
=item B<-comment=text>
485
 
486
This option provides text to be used to document the operation in the log.
487
 
488
If none is provided, then the utility will use a simple comment of its own.
489
 
490
=item B<-workspace=path>
491
 
492
This option can be used to specify the path to a workspace to be labeled.
493
 
494
If not provided then the utility will use the current directory to determine
495
the root of the workspace.
496
 
497
=item B<packagebase=path>
498
 
499
This option can be used to specify the path to a package within a repository.
500
 
501
If the 'label' contains a package base, then it will be extracted and used.
502
 
503
If not provided and the utility is within a workspace, then the package base will
504
be taken to be that of the package in the workspace.
505
 
506
=item B<-branch>
507
 
508
This option modifies all commands. It causes the labeling operations to be
509
performed on a the packages 'branches' area instead of the default 'tags'
510
area.
511
 
512
=back
513
 
514
=head1 DESCRIPTION
515
 
516
This program provides a number of useful Subversion labeling operations. These
517
are:
518
 
519
=over 8
520
 
521
=item   check - check existance of a label
522
 
523
=item   available - check non-existance of a label
524
 
525
=item   list - list the label on a package
526
 
527
=item   rename - rename a label
528
 
529
=item   label - label a workspace
530
 
531
=item   delete - delete a label
532
 
533
=item   clone - duplicate a label
534
 
535
=back
536
 
537
The various operations may be mixed in the one command. The order of the
538
operations is: check, available, list, rename, label, delete and clone
539
 
540
=head2 LABEL format
541
 
542
A 'label' as used by JATS within a Subversion repository, may have four elements.
543
These are:
544
 
545
=over
546
 
547
=item   * Package Path
548
 
549
Any text preceeding a / will be taken to be a package path. This identifies the
550
root of the package within the repository.
551
 
552
=item   * Label Type
553
 
554
This will be one of 'trunk', 'branches' or 'tags'.
555
 
556
Normally labels are placed on the 'tags' subdirectory of a package.
557
 
558
=item   * Simple Label
559
 
341 dpurdie 560
The label tag. It can only contain Alphanumerics and the characters :-_.
267 dpurdie 561
In practice this can be a simple version number as the labels are held the
562
context of a package.
563
 
564
=item   * Peg
565
 
566
A peg consists of a '@' and a number string at the end of the label.
567
 
568
=back
569
 
570
An example of a full label is: repo/package/component/tags/label_text@1234
571
 
572
Not all operation support the full label syntax. The 'peg' is not allowed in
573
a label that will be used as a target of a repository copy operation, nor
574
is the 'Package Path'.
575
 
576
Full labels can be used in operations that specify the source of a
577
copy operation, such as a delete, rename or clone operation.
578
 
579
All operations report a 'Full Label' that can be used to reference the
341 dpurdie 580
repository at any time in the future. This is the 'tag' that needs to be
267 dpurdie 581
provided to 'Release Manager in order to reproduce the package.
582
 
583
=head1 EXAMPLE
584
 
585
jats svnlabel -label daf_br_23.0.0.syd
586
 
587
=cut
588