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
        #
361 dpurdie 358
        $session = NewSessionByUrl ( $opt_packagebase, 0, $session );
267 dpurdie 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;
361 dpurdie 369
        $session = NewSessionByUrl ( $1, 0, $session );
267 dpurdie 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
 
361 dpurdie 399
=for htmltoc    GENERAL::Subversion::
400
 
267 dpurdie 401
=head1 NAME
402
 
403
jats_svnlabel - Subversion label operations
404
 
405
=head1 SYNOPSIS
406
 
361 dpurdie 407
jats svnlabel [options] C<label>
267 dpurdie 408
 
409
 Options:
410
    -help                  - brief help message
411
    -help -help            - Detailed help message
412
    -man                   - Full documentation
413
    -available             - Check for label availablility
414
    -check                 - Check for label existence
415
    -clone=xxx             - Clone a package version
416
    -delete                - Delete label from the repository
417
    -label                 - Labels a Package
418
    -list                  - List lables in a package
419
    -rename=xxx            - Rename a label
420
 
421
 Modifiers
422
    -branch                - Use branches, not tags
423
    -replace               - Replace existing labels. Use with -label
424
    -comment=text          - Comment to add to repository operations
425
    -workspace=path        - Path to a workspace to label
426
    -packagebase=path      - Repostory path to package base
427
 
428
=head1 OPTIONS
429
 
430
=over 8
431
 
432
=item B<-help>
433
 
434
Print a brief help message and exits.
435
 
436
=item B<-help -help>
437
 
438
Print a detailed help message with an explanation for each option.
439
 
440
=item B<-man>
441
 
442
Prints the manual page and exits.
443
 
444
=item B<-clone=xxx>
445
 
446
This option will copy a labled version of a package to a new label.
447
 
448
=item B<-delete>
449
 
450
This option will delete the specified label from the repository
451
 
452
=item B<-available>
453
 
454
This option will check for the lables non-existence. An error will be reported
455
if the label exists.
456
 
457
=item B<-check>
458
 
459
This option will check for the lables existence. An error will be reported
460
if the label does not exist.
461
 
462
=item B<-label>
463
 
464
This option will label a workspace.
465
 
466
The -replace option may be used to force labels to be moved.
467
 
468
=item B<-rename=xxx>
469
 
470
This option will rename a label. The new name of the label is provided as the
471
argument after the option. If any further operation are to be performed the
472
new label name will be used.
473
 
474
=item B<-list>
475
 
476
This option will case all lables for the related package to be shown. The
477
command assumes that the repository is in a trunk/tags/branches format.
478
 
479
By default tags are shown. Branches may be shown with the -branches option.
480
 
481
=item B<-replace>
482
 
483
This option may be used with the -label command to allow existing labels to
484
be replaced.
485
 
486
=item B<-comment=text>
487
 
488
This option provides text to be used to document the operation in the log.
489
 
490
If none is provided, then the utility will use a simple comment of its own.
491
 
492
=item B<-workspace=path>
493
 
494
This option can be used to specify the path to a workspace to be labeled.
495
 
496
If not provided then the utility will use the current directory to determine
497
the root of the workspace.
498
 
499
=item B<packagebase=path>
500
 
501
This option can be used to specify the path to a package within a repository.
502
 
503
If the 'label' contains a package base, then it will be extracted and used.
504
 
505
If not provided and the utility is within a workspace, then the package base will
506
be taken to be that of the package in the workspace.
507
 
508
=item B<-branch>
509
 
510
This option modifies all commands. It causes the labeling operations to be
511
performed on a the packages 'branches' area instead of the default 'tags'
512
area.
513
 
514
=back
515
 
516
=head1 DESCRIPTION
517
 
518
This program provides a number of useful Subversion labeling operations. These
519
are:
520
 
521
=over 8
522
 
361 dpurdie 523
=item   *
267 dpurdie 524
 
361 dpurdie 525
check - check existance of a label
267 dpurdie 526
 
361 dpurdie 527
=item   *
267 dpurdie 528
 
361 dpurdie 529
available - check non-existance of a label
267 dpurdie 530
 
361 dpurdie 531
=item   *
267 dpurdie 532
 
361 dpurdie 533
list - list the label on a package
267 dpurdie 534
 
361 dpurdie 535
=item   *
267 dpurdie 536
 
361 dpurdie 537
rename - rename a label
538
 
539
=item   *
540
 
541
label - label a workspace
542
 
543
=item   *
544
 
545
delete - delete a label
546
 
547
=item   *
548
 
549
clone - duplicate a label
550
 
267 dpurdie 551
=back
552
 
553
The various operations may be mixed in the one command. The order of the
554
operations is: check, available, list, rename, label, delete and clone
555
 
556
=head2 LABEL format
557
 
558
A 'label' as used by JATS within a Subversion repository, may have four elements.
559
These are:
560
 
561
=over
562
 
563
=item   * Package Path
564
 
565
Any text preceeding a / will be taken to be a package path. This identifies the
566
root of the package within the repository.
567
 
568
=item   * Label Type
569
 
570
This will be one of 'trunk', 'branches' or 'tags'.
571
 
572
Normally labels are placed on the 'tags' subdirectory of a package.
573
 
574
=item   * Simple Label
575
 
341 dpurdie 576
The label tag. It can only contain Alphanumerics and the characters :-_.
267 dpurdie 577
In practice this can be a simple version number as the labels are held the
578
context of a package.
579
 
580
=item   * Peg
581
 
582
A peg consists of a '@' and a number string at the end of the label.
583
 
584
=back
585
 
586
An example of a full label is: repo/package/component/tags/label_text@1234
587
 
588
Not all operation support the full label syntax. The 'peg' is not allowed in
589
a label that will be used as a target of a repository copy operation, nor
590
is the 'Package Path'.
591
 
592
Full labels can be used in operations that specify the source of a
593
copy operation, such as a delete, rename or clone operation.
594
 
595
All operations report a 'Full Label' that can be used to reference the
341 dpurdie 596
repository at any time in the future. This is the 'tag' that needs to be
267 dpurdie 597
provided to 'Release Manager in order to reproduce the package.
598
 
599
=head1 EXAMPLE
600
 
601
jats svnlabel -label daf_br_23.0.0.syd
602
 
603
=cut
604