Subversion Repositories DevTools

Rev

Rev 363 | Rev 379 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
311 dpurdie 1
########################################################################
2
# Copyright (C) 1998-2008 ERG Limited, All rights reserved
3
#
4
# Module name   : jats_svn.pl
5
# Module type   : Jats Utility
6
# Compiler(s)   : Perl
7
# Environment(s): Jats
8
#
9
# Description   : A script to perform a number of SVN utility functions
10
#                 The script will:
11
#                   Delete a package
12
#                   Create a package
13
#                   Import source to a package
14
#
15
#
16
#......................................................................#
17
 
18
require 5.006_001;
19
use strict;
20
use warnings;
21
use JatsError;
22
use JatsSvn qw(:All);
23
use JatsLocateFiles;
24
 
25
use Pod::Usage;                                 # required for help support
26
use Getopt::Long qw(:config require_order);     # Stop on non-option
27
use Cwd;
28
use File::Path;
29
use File::Copy;
30
use File::Basename;
31
use File::Compare;
32
 
33
my $VERSION = "1.0.0";                          # Update this
34
 
35
#
36
#   Options
37
#
38
my $opt_debug   = $ENV{'GBE_DEBUG'};            # Allow global debug
39
my $opt_verbose = $ENV{'GBE_VERBOSE'};          # Allow global verbose
40
my $opt_help = 0;
41
 
42
#
43
#   Globals
44
#
45
my $opr_done;                                   # User has done something
46
 
47
#-------------------------------------------------------------------------------
48
# Function        : Mainline Entry Point
49
#
50
# Description     :
51
#
52
# Inputs          :
53
#
54
my $result = GetOptions (
55
                "help:+"        => \$opt_help,              # flag, multiple use allowed
56
                "manual:3"      => \$opt_help,              # flag
57
                "verbose:+"     => \$opt_verbose,           # flag, multiple use allowed
58
 
59
                );
60
 
61
                #
62
                #   UPDATE THE DOCUMENTATION AT THE END OF THIS FILE !!!
63
                #
64
 
65
#
66
#   Process help and manual options
67
#
68
pod2usage(-verbose => 0, -message => "Version: $VERSION") if ($opt_help == 1 || ! $result);
69
pod2usage(-verbose => 1) if ($opt_help == 2 );
70
pod2usage(-verbose => 2) if ($opt_help > 2);
71
 
72
#
73
#   Configure the error reporting process now that we have the user options
74
#
75
ErrorConfig( 'name'    =>'SVN',
76
             'verbose' => $opt_verbose,
77
            );
78
 
79
#
369 dpurdie 80
#   Reconfigure the options parser to allow subcommands to parse options
311 dpurdie 81
#
82
Getopt::Long::Configure('permute');
83
 
84
#
85
#   Process command
86
#   First command line argument is a subversion command
87
#
88
my $cmd = shift @ARGV || "help";
89
CreatePackage()                        if ( $cmd =~ m/^create/ );
90
DeletePackage()                        if ( $cmd =~ m/^delete-package/ );
91
ImportPackage()                        if ( $cmd =~ m/^import/ );
92
SvnRepoCmd($cmd, @ARGV)                if ( $cmd eq 'ls' );
363 dpurdie 93
TestSvn()                              if ($cmd eq 'test');
369 dpurdie 94
ShowPaths()                            if ( $cmd =~ m/^path/ );
95
ShowTag()                              if ( $cmd =~ m/^tag/ );
96
ShowUrl()                              if ( $cmd =~ m/^url/ );
311 dpurdie 97
 
98
pod2usage(-verbose => 0, -message => "No valid operations specified") unless ( $opr_done );
99
exit 0;
100
 
101
#-------------------------------------------------------------------------------
369 dpurdie 102
# Function        : ShowPaths
103
#
104
# Description     : Show PATHS
105
#
106
# Inputs          : 
107
#
108
# Returns         : 
109
#
110
sub ShowPaths
111
{
112
    #
113
    #   Parse more options
114
    #
115
    GetOptions (
116
                "help:+"        => \$opt_help,
117
                "manual:3"      => \$opt_help,
118
                ) || Error ("Invalid command line" );
119
 
120
    #
121
    #   Subcommand specific help
122
    #
123
    SubCommandHelp( $opt_help, "Subversion Paths") if ($opt_help || $#ARGV >= 0);
124
 
125
    #
126
    #   Display known PATHS
127
    #
128
    my ( $pSVN_URLS, $pSVN_URLS_LIST) = SvnPaths();
129
    print ("Configured SubVersion Repository Paths\n");
130
    print sprintf("    %-20s %s\n", 'Tag', 'URL Prefix');
131
 
132
    foreach my $key ( @{$pSVN_URLS_LIST} )
133
    {
134
        print sprintf("    %-20s %s\n", $key || 'Default', $pSVN_URLS->{$key} );
135
    }
136
 
137
    $opr_done = 1;
138
}
139
 
140
#-------------------------------------------------------------------------------
141
# Function        : ShowTag
142
#
143
# Description     : Convert a URL into a TAG
144
#                   Convert the current workspace info into a TAG
145
#
146
# Inputs          : url                     - Url to convert (optional)
147
#                   Options
148
#                       -help[=n]           - Show help
149
#                       -man                - Show manual
150
#                       -url=url            - Convert URL
151
#                       -path=path          - Convert Workspace
152
#
153
# Returns         : Nothing
154
#
155
sub ShowTag
156
{
157
    my $opt_path;
158
    my $opt_url;
159
 
160
    #
161
    #   Parse more options
162
    #
163
    GetOptions (
164
                "help:+"        => \$opt_help,
165
                "manual:3"      => \$opt_help,
166
                "path:s"        => \$opt_path,
167
                "url:s"         => \$opt_url,
168
                ) || Error ("Invalid command line" );
169
 
170
    #
171
    #   Subcommand specific help
172
    #
173
    SubCommandHelp( $opt_help, "Url to Tag") if ($opt_help);
174
 
175
    #
176
    #   Bare argument is a URL
177
    #   If no arguments provided assume a path of the current directory
178
    #
179
    $opt_url = shift (@ARGV) if ( $#ARGV == 0 );
180
    $opt_path = '.' unless ( defined $opt_path || defined $opt_url );
181
 
182
    #
183
    #   Sanity Tests
184
    #
185
    Error ("Cannot specify both a URL and a PATH")
186
            if ( defined $opt_url && defined $opt_path );
187
    Warning ("Too many arguments") if ( $#ARGV >= 0 );
188
 
189
    #   Do all the hard work
190
    #
191
    my $uref;
192
    if ( $opt_url )
193
    {
194
        $uref = NewSessionByUrl ( $opt_url );
195
        $uref->CalcRmReference($uref->Full());
196
    }
197
    else
198
    {
199
        $uref = NewSessionByWS($opt_path, 0, 1);
200
        my $ws_root = $uref->SvnLocateWsRoot(1);
201
        $uref->CalcRmReference($uref->FullWs());
202
    }
203
 
204
    Message ("Tag is: " . $uref->RmRef() );
205
    $opr_done = 1;
206
}
207
#-------------------------------------------------------------------------------
208
# Function        : ShowUrl
209
#
210
# Description     : Convert a TAG into a URL
211
#                   Show the current workspace URL
212
#
213
# Inputs          : tag                     - Tag to convert (optional)
214
#                   Options
215
#                       -help[=n]           - Show help
216
#                       -man                - Show manual
217
#                       -tag=tag            - Convert TAG
218
#                       -path=path          - Convert Workspace
219
#
220
# Returns         : Nothing
221
#
222
sub ShowUrl
223
{
224
    my $opt_path;
225
    my $opt_tag;
226
 
227
    #
228
    #   Parse more options
229
    #
230
    GetOptions (
231
                "help:+"        => \$opt_help,
232
                "manual:3"      => \$opt_help,
233
                "path:s"        => \$opt_path,
234
                "tag:s"         => \$opt_tag,
235
                ) || Error ("Invalid command line" );
236
 
237
    #
238
    #   Subcommand specific help
239
    #
240
    SubCommandHelp( $opt_help, "Tag to Url") if ($opt_help);
241
 
242
    #
243
    #   Bare argument is a TAG
244
    #   If no arguments provided assume a path of the current directory
245
    #
246
    $opt_tag = shift (@ARGV) if ( $#ARGV == 0 );
247
    $opt_path = '.' unless ( defined $opt_path || defined $opt_tag );
248
 
249
    #
250
    #   Sanity Tests
251
    #
252
    Error ("Cannot specify both a TAG and a PATH")
253
            if ( defined $opt_tag && defined $opt_path );
254
    Warning ("Too many arguments") if ( $#ARGV >= 0 );
255
 
256
    #   Do all the hard work
257
    #
258
    my $uref;
259
    my $url;
260
    if ( $opt_tag )
261
    {
262
        $url = SvnPath2Url($opt_tag);
263
    }
264
    else
265
    {
266
        $uref = NewSessionByWS($opt_path, 0, 1);
267
        my $ws_root = $uref->SvnLocateWsRoot(1);
268
        $url = $uref->FullWsRev();
269
    }
270
 
271
    Message ("Url: $url");
272
    $opr_done = 1;
273
}
274
 
275
#-------------------------------------------------------------------------------
363 dpurdie 276
# Function        : TestSvn
277
#
278
# Description     : Test access to subversion
279
#
280
# Inputs          : None
281
#
282
# Returns         :
283
#
284
sub TestSvn
285
{
286
    #
287
    #   Parse more options
288
    #
289
    GetOptions (
290
                "help:+"        => \$opt_help,
291
                "manual:3"      => \$opt_help,
292
                ) || Error ("Invalid command line" );
293
 
294
    #
295
    #   Subcommand specific help
296
    #
297
    SubCommandHelp( $opt_help, "Test Subversion") if ($opt_help || $#ARGV >= 0);
298
 
299
    SvnUserCmd( '--version');
300
    $opr_done = 1;
301
}
302
 
303
 
304
#-------------------------------------------------------------------------------
311 dpurdie 305
# Function        : SvnRepoCmd
306
#
307
# Description     : Execute a SVN command, where the first argument
308
#                   is a repository specifier
309
#
310
# Inputs          : $cmd
311
#                   $repo_url
312
#                   @opts
313
#
314
# Returns         : 
315
#
316
sub SvnRepoCmd
317
{
318
    my ( $cmd, $repo_url, @opts ) = @_;
319
    my $uref = NewSessionByUrl ( $repo_url );
320
 
321
    SvnUserCmd( $cmd,
322
            $uref->Full,
323
            @opts,
324
            { 'credentials' => 1 });
325
 
326
    $opr_done = 1;
327
}
328
 
329
#-------------------------------------------------------------------------------
330
# Function        : DeletePackage
331
#
332
# Description     : Delete a Package structure within a Repository
333
#                   Intended for test usage
334
#
335
# Inputs          : URL                 - Url to Repo + Package Base
336
#
337
# Returns         : 
338
#
339
sub DeletePackage
340
{
341
    #
342
    #   Parse more options
343
    #
344
    GetOptions (
345
                "help:+"        => \$opt_help,
346
                "manual:3"      => \$opt_help,
347
                ) || Error ("Invalid command line" );
348
 
349
    #
350
    #   Subcommand specific help
351
    #
352
    SubCommandHelp( $opt_help, "Delete a Package") if ($opt_help || $#ARGV < 0);
353
 
354
    #
355
    #   Sanity Tests
356
    #
357
    Message ("Delete Entire Package Tree" );
358
    Warning ("Too many arguments: @ARGV") if ( $#ARGV >= 1 );
359
 
360
    #
361
    #   Do all the hard work
362
    #       Create
363
    #       Import
364
    #       Label
365
    #
366
    my $uref = NewSessionByUrl ( $ARGV[0] );
367
    $uref->SvnValidatePackageRoot();
368
    $uref->SvnDelete (
369
                      'target'      => $uref->Full,
370
                      'comment'   => ['Deleted by user command','jats svn delete-package'],
371
                      'noerror'     => 0,
372
                      );
373
    $opr_done = 1;
374
}
375
 
376
#-------------------------------------------------------------------------------
377
# Function        : CreatePackage
378
#
379
# Description     : Create a Package structure within a Repository
380
#                   Optionally Import Data
381
#                   Optionally Tag the import
382
#                   Optionally Tag the import on a branch
383
#
384
# Inputs          : URL                 - Url to Repo + Package Base
385
#                   Options             - Command modifiers
386
#                       -import=path    - Import named directory
387
#                       -label=name     - Label the result
388
#                       -tag=name       - Import to Tag Only
389
#                       -branch=name    - Import to Branch only
390
#                       -new            - Must be new package
391
#                       -replace        - Replace existing
392
#
393
# Returns         : 
394
#
395
sub CreatePackage
396
{
397
    my $opt_import;
398
    my $opt_tag;
399
    my $opt_branch;
400
    my $opt_trunk;
401
    my $opt_new;
402
    my $opt_label;
403
    my $opt_replace;
404
    my $pname;
405
    my $type;
406
 
407
 
408
    Message ("Create New Package Version" );
409
 
410
    #
411
    #   Parse more options
412
    #
413
    GetOptions (
414
                "help:+"        => \$opt_help,
415
                "manual:3"      => \$opt_help,
416
                "verbose:+"     => \$opt_verbose,
417
                "import=s"      => \$opt_import,
418
                "new"           => \$opt_new,
419
                "branch=s"      => \$opt_branch,
420
                "trunk"         => \$opt_trunk,
421
                "tag=s"         => \$opt_tag,
422
                "label=s"       => \$opt_label,
423
                "replace"       => \$opt_replace,
424
 
425
                ) || Error ("Invalid command line" );
426
 
427
    #
428
    #   Subcommand specific help
429
    #
430
    SubCommandHelp( $opt_help, "Create a Package Version") if ($opt_help || $#ARGV < 0);
431
 
432
    #
369 dpurdie 433
    #   Alter the error reporting parameters
311 dpurdie 434
    #
435
    ErrorConfig( 'verbose' => $opt_verbose );
436
 
437
    #
438
    #   Sanity Tests
439
    #
440
    my $count = 0;
441
    $count++ if ( $opt_trunk );
442
    $count++ if ( $opt_branch );
443
    $count++ if ( $opt_tag );
444
    Error ("Conflicting options: -trunk, -tag, -branch") if ( $count > 1 );
445
    Error ("Nothing imported to be labeled") if ( $count && !$opt_import );
446
    Error ("Import path does not exist: $opt_import") if ( $opt_import && ! -d $opt_import );
447
    Error ("Conflicting options: new and replace") if ( $opt_new && $opt_replace );
448
 
449
    ($type, $opt_label) = ('tags', $opt_tag)            if ( $opt_tag);
450
    ($type, $opt_label) = ('branches', $opt_branch)     if ( $opt_branch );
451
    ($type, $opt_label) = ('trunk', $opt_label)         if ( $opt_trunk);
452
 
453
    #
454
    #   Do all the hard work
455
    #       Create
456
    #       Import
457
    #       Label
458
    #
459
    my $uref = NewSessionByUrl ( $ARGV[0] );
460
    $uref->SvnCreatePackage (
461
                      'import'  => $opt_import,
462
                      'label'   => $opt_label,
463
                      'type'    => $type,
464
                      'new'     => $opt_new,
465
                      'replace' => $opt_replace,
466
                      );
467
    Message ("Repository Ref: " . $uref->RmRef);
468
    $opr_done = 1;
469
}
470
 
471
#-------------------------------------------------------------------------------
472
# Function        : ImportPackage
473
#
474
# Description     : Import a new version of a package
475
#                   Take great care to reuse file-versions that are already in
476
#                   the  package
477
#
369 dpurdie 478
#                   Intended to allow the importation of multiple
311 dpurdie 479
#                   versions of a package
480
#
481
# Inputs          : 
482
#
483
# Returns         : 
484
#
485
sub ImportPackage
486
{
487
    Message ("Import Package Version" );
488
 
489
    #
490
    #   Options
491
    #
492
    my $opt_package;
493
    my $opt_dir;
494
    my $opt_label;
495
    my $opt_replace = 0;
496
    my $opt_reuse;
497
    my $opt_workdir = "SvnImportDir";
498
    my $opt_delete = 1;
499
 
500
    #
501
    #   Other globals
502
    #
503
    my $url_label;
504
 
505
    #
506
    #   Configuration options
507
    #
508
    my $result = GetOptions (
509
                    "help:+"        => \$opt_help,
510
                    "manual:3"      => \$opt_help,
511
                    "verbose:+"     => \$opt_verbose,
512
                    "package=s"     => \$opt_package,
513
                    "dir=s"         => \$opt_dir,
514
                    "label=s"       => \$opt_label,
515
                    "replace"       => \$opt_replace,
516
                    "reuse"         => \$opt_reuse,
517
                    "workspace=s"   => \$opt_workdir,
518
                    "delete!"       => \$opt_delete,
519
 
520
                    #
521
                    #   Update documentation at the end of the file
522
                    #
523
                    ) || Error ("Invalid command line" );
524
 
525
    #
526
    #   Insert defaults
341 dpurdie 527
    #   User can specify base package via -package or a non-options argument
311 dpurdie 528
    #
529
    $opt_package = $ARGV[0] unless ( $opt_package );
530
 
531
    #
532
    #   Subcommand specific help
533
    #
534
    SubCommandHelp( $opt_help, "Import directory to a Package")
535
        if ($opt_help || ! $opt_package );
536
 
537
    #
369 dpurdie 538
    #   Alter the error reporting parameters
311 dpurdie 539
    #
540
    ErrorConfig( 'verbose' => $opt_verbose );
541
 
542
    #
543
    #   Configure the error reporting process now that we have the user options
544
    #
545
    Error ("No package URL specified") unless ( $opt_package );
546
    Error ("No base directory specified") unless ( $opt_dir );
547
    Error ("Invalid base directory: $opt_dir") unless ( -d $opt_dir );
548
 
549
    #
550
    #   Create an SVN session
551
    #
552
    my $svn = NewSessionByUrl ( $opt_package );
553
 
554
    #
555
    #   Ensure that the required label is available
556
    #
557
    if ( $opt_label )
558
    {
559
        $opt_label = SvnIsaSimpleLabel ($opt_label);
560
        $url_label = $svn->BranchName( $opt_label, 'tags' );
561
        $svn->SvnValidateTarget (
562
                        'target' => $url_label,
563
                        'available' => 1,
564
                        ) unless ( $opt_replace );
565
    }
566
 
567
    #
568
    #   Create a workspace based on the users package
569
    #   Allow the workspace to be reused to speed up multiple
570
    #   operations
571
    #
572
    unless ( $opt_reuse && -d $opt_workdir )
573
    {
574
        Message ("Creating Workspace");
575
        rmtree( $opt_workdir );
576
 
577
        $svn->SvnValidatePackageRoot ();
578
        #DebugDumpData( 'Svn', $svn );
579
        $svn->SvnValidateTarget (
580
                            'cmd'    => 'SvnImporter',
581
                            'target' => $svn->Full,
582
                            'require' => 1,
583
                            );
584
 
585
        $svn->SvnCo ( $svn->Full . '/trunk', $opt_workdir );
586
        Error ("Cannot locate the created Workspace")
587
            unless ( -d $opt_workdir );
588
    }
589
    else
590
    {
591
        Message ("Reusing Workspace");
592
    }
593
 
594
    #
595
    #   Determine differences between the two folders
596
    #       Create structures for each directory
597
    #
598
    Message ("Determine Files in packages");
599
 
600
    my $search = JatsLocateFiles->new("--Recurse=1",
601
                                       "--DirsToo",
602
                                       "--FilterOutRe=/\.svn/",
603
                                       "--FilterOutRe=/\.svn\$",
604
                                       "--FilterOutRe=^/${opt_workdir}\$",
605
                                       "--FilterOutRe=^/${opt_workdir}/",
606
                                       );
607
    my @ws = $search->search($opt_workdir);
608
    my @dir = $search->search($opt_dir);
609
 
610
    #Information ("WS Results", @ws);
611
    #Information ("DIR Results", @dir);
612
 
613
    #
614
    #   Create a hash the Workspace and the User dir
615
    #   The key will be file names
616
    #
617
    my %ws;  map ( $ws{$_} = 1 , @ws );
618
    my %dir; map ( $dir{$_} = 1 , @dir );
619
 
620
    #
621
    #   Create a hash of common elements
622
    #   Removing then from the other two
623
    #
624
    my %common;
625
    foreach ( keys %ws )
626
    {
627
        next unless ( exists $dir{$_} );
628
        $common{$_} = 1;
629
        delete $ws{$_};
630
        delete $dir{$_};
631
    }
632
 
633
    #DebugDumpData( 'WS', \%ws );
634
    #DebugDumpData( 'DIR', \%dir );
635
    #DebugDumpData( 'COMMON', \%common );
636
 
637
    #
638
    #   Add New Files
639
    #   Won't add empty directories at this point
640
    #
641
    #   Process by sorted list
642
    #   This will ensure we process parent directories first
643
    #
644
    my @added = sort keys %dir;
645
 
646
    if ( @added )
647
    {
648
        foreach my $file ( @added  )
649
        {
650
            my $src = "$opt_dir/$file";
651
            my $target = "$opt_workdir/$file";
652
 
653
            if ( -d $src )
654
            {
655
                mkdir ( $target ) unless (-d $target);
656
            }
657
            else
658
            {
659
 
660
                my $path = dirname ( $target);
661
                mkdir ( $path ) unless (-d $path);
662
 
663
                Verbose ("Adding $file");
664
                unless (File::Copy::copy( $src, $target ))
665
                {
666
                    Error("Failed to transfer file [$file]: $!");
667
                }
668
            }
669
        }
670
 
671
        #
672
        #   Inform Subversion about the added files
673
        #   The command line does have a finite length, so add them 200 at a
674
        #   time.
675
        #
676
 
677
        my $base = 0;
678
        my $num = $#added;
679
        Message ("Update the workspace: Added $num files");
680
 
681
        while ( $base <= $num )
682
        {
683
            my $end = $base + 200;
684
            $end = $num if ( $end > $num );
685
 
686
            $svn->SvnCmd ( 'add'
687
                            , '--depth=empty'
688
                            , '--parents'
689
                            , map ("$opt_workdir/$_", @added[$base .. $end] ),
690
                            { 'error' => 'Adding files to workspace' } );
691
 
692
            $base = $end + 1;
693
        }
694
    }
695
 
696
    #
697
    #   Remove files
698
    #   Don't really need to delete the files as the svn delete
369 dpurdie 699
    #   command will do this too. Just do it anyway
311 dpurdie 700
    #
701
    my @rm_files = sort keys %ws;
702
    if ( @rm_files )
703
    {
704
        foreach my $file ( @rm_files  )
705
        {
706
            Verbose ("Removing $file");
707
            unlink "$opt_workdir/$file";
708
        }
709
 
710
        #
711
        #   Inform Subversion about the removed files
712
        #
713
        my $base = 0;
714
        my $num = $#rm_files;
715
        Message ("Update the workspace: Removed $num Files");
716
 
717
        while ( $base <= $num )
718
        {
719
            my $end = $base + 200;
720
            $end = $num if ( $end > $num );
721
 
722
            $svn->SvnCmd ( 'delete', map ("$opt_workdir/$_", @rm_files[$base .. $end] ),
723
                            { 'error' => 'Deleting files from workspace' } );
724
 
725
 
726
            $base = $end + 1;
727
        }
728
    }
729
 
730
    #
731
    #   The common files may have changed
732
    #   Simply copy them all in and let subversion figure it out
733
    #
734
    foreach my $file ( sort keys %common  )
735
    {
736
        my $src = "$opt_dir/$file";
737
        my $target = "$opt_workdir/$file";
738
 
739
        next if ( -d $src );
740
        if ( File::Compare::compare ($src, $target) )
741
        {
742
            Verbose ("Transfer $file");
743
            unlink $target;
744
            unless (File::Copy::copy( $src, $target ))
745
            {
746
                Error("Failed to transfer file [$file]: $!",
747
                      "Src: $src",
748
                      "Tgt: $target");
749
            }
750
        }
751
    }
752
 
753
    #
754
    #   Commit the workspace
755
    #   This will go back onto the trunk
756
    #
757
    $svn = NewSessionByWS( $opt_workdir );
758
    $svn->SvnCi ('comment' => "Checkin by Svn Import" );
759
    Message ("Repository Ref: " . $svn->RmRef);
760
 
761
    #
762
    #   Label the result
763
    #   The workspace will have been updated, so we can use it as the base for
764
    #   the labeling process
765
    #
766
    if ( $opt_label )
767
    {
768
        $svn->SvnCopyWs (
769
                       target => $url_label,
770
                       'noswitch' => 1,
771
                       'replace' => $opt_replace,
772
                       'comment' => 'Created by Jats Svn Import',
773
                       );
774
        Message ("Repository Ref: " . $svn->RmRef);
775
    }
776
 
777
    #
778
    #   Clean up
779
    #
780
    if ( $opt_delete && ! $opt_reuse )
781
    {
782
        Message ("Delete Workspace");
783
        rmtree( $opt_workdir );
784
    }
785
 
786
    $opr_done = 1;
787
}
788
 
789
#-------------------------------------------------------------------------------
790
# Function        : SubCommandHelp
791
#
792
# Description     : Provide help on a subcommand
793
#
794
# Inputs          : $help_level             - Help Level 1,2,3
795
#                   $topic                  - Topic Name
796
#
797
# Returns         : This function does not return
798
#
799
sub SubCommandHelp
800
{
801
    my ($help_level, $topic) = @_;
802
    my @sections;
803
    #
804
    #   Spell out the section we want to display
805
    #
806
    #   Note:
807
    #   Due to bug in pod2usage can't use 'head1' by itself
808
    #   Each one needs a subsection.
809
    #
810
    push @sections, qw( NAME SYNOPSIS ) ;
811
    push @sections, qw( ARGUMENTS OPTIONS ) if ( $help_level > 1 );
812
    push @sections, qw( DESCRIPTION )       if ( $help_level > 2 );
813
 
814
    #
815
    #   Extract section from the POD
816
    #
817
    pod2usage({-verbose => 99,
818
               -noperldoc => 1,
819
               -sections => $topic . '/' . join('|', @sections) } );
820
}
821
 
822
 
823
 
824
#-------------------------------------------------------------------------------
825
#   Documentation
826
#   NOTE
827
#
828
#   Each subcommand MUST have
829
#   head1 section as used by the subcommand
830
#       This should be empty, as the contents will NOT be displayed
831
#   head2 sections called
832
#       NAME SYNOPSIS ARGUMENTS OPTIONS DESCRIPTION
833
#
834
#=head1 xxxxxx
835
#=head2 NAME
836
#=head2 SYNOPSIS
837
#=head2 ARGUMENTS
838
#=head2 OPTIONS
839
#=head2 DESCRIPTION
840
#
841
 
842
=pod
843
 
361 dpurdie 844
=for htmltoc    GENERAL::Subversion::
845
 
311 dpurdie 846
=head1 NAME
847
 
848
jats svn - Miscellaneous SubVersion Operations
849
 
850
=head1 SYNOPSIS
851
 
852
jats svn [options] command [command options]
853
 
854
 Options:
855
    -help[=n]              - Help message, [n=1,2,3]
856
    -man                   - Full documentation [-help=3]
857
    -verbose[=n]           - Verbose command operation
858
 
859
 Common Command Options:
860
    All command support suboptions to provide command specific help
861
 
862
    -help[=n]              - Help message, [n=1,2,3]
863
    -man                   - Full documentation [-help=3]
864
 
865
 Commands are:
363 dpurdie 866
    test                   - Test access to subversion
369 dpurdie 867
    paths                  - Display Subversion tag to URL conversions
311 dpurdie 868
    ls URL                 - List Repo contents for URL
369 dpurdie 869
    tag [URL]              - Convert URL or Path to a Release Manager Tag
870
    url [TAG]              - Convert TAG or Path to a Subversion URL
311 dpurdie 871
    delete-package URL     - Delete Package Subtree
872
    create URL             - Create a new package at URL
873
    import URL             - Import files to package at URL
874
 
875
 Use the command
876
    jats svn command -h
877
 for command specific help
878
 
879
 
880
=head1 OPTIONS
881
 
882
=over
883
 
884
=item B<-help[=n]>
885
 
886
Print a help message and exit. The level of help may be either 1, 2 or
887
3 for a full manual.
888
 
889
This option may be specified multiple times to increment the help level, or
890
the help level may be directly specified as a number.
891
 
892
=item B<-man>
893
 
894
This is the same as '-help=3'.
895
The complete help is produced in a man page format.
896
 
897
=item B<--verbose[=n]>
898
 
899
This option will increase the level of verbosity of the commands.
900
 
901
If an argument is provided, then it will be used to set the level, otherwise the
902
existing level will be incremented. This option may be specified multiple times.
903
 
904
=back
905
 
906
=head1 DESCRIPTION
907
 
908
This program provides a number of useful Subversion based operations.
909
 
363 dpurdie 910
=head1 Test Subversion
911
 
912
=head2 NAME
913
 
914
Test Subversion
915
 
916
=head2 SYNOPSIS
917
 
918
    jats svn test
919
 
920
=head2 DESCRIPTION
921
 
922
This command will ensure that the subversion command line utility can be
923
located. The command will report the version of the svn client found.
924
 
369 dpurdie 925
=head1 Subversion Paths
926
 
927
=head2 NAME
928
 
929
Subversion Paths
930
 
931
=head2 SYNOPSIS
932
 
933
    jats svn paths
934
 
935
=head2 DESCRIPTION
936
 
937
This command will display the base Tags and associated URLs that are used by
938
JATS to convert a 'Subversion Tag' into a full URLs that will be used to access
939
a physical repository.
940
 
941
The 'Tags' configuration is site-specific.
942
 
311 dpurdie 943
=head1 List Repository
944
 
363 dpurdie 945
=head2 NAME
946
 
947
List Repository
948
 
949
=head2 SYNOPSIS
950
 
951
    jats svn ls <URL>
952
 
953
=head2 DESCRIPTION
954
 
311 dpurdie 955
This command will take a URL and perform a 'svn' list operation. The URL will
956
be expanded to include the site specific repository.
957
 
369 dpurdie 958
=head1 Url to Tag
959
 
960
=head2 NAME
961
 
962
Url to Tag
963
 
964
=head2 SYNOPSIS
965
 
966
    jats svn tag [Option] [tag]
967
 
968
 Options:
969
    -help[=n]              - Help message, [n=1,2,3]
970
    -man                   - Full documentation [-help=3]
971
    -path=path             - Convert specified path
972
    -url=url               - Convert specified URL
973
 
974
=head2 DESCRIPTION
975
 
976
This command will convert a URL or a PATH to a Subversion Tag that can
977
be used within the remainder of the build system. If no PATH or URL is provided,
978
then the command uses a path of the current directory.
979
 
980
The command will convert either a PATH or a URL. It will not do both.
981
 
982
The command will use the configured Subversion URL prefixes to create the Tag.
983
 
984
If a PATH is to be converted, then the PATH must address a Subversion workspace.
985
The conversion will return a Tag to the root of the Workspace and Peg it to
986
the last committed version. The command will not determine if the workspace
987
contains modified files.
988
 
989
If a URL is to be converted, then the resultant value should be used with
990
caution. The result is only as good as the provided URL and may not address
991
the root of a package.
992
 
993
=head1 Tag to Url
994
 
995
=head2 NAME
996
 
997
Tag to Url
998
 
999
=head2 SYNOPSIS
1000
 
1001
    jats svn url [Option] [url]
1002
 
1003
 Options:
1004
    -help[=n]              - Help message, [n=1,2,3]
1005
    -man                   - Full documentation [-help=3]
1006
    -path=path             - Convert specified path
1007
    -url=url               - Convert specified URL
1008
 
1009
=head2 DESCRIPTION
1010
 
1011
This command will convert a TAG or a PATH to a full URL that can be used
1012
directly by Subversion. If no PATH or TAG is provided, then the command uses a
1013
path of the current directory.
1014
 
1015
The command will convert either a TAG or a URL. It will not do both.
1016
 
1017
The command will use the configured Subversion URL prefixes to expand the TAG.
1018
 
1019
If a PATH is to be converted, then the PATH must address a Subversion workspace.
1020
The conversion will return a URL to the root of the Workspace and Peg it to
1021
the last committed version. The command will not determine if the workspace
1022
contains modified files.
1023
 
1024
If a TAG is to be converted, then the resultant value should be used with
1025
caution. The result is only as good as the provided URL and may not address
1026
the root of a package.
1027
 
311 dpurdie 1028
=head1 Delete a Package
1029
 
1030
=head2 NAME
1031
 
1032
Delete a Package
1033
 
1034
=head2 SYNOPSIS
1035
 
1036
jats svn delete-package URL [options]
1037
 
1038
 Options:
1039
    -help[=n]              - Help message, [n=1,2,3]
1040
    -man                   - Full documentation [-help=3]
1041
    -verbose[=n]           - Verbose command operation
1042
 
1043
=head2 ARGUMENTS
1044
 
1045
The command takes one argument: The URL of the desired package.
1046
This may be be:
1047
 
1048
=over
1049
 
1050
=item * A full URL
1051
 
1052
Complete with protocol and path information.
1053
 
1054
=item * A simple URL
1055
 
1056
JATS will prepend the site-specific repository location to the user provided URL
1057
 
1058
=back
1059
 
1060
=head2 OPTIONS
1061
 
1062
This command has no significant options, other than the general help options.
1063
 
1064
=head2 DESCRIPTION
1065
 
1066
This command will delete a package from the repository. It will ensure
1067
that the package is a valid package, before it is deleted.
1068
 
1069
The command is intended to be used by test scripts, rather than users.
1070
 
1071
=head1 Create a Package Version
1072
 
1073
=head2 NAME
1074
 
1075
Create a Package Version
1076
 
1077
=head2 SYNOPSIS
1078
 
1079
jats svn [options] create URL [command options]
1080
 
1081
 Options:
1082
    -help[=n]               - Help message, [n=1,2,3]
1083
    -man                    - Full documentation [-help=3]
1084
    -verbose[=n]            - Verbose command operation
1085
 
1086
 Command Options
1087
    -help[=n]               - Provide command specific help
1088
    -import=nnn             - Import directory tree
1089
    -label=nnn              - Label it (trunk import only)
1090
    -new                    - Package must not exist
1091
    -replace                - Replace any existing versions
1092
    -trunk                  - Import to trunk
1093
    -tags=nnn               - Import to tags
1094
    -branch=nnn             - Import to branches
1095
 
1096
=head2 ARGUMENTS
1097
 
1098
The command takes one argument: The URL of the desired package.
1099
This may be be:
1100
 
1101
=over
1102
 
1103
=item * A full URL
1104
 
1105
Complete with protocol and path information.
1106
 
1107
=item * A simple URL
1108
 
1109
JATS will prepend the site-specific repository location to the user provided URL
1110
 
1111
=back
1112
 
1113
=head2 OPTIONS
1114
 
1115
=over
1116
 
1117
=item -help[=n]
1118
 
1119
Print a help message and exit. The level of help may be either 1, 2 or 3.
1120
 
1121
This option may be specified multiple times to increment the help level, or
1122
the help level may be directly specified as a number.
1123
 
1124
=item -import=nnn
1125
 
1126
This option specifies the path of a subdirectory tree to import into the newly
1127
created package. In not provided, then only a package skeleton will be created.
1128
 
1129
=item -label=nnn
1130
 
1131
This option specifies a label to place the imported source, if the source is
1132
being imported to the 'trunk' of the package.
1133
 
1134
=item -new
1135
 
1136
This option specifies that the named package MUST not exist at all.
1137
 
1138
=item -replace
1139
 
1140
This option allows the program to replace any existing versions of the
1141
imported source. It will allow the deletion of any existing trunk, tags or
1142
branches.
1143
 
1144
=item -trunk
1145
 
1146
This option specifies that imported source will be placed on the trunk of the
1147
package. This is the default mode of import.
1148
 
1149
The options -trunk, -tags and -branch are mutually exclusive.
1150
 
1151
=item -tags=nnn
1152
 
1153
This option specifies that imported source will be placed directly on the
1154
named tag of the package.
1155
 
1156
The options -trunk, -tags and -branch are mutually exclusive.
1157
 
1158
=item -branch=nnn
1159
 
1160
This option specifies that imported source will be placed directly on the
1161
named branch of the package.
1162
 
1163
The options -trunk, -tags and -branch are mutually exclusive.
1164
 
1165
=back
1166
 
1167
=head2 DESCRIPTION
1168
 
1169
This command will create a new package within a repository. It will ensure
1170
that the package contains the three required subdirectories: trunk, tags and
1171
branches.
1172
 
1173
The command will also ensure that packages are not placed at inappropriate
1174
locations within the repository. It is not correct to place a package within
1175
another package.
1176
 
1177
The command will, optionally, import a directory tree into the repository and,
1178
optionally, label the package.
1179
 
1180
The package body may be imported to the 'trunk' or to a branch or a tag.
1181
By default the data will be imported to the trunk and may be labeled (tagged).
1182
 
1183
Options allow the targets to be deleted if they exist or to ensure that they
1184
are not present.
1185
 
1186
The command does not attempt to merge file versions within the repository. It
1187
may result in multiple instances of a file within the repository. Use only for
341 dpurdie 1188
simple imports. Use the 'import' command for more sophisticated import requirements.
311 dpurdie 1189
 
1190
=head1 Import directory to a Package
1191
 
1192
=head2 NAME
1193
 
1194
Import directory to a Package
1195
 
1196
=head2 SYNOPSIS
1197
 
1198
jats svn [options] import URL [command options]
1199
 
1200
 Options:
1201
    -help[=n]               - Help message, [n=1,2,3]
1202
    -man                    - Full documentation [-help=3]
1203
    -verbose[=n]            - Verbose command operation
1204
 
1205
 Command Options
1206
    -help[=n]               - Command specific help, [n=1,2,3]
1207
    -verbose[=n]            - Verbose operation
1208
    -package=name           - Name of source package
1209
    -dir=path               - Path to new version
1210
    -label                  - Label the result
1211
    -replace                - Allow the label to be replaced
1212
    -reuse                  - Reuse the import directory
1213
    -workspace=path         - Path and name of alternate workspace
1214
    -[no]delete             - Deletes workspace after use. Default:yes
1215
 
1216
=head2 ARGUMENTS
1217
 
1218
The command takes one argument: The URL of the desired package.
1219
This may be be:
1220
 
1221
=over
1222
 
1223
=item * A full URL
1224
 
1225
Complete with protocol and path information.
1226
 
1227
=item * A simple URL
1228
 
1229
JATS will prepend the site-specific repository location to the user provided URL
1230
 
1231
=back
1232
 
1233
=head2 OPTIONS
1234
 
1235
=over
1236
 
1237
=item -help[=n]
1238
 
1239
Print a help message and exit. The level of help may be either 1, 2 or 3.
1240
 
1241
This option may be specified multiple times to increment the help level, or
1242
the help level may be directly specified as a number.
1243
 
1244
=item -verbose[=n]
1245
 
1246
This option will increase the level of verbosity of the utility.
1247
 
1248
If an argument is provided, then it will be used to set the level, otherwise the
1249
existing level will be incremented. This option may be specified multiple times.
1250
 
1251
 
1252
=item -package=name
1253
 
1254
Either this option or a bare URL on the command line must be provided. It
1255
specifies the repository and package to be used as a basis for the work.
1256
 
1257
=item -dir=path
1258
 
1259
This option is mandatory. It specifies the path to a local directory that
1260
contains a version of the software to be checked in.
1261
 
1262
=item -label=name
1263
 
1264
The resulting software version will be labeled with this tag, if it is provided.
1265
 
1266
=item -replace
1267
 
1268
This option, if provided, allows the label to be replaced.
1269
 
1270
=item -reuse
1271
 
1272
This option can be used to speed the creation of multiple versions in a scripted
1273
environment. The option allows the utility to reuse the workspace if it exists.
1274
 
1275
=item -workspace=path
1276
 
1277
This option specifies an alternate workspace directory to create and use. The
1278
default directory is "SvnImportDir" within the users current directory.
1279
 
1280
=item [no]delete
1281
 
341 dpurdie 1282
This option control the deletion of the workspace directory. By default the
311 dpurdie 1283
directory will be deleted, unless re-use is also used.
1284
 
1285
=back
1286
 
1287
=head2 DESCRIPTION
1288
 
1289
Import a new version of a package to the trunk of the package. The utility
1290
will only import changed files so that file history is preserved within the
1291
repository.
1292
 
1293
This utility is used import software from another version control system
1294
The utility will:
1295
 
1296
=over
1297
 
361 dpurdie 1298
=item *
311 dpurdie 1299
 
361 dpurdie 1300
Create a Work Space based on the current package version
1301
 
311 dpurdie 1302
The 'trunk' of the named package will be used as the base for the workspace.
1303
 
361 dpurdie 1304
=item *
311 dpurdie 1305
 
361 dpurdie 1306
Update files and directories
1307
 
311 dpurdie 1308
Determines the files and directories that have been added and deleted and
1309
update the Workspace to reflect the new structure.
1310
 
361 dpurdie 1311
=item *
311 dpurdie 1312
 
361 dpurdie 1313
Check in the new version
311 dpurdie 1314
 
361 dpurdie 1315
=item *
1316
 
1317
Label the new version
1318
 
311 dpurdie 1319
=back
1320
 
1321
The utility can optionally perform other operations including:
1322
 
1323
=over
1324
 
361 dpurdie 1325
=item *
311 dpurdie 1326
 
361 dpurdie 1327
Import directly to a branch. This does not affect the 'trunk'.
311 dpurdie 1328
 
361 dpurdie 1329
=item *
1330
 
1331
Import directly to a tag. This does not affect the 'trunk'
1332
 
311 dpurdie 1333
=back
1334
 
1335
=cut
1336