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
    #
379 dpurdie 153
    #   Remove trailing / on all directory names
267 dpurdie 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}" )
379 dpurdie 214
        if ( !$opt_branch && (($session->WsType) eq 'tags') );
267 dpurdie 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
#
379 dpurdie 296
#                   Calculateion may be bypassed in the global $src_label
297
#                   is specified.
298
#
267 dpurdie 299
# Inputs          : $base
379 dpurdie 300
#                   $name           - May contain hint
301
#                                     Prefixed with 'tags/' or 'branches/'
267 dpurdie 302
#
303
# Returns         : Full label
304
#
305
sub make_src_label
306
{
307
    return $src_label if ( $src_label );
308
 
309
    my ($base, $name) = @_;
379 dpurdie 310
    my $result = $name;
311
    unless ( $name =~ m~(^branches/)|(^tags)~ )
312
    {
313
        $result = ($opt_branch ? 'branches/' : 'tags/' ) . $name;
314
    }
315
    return $base . '/' . $result;
267 dpurdie 316
}
317
 
318
 
319
#-------------------------------------------------------------------------------
320
# Function        : LocateRoots
321
#
322
# Description     : Determine workspace root and associated
323
#                   package root
324
#
325
#                   Uses several hint to figure it out
326
#                       The default is the package in the current directory
327
#                       -workspace - may address a workspace
328
#                       -packagebase - may specify a package base
329
#                                      Does not work with -label
330
#                                      as we need a workspace
331
#
332
#
333
# Inputs          : None - uses globals
334
#
335
# Returns         : Setup global variables
336
#
337
sub LocateRoots
338
{
339
    #
340
    #   Use current directory as the workspace unless the user
341
    #   has specified a different one
342
    #
343
    $session = NewSessionByWS( $opt_workspace || '.', $opt_workspace ? 0 : 1 );
344
 
345
    Verbose ("Determine the current workspace root" );
346
    my $ws_root = $session->SvnLocateWsRoot(1) || '';
347
 
348
    #
349
    #   Only need a WS root for the label operation
350
    #   Every thing else can live without it
351
    #
352
    Error ("Cannot determine source Workspace") if ( $opt_label && !$ws_root );
353
 
354
    #
355
    #   Calculate the package base
356
    #       - User specified
357
    #       - Extacted from label
358
    #       - Extracted from WorkSpace
359
    #           - User specified Workspace
360
    #           - Current directory
361
    #
362
    if ( $opt_packagebase )
363
    {
364
        #
365
        #   User has given us the package base
366
        #
361 dpurdie 367
        $session = NewSessionByUrl ( $opt_packagebase, 0, $session );
267 dpurdie 368
        $session->SvnValidatePackageRoot();
369
    }
375 dpurdie 370
    elsif ( (!$opt_label ) && $label && $label =~ m~(.+)(/(tags|branches|trunk)(/|@)(.+))~ )
267 dpurdie 371
    {
372
        #
375 dpurdie 373
        #   Attempt to extract it from the label, but only if we are not
374
        #   labeling a sandbox.
267 dpurdie 375
        #   Remove it from the label
376
        #
377
        $src_label = $2;
378
        $label = $5;
361 dpurdie 379
        $session = NewSessionByUrl ( $1, 0, $session );
267 dpurdie 380
        $session->SvnValidatePackageRoot();
381
        $src_label = $session->Full . $src_label;
382
    }
383
    elsif ( $ws_root )
384
    {
385
        # $s2 = $session;
386
    }
387
    else
388
    {
389
        Error ("Cannot determine the Package Base");
390
    }
391
    $pkg_root = $session->Full;
392
 
393
    #
394
    #   Everything needs a $pkg_root
395
    #
396
    Error ("Cannot determine Package Base") unless ( $pkg_root  );
397
 
398
    Verbose ("Workspace root: $ws_root");
399
    Verbose ("Package root  : $pkg_root");
400
#DebugDumpData ("Session", $session );
401
}
402
 
403
#-------------------------------------------------------------------------------
404
#   Documentation
405
#
406
 
407
=pod
408
 
361 dpurdie 409
=for htmltoc    GENERAL::Subversion::
410
 
267 dpurdie 411
=head1 NAME
412
 
413
jats_svnlabel - Subversion label operations
414
 
415
=head1 SYNOPSIS
416
 
361 dpurdie 417
jats svnlabel [options] C<label>
267 dpurdie 418
 
419
 Options:
420
    -help                  - brief help message
421
    -help -help            - Detailed help message
422
    -man                   - Full documentation
423
    -available             - Check for label availablility
424
    -check                 - Check for label existence
425
    -clone=xxx             - Clone a package version
426
    -delete                - Delete label from the repository
427
    -label                 - Labels a Package
428
    -list                  - List lables in a package
429
    -rename=xxx            - Rename a label
430
 
431
 Modifiers
432
    -branch                - Use branches, not tags
433
    -replace               - Replace existing labels. Use with -label
434
    -comment=text          - Comment to add to repository operations
435
    -workspace=path        - Path to a workspace to label
436
    -packagebase=path      - Repostory path to package base
437
 
438
=head1 OPTIONS
439
 
440
=over 8
441
 
442
=item B<-help>
443
 
444
Print a brief help message and exits.
445
 
446
=item B<-help -help>
447
 
448
Print a detailed help message with an explanation for each option.
449
 
450
=item B<-man>
451
 
452
Prints the manual page and exits.
453
 
454
=item B<-clone=xxx>
455
 
456
This option will copy a labled version of a package to a new label.
457
 
458
=item B<-delete>
459
 
460
This option will delete the specified label from the repository
461
 
462
=item B<-available>
463
 
464
This option will check for the lables non-existence. An error will be reported
465
if the label exists.
466
 
467
=item B<-check>
468
 
469
This option will check for the lables existence. An error will be reported
470
if the label does not exist.
471
 
472
=item B<-label>
473
 
474
This option will label a workspace.
475
 
476
The -replace option may be used to force labels to be moved.
477
 
478
=item B<-rename=xxx>
479
 
480
This option will rename a label. The new name of the label is provided as the
481
argument after the option. If any further operation are to be performed the
482
new label name will be used.
483
 
484
=item B<-list>
485
 
486
This option will case all lables for the related package to be shown. The
487
command assumes that the repository is in a trunk/tags/branches format.
488
 
489
By default tags are shown. Branches may be shown with the -branches option.
490
 
491
=item B<-replace>
492
 
493
This option may be used with the -label command to allow existing labels to
494
be replaced.
495
 
496
=item B<-comment=text>
497
 
498
This option provides text to be used to document the operation in the log.
499
 
500
If none is provided, then the utility will use a simple comment of its own.
501
 
502
=item B<-workspace=path>
503
 
504
This option can be used to specify the path to a workspace to be labeled.
505
 
506
If not provided then the utility will use the current directory to determine
507
the root of the workspace.
508
 
509
=item B<packagebase=path>
510
 
511
This option can be used to specify the path to a package within a repository.
512
 
513
If the 'label' contains a package base, then it will be extracted and used.
514
 
515
If not provided and the utility is within a workspace, then the package base will
516
be taken to be that of the package in the workspace.
517
 
518
=item B<-branch>
519
 
520
This option modifies all commands. It causes the labeling operations to be
521
performed on a the packages 'branches' area instead of the default 'tags'
522
area.
523
 
524
=back
525
 
526
=head1 DESCRIPTION
527
 
528
This program provides a number of useful Subversion labeling operations. These
529
are:
530
 
531
=over 8
532
 
361 dpurdie 533
=item   *
267 dpurdie 534
 
361 dpurdie 535
check - check existance of a label
267 dpurdie 536
 
361 dpurdie 537
=item   *
267 dpurdie 538
 
361 dpurdie 539
available - check non-existance of a label
267 dpurdie 540
 
361 dpurdie 541
=item   *
267 dpurdie 542
 
375 dpurdie 543
list - list the labels on a package
267 dpurdie 544
 
361 dpurdie 545
=item   *
267 dpurdie 546
 
361 dpurdie 547
rename - rename a label
548
 
549
=item   *
550
 
551
label - label a workspace
552
 
553
=item   *
554
 
555
delete - delete a label
556
 
557
=item   *
558
 
559
clone - duplicate a label
560
 
267 dpurdie 561
=back
562
 
563
The various operations may be mixed in the one command. The order of the
564
operations is: check, available, list, rename, label, delete and clone
565
 
566
=head2 LABEL format
567
 
568
A 'label' as used by JATS within a Subversion repository, may have four elements.
569
These are:
570
 
571
=over
572
 
573
=item   * Package Path
574
 
575
Any text preceeding a / will be taken to be a package path. This identifies the
576
root of the package within the repository.
577
 
578
=item   * Label Type
579
 
580
This will be one of 'trunk', 'branches' or 'tags'.
581
 
582
Normally labels are placed on the 'tags' subdirectory of a package.
583
 
584
=item   * Simple Label
585
 
341 dpurdie 586
The label tag. It can only contain Alphanumerics and the characters :-_.
267 dpurdie 587
In practice this can be a simple version number as the labels are held the
588
context of a package.
589
 
590
=item   * Peg
591
 
592
A peg consists of a '@' and a number string at the end of the label.
593
 
594
=back
595
 
596
An example of a full label is: repo/package/component/tags/label_text@1234
597
 
598
Not all operation support the full label syntax. The 'peg' is not allowed in
599
a label that will be used as a target of a repository copy operation, nor
600
is the 'Package Path'.
601
 
602
Full labels can be used in operations that specify the source of a
603
copy operation, such as a delete, rename or clone operation.
604
 
605
All operations report a 'Full Label' that can be used to reference the
341 dpurdie 606
repository at any time in the future. This is the 'tag' that needs to be
267 dpurdie 607
provided to 'Release Manager in order to reproduce the package.
608
 
609
=head1 EXAMPLE
610
 
611
jats svnlabel -label daf_br_23.0.0.syd
612
 
613
=cut
614