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