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