Subversion Repositories DevTools

Rev

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

Rev Author Line No. Line
311 dpurdie 1
########################################################################
6177 dpurdie 2
# COPYRIGHT - VIX IP PTY LTD ("VIX"). ALL RIGHTS RESERVED.
311 dpurdie 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;
379 dpurdie 24
use JatsProperties;
7217 dpurdie 25
use FileUtils;
311 dpurdie 26
use Pod::Usage;                                 # required for help support
27
use Getopt::Long qw(:config require_order);     # Stop on non-option
28
use Cwd;
29
use File::Path;
30
use File::Copy;
31
use File::Basename;
32
use File::Compare;
387 dpurdie 33
use Encode;
311 dpurdie 34
 
35
my $VERSION = "1.0.0";                          # Update this
36
 
37
#
38
#   Options
39
#
40
my $opt_debug   = $ENV{'GBE_DEBUG'};            # Allow global debug
41
my $opt_verbose = $ENV{'GBE_VERBOSE'};          # Allow global verbose
42
my $opt_help = 0;
43
 
44
#
45
#   Globals
46
#
47
my $opr_done;                                   # User has done something
48
 
49
#-------------------------------------------------------------------------------
50
# Function        : Mainline Entry Point
51
#
52
# Description     :
53
#
54
# Inputs          :
55
#
56
my $result = GetOptions (
57
                "help:+"        => \$opt_help,              # flag, multiple use allowed
58
                "manual:3"      => \$opt_help,              # flag
59
                "verbose:+"     => \$opt_verbose,           # flag, multiple use allowed
60
 
61
                );
62
 
63
                #
64
                #   UPDATE THE DOCUMENTATION AT THE END OF THIS FILE !!!
65
                #
66
 
67
#
68
#   Process help and manual options
69
#
70
pod2usage(-verbose => 0, -message => "Version: $VERSION") if ($opt_help == 1 || ! $result);
71
pod2usage(-verbose => 1) if ($opt_help == 2 );
72
pod2usage(-verbose => 2) if ($opt_help > 2);
73
 
74
#
75
#   Configure the error reporting process now that we have the user options
76
#
77
ErrorConfig( 'name'    =>'SVN',
78
             'verbose' => $opt_verbose,
79
            );
80
 
81
#
369 dpurdie 82
#   Reconfigure the options parser to allow subcommands to parse options
311 dpurdie 83
#
84
Getopt::Long::Configure('permute');
7217 dpurdie 85
InitFileUtils();
311 dpurdie 86
 
87
#
88
#   Process command
89
#   First command line argument is a subversion command
90
#
91
my $cmd = shift @ARGV || "help";
92
CreatePackage()                        if ( $cmd =~ m/^create/ );
2049 dpurdie 93
CreateBranch()                         if ( $cmd =~ m/^branch/ );
94
SwitchBranch()                         if ( $cmd =~ m/^switch/ );
385 dpurdie 95
DeleteBranch()                         if ( $cmd =~ m/^delete-branch/ );
311 dpurdie 96
DeletePackage()                        if ( $cmd =~ m/^delete-package/ );
97
ImportPackage()                        if ( $cmd =~ m/^import/ );
98
SvnRepoCmd($cmd, @ARGV)                if ( $cmd eq 'ls' );
363 dpurdie 99
TestSvn()                              if ($cmd eq 'test');
369 dpurdie 100
ShowPaths()                            if ( $cmd =~ m/^path/ );
101
ShowTag()                              if ( $cmd =~ m/^tag/ );
102
ShowUrl()                              if ( $cmd =~ m/^url/ );
7217 dpurdie 103
SvnMerge()                             if ( $cmd =~ m/^merge/ );
104
SvnReintegrate()                       if ( $cmd =~ m/^reintegrate/ );
311 dpurdie 105
 
106
pod2usage(-verbose => 0, -message => "No valid operations specified") unless ( $opr_done );
107
exit 0;
108
 
109
#-------------------------------------------------------------------------------
369 dpurdie 110
# Function        : ShowPaths
111
#
112
# Description     : Show PATHS
113
#
2049 dpurdie 114
# Inputs          :
369 dpurdie 115
#
2049 dpurdie 116
# Returns         :
369 dpurdie 117
#
118
sub ShowPaths
119
{
120
    #
121
    #   Parse more options
122
    #
123
    GetOptions (
124
                "help:+"        => \$opt_help,
125
                "manual:3"      => \$opt_help,
126
                ) || Error ("Invalid command line" );
127
 
128
    #
129
    #   Subcommand specific help
130
    #
131
    SubCommandHelp( $opt_help, "Subversion Paths") if ($opt_help || $#ARGV >= 0);
132
 
133
    #
134
    #   Display known PATHS
135
    #
136
    my ( $pSVN_URLS, $pSVN_URLS_LIST) = SvnPaths();
137
    print ("Configured SubVersion Repository Paths\n");
138
    print sprintf("    %-20s %s\n", 'Tag', 'URL Prefix');
139
 
140
    foreach my $key ( @{$pSVN_URLS_LIST} )
141
    {
142
        print sprintf("    %-20s %s\n", $key || 'Default', $pSVN_URLS->{$key} );
143
    }
144
 
145
    $opr_done = 1;
146
}
147
 
148
#-------------------------------------------------------------------------------
149
# Function        : ShowTag
150
#
151
# Description     : Convert a URL into a TAG
152
#                   Convert the current workspace info into a TAG
153
#
154
# Inputs          : url                     - Url to convert (optional)
155
#                   Options
156
#                       -help[=n]           - Show help
157
#                       -man                - Show manual
158
#                       -url=url            - Convert URL
159
#                       -path=path          - Convert Workspace
160
#
161
# Returns         : Nothing
162
#
163
sub ShowTag
164
{
165
    my $opt_path;
166
    my $opt_url;
167
 
168
    #
169
    #   Parse more options
170
    #
171
    GetOptions (
172
                "help:+"        => \$opt_help,
173
                "manual:3"      => \$opt_help,
174
                "path:s"        => \$opt_path,
175
                "url:s"         => \$opt_url,
176
                ) || Error ("Invalid command line" );
177
 
178
    #
179
    #   Subcommand specific help
180
    #
181
    SubCommandHelp( $opt_help, "Url to Tag") if ($opt_help);
182
 
183
    #
184
    #   Bare argument is a URL
185
    #   If no arguments provided assume a path of the current directory
186
    #
187
    $opt_url = shift (@ARGV) if ( $#ARGV == 0 );
188
    $opt_path = '.' unless ( defined $opt_path || defined $opt_url );
189
 
190
    #
191
    #   Sanity Tests
192
    #
193
    Error ("Cannot specify both a URL and a PATH")
194
            if ( defined $opt_url && defined $opt_path );
195
    Warning ("Too many arguments") if ( $#ARGV >= 0 );
196
 
197
    #   Do all the hard work
198
    #
199
    my $uref;
200
    if ( $opt_url )
201
    {
202
        $uref = NewSessionByUrl ( $opt_url );
203
        $uref->CalcRmReference($uref->Full());
204
    }
205
    else
206
    {
207
        $uref = NewSessionByWS($opt_path, 0, 1);
208
        my $ws_root = $uref->SvnLocateWsRoot(1);
209
        $uref->CalcRmReference($uref->FullWs());
210
    }
211
 
1403 dpurdie 212
    Message ("Tag is  : " . $uref->RmRef() );
213
    Message ("Vcs Tag : " . $uref->SvnTag  );
2049 dpurdie 214
 
369 dpurdie 215
    $opr_done = 1;
216
}
217
#-------------------------------------------------------------------------------
218
# Function        : ShowUrl
219
#
220
# Description     : Convert a TAG into a URL
221
#                   Show the current workspace URL
222
#
223
# Inputs          : tag                     - Tag to convert (optional)
224
#                   Options
225
#                       -help[=n]           - Show help
226
#                       -man                - Show manual
227
#                       -tag=tag            - Convert TAG
228
#                       -path=path          - Convert Workspace
229
#
230
# Returns         : Nothing
231
#
232
sub ShowUrl
233
{
234
    my $opt_path;
235
    my $opt_tag;
236
 
237
    #
238
    #   Parse more options
239
    #
240
    GetOptions (
241
                "help:+"        => \$opt_help,
242
                "manual:3"      => \$opt_help,
243
                "path:s"        => \$opt_path,
244
                "tag:s"         => \$opt_tag,
245
                ) || Error ("Invalid command line" );
246
 
247
    #
248
    #   Subcommand specific help
249
    #
250
    SubCommandHelp( $opt_help, "Tag to Url") if ($opt_help);
251
 
252
    #
253
    #   Bare argument is a TAG
254
    #   If no arguments provided assume a path of the current directory
255
    #
256
    $opt_tag = shift (@ARGV) if ( $#ARGV == 0 );
257
    $opt_path = '.' unless ( defined $opt_path || defined $opt_tag );
258
 
259
    #
260
    #   Sanity Tests
261
    #
262
    Error ("Cannot specify both a TAG and a PATH")
263
            if ( defined $opt_tag && defined $opt_path );
264
    Warning ("Too many arguments") if ( $#ARGV >= 0 );
265
 
266
    #   Do all the hard work
267
    #
268
    my $uref;
269
    my $url;
270
    if ( $opt_tag )
271
    {
2429 dpurdie 272
        my $path = $opt_tag;
273
        my $label;
274
 
275
        $path =~ s~^SVN::~~;
276
        if ( $path =~ m~(.+)::(.+)~ )
277
        {
278
            $path = $1;
279
            $label = $2;
280
        }
281
        $url = SvnPath2Url($path);
282
        if ( $label && $label =~ m~^\d+$~ )
283
        {
284
            $url .= '@' . $label;
285
        }
286
        elsif ( $label )
287
        {
288
            $url =~ m~(.+)(/(tags|branches|trunk)(/|$|@))~;
289
            $url = $1 . '/tags/'. $label;
290
        }
369 dpurdie 291
    }
292
    else
293
    {
294
        $uref = NewSessionByWS($opt_path, 0, 1);
295
        my $ws_root = $uref->SvnLocateWsRoot(1);
296
        $url = $uref->FullWsRev();
297
    }
298
 
299
    Message ("Url: $url");
300
    $opr_done = 1;
301
}
302
 
303
#-------------------------------------------------------------------------------
363 dpurdie 304
# Function        : TestSvn
305
#
306
# Description     : Test access to subversion
307
#
308
# Inputs          : None
309
#
310
# Returns         :
311
#
312
sub TestSvn
313
{
314
    #
315
    #   Parse more options
316
    #
317
    GetOptions (
318
                "help:+"        => \$opt_help,
319
                "manual:3"      => \$opt_help,
320
                ) || Error ("Invalid command line" );
321
 
322
    #
323
    #   Subcommand specific help
324
    #
325
    SubCommandHelp( $opt_help, "Test Subversion") if ($opt_help || $#ARGV >= 0);
326
 
327
    SvnUserCmd( '--version');
328
    $opr_done = 1;
329
}
330
#-------------------------------------------------------------------------------
311 dpurdie 331
# Function        : SvnRepoCmd
332
#
333
# Description     : Execute a SVN command, where the first argument
334
#                   is a repository specifier
335
#
336
# Inputs          : $cmd
337
#                   $repo_url
338
#                   @opts
339
#
2049 dpurdie 340
# Returns         :
311 dpurdie 341
#
342
sub SvnRepoCmd
343
{
344
    my ( $cmd, $repo_url, @opts ) = @_;
345
    my $uref = NewSessionByUrl ( $repo_url );
346
 
347
    SvnUserCmd( $cmd,
348
            $uref->Full,
349
            @opts,
350
            { 'credentials' => 1 });
2049 dpurdie 351
 
311 dpurdie 352
    $opr_done = 1;
353
}
354
 
355
#-------------------------------------------------------------------------------
356
# Function        : DeletePackage
357
#
358
# Description     : Delete a Package structure within a Repository
359
#                   Intended for test usage
360
#
361
# Inputs          : URL                 - Url to Repo + Package Base
362
#
2049 dpurdie 363
# Returns         :
311 dpurdie 364
#
365
sub DeletePackage
366
{
379 dpurdie 367
    my $opt_error = 0;
311 dpurdie 368
    #
369
    #   Parse more options
370
    #
371
    GetOptions (
372
                "help:+"        => \$opt_help,
373
                "manual:3"      => \$opt_help,
379 dpurdie 374
                "error!"       => \$opt_error,
311 dpurdie 375
                ) || Error ("Invalid command line" );
376
 
377
    #
378
    #   Subcommand specific help
379
    #
380
    SubCommandHelp( $opt_help, "Delete a Package") if ($opt_help || $#ARGV < 0);
381
 
382
    #
383
    #   Sanity Tests
384
    #
385
    Message ("Delete Entire Package Tree" );
386
    Warning ("Too many arguments: @ARGV") if ( $#ARGV >= 1 );
387
 
388
    #
389
    #   Do all the hard work
390
    #       Create
391
    #       Import
392
    #       Label
393
    #
394
    my $uref = NewSessionByUrl ( $ARGV[0] );
379 dpurdie 395
    $uref->SvnValidatePackageRoot(!$opt_error);
311 dpurdie 396
    $uref->SvnDelete (
397
                      'target'      => $uref->Full,
385 dpurdie 398
                      'comment'   => [$uref->Path().": Delete Package",'Deleted by user command: jats svn delete-package'],
379 dpurdie 399
                      'noerror'   => !$opt_error,
311 dpurdie 400
                      );
401
    $opr_done = 1;
402
}
403
 
404
#-------------------------------------------------------------------------------
405
# Function        : CreatePackage
406
#
407
# Description     : Create a Package structure within a Repository
408
#                   Optionally Import Data
409
#                   Optionally Tag the import
410
#                   Optionally Tag the import on a branch
411
#
412
# Inputs          : URL                 - Url to Repo + Package Base
413
#                   Options             - Command modifiers
414
#                       -import=path    - Import named directory
415
#                       -label=name     - Label the result
416
#                       -tag=name       - Import to Tag Only
417
#                       -branch=name    - Import to Branch only
418
#                       -new            - Must be new package
419
#                       -replace        - Replace existing
420
#
2049 dpurdie 421
# Returns         :
311 dpurdie 422
#
423
sub CreatePackage
424
{
425
    my $opt_import;
426
    my $opt_tag;
427
    my $opt_branch;
428
    my $opt_trunk;
429
    my $opt_new;
430
    my $opt_label;
431
    my $opt_replace;
432
    my $pname;
433
    my $type;
385 dpurdie 434
    my $opt_author;
435
    my $opt_date;
311 dpurdie 436
    Message ("Create New Package Version" );
437
 
438
    #
439
    #   Parse more options
440
    #
441
    GetOptions (
442
                "help:+"        => \$opt_help,
443
                "manual:3"      => \$opt_help,
444
                "verbose:+"     => \$opt_verbose,
445
                "import=s"      => \$opt_import,
446
                "new"           => \$opt_new,
447
                "branch=s"      => \$opt_branch,
448
                "trunk"         => \$opt_trunk,
1403 dpurdie 449
                "tags=s"        => \$opt_tag,
311 dpurdie 450
                "label=s"       => \$opt_label,
451
                "replace"       => \$opt_replace,
385 dpurdie 452
                'author=s'      => \$opt_author,
453
                'date=s'        => \$opt_date,
311 dpurdie 454
 
455
                ) || Error ("Invalid command line" );
456
 
457
    #
458
    #   Subcommand specific help
459
    #
460
    SubCommandHelp( $opt_help, "Create a Package Version") if ($opt_help || $#ARGV < 0);
2049 dpurdie 461
 
311 dpurdie 462
    #
369 dpurdie 463
    #   Alter the error reporting parameters
311 dpurdie 464
    #
465
    ErrorConfig( 'verbose' => $opt_verbose );
466
 
467
    #
468
    #   Sanity Tests
469
    #
470
    my $count = 0;
471
    $count++ if ( $opt_trunk );
472
    $count++ if ( $opt_branch );
473
    $count++ if ( $opt_tag );
474
    Error ("Conflicting options: -trunk, -tag, -branch") if ( $count > 1 );
475
    Error ("Nothing imported to be labeled") if ( $count && !$opt_import );
476
    Error ("Import path does not exist: $opt_import") if ( $opt_import && ! -d $opt_import );
477
    Error ("Conflicting options: new and replace") if ( $opt_new && $opt_replace );
385 dpurdie 478
    Error ("Too many command line arguments") if ( exists $ARGV[1] );
311 dpurdie 479
 
1403 dpurdie 480
    $type = 'tags/' . $opt_tag          if ( $opt_tag);
481
    $type = 'branches/' . $opt_branch   if ( $opt_branch );
482
    $type = 'trunk'                     if ( $opt_trunk);
311 dpurdie 483
 
484
    #
485
    #   Do all the hard work
486
    #       Create
487
    #       Import
488
    #       Label
489
    #
490
    my $uref = NewSessionByUrl ( $ARGV[0] );
491
    $uref->SvnCreatePackage (
492
                      'import'  => $opt_import,
493
                      'label'   => $opt_label,
494
                      'type'    => $type,
495
                      'new'     => $opt_new,
496
                      'replace' => $opt_replace,
497
                      );
385 dpurdie 498
    #
499
    # Report RmPath as using a pegged version of a new package is a bit silly
500
    #
1403 dpurdie 501
#    Message ("Repository Ref: " . $uref->RmPath);
502
#    Message ("Vcs Tag       : " . $uref->SvnTag);
1329 dpurdie 503
    if ( $uref->{REVNO} )
504
    {
505
        $uref->setRepoProperty('svn:author', $opt_author) if (defined ($opt_author));
506
        $uref->setRepoProperty('svn:date', $opt_date) if (defined ($opt_date));
507
    }
311 dpurdie 508
    $opr_done = 1;
509
}
510
 
511
#-------------------------------------------------------------------------------
512
# Function        : ImportPackage
513
#
514
# Description     : Import a new version of a package
515
#                   Take great care to reuse file-versions that are already in
516
#                   the  package
517
#
369 dpurdie 518
#                   Intended to allow the importation of multiple
311 dpurdie 519
#                   versions of a package
520
#
2049 dpurdie 521
# Inputs          :
311 dpurdie 522
#
2049 dpurdie 523
# Returns         :
311 dpurdie 524
#
525
sub ImportPackage
526
{
527
    Message ("Import Package Version" );
528
 
529
    #
530
    #   Options
531
    #
532
    my $opt_package;
533
    my $opt_dir;
534
    my $opt_label;
535
    my $opt_replace = 0;
536
    my $opt_reuse;
537
    my $opt_workdir = "SvnImportDir";
538
    my $opt_delete = 1;
379 dpurdie 539
    my $opt_author;
540
    my $opt_date;
541
    my $opt_log = '';
542
    my $opt_branch;
543
    my $opt_datafile;
1403 dpurdie 544
    my $opt_printfiles;
2429 dpurdie 545
    my $opt_commit = 1;
2764 dpurdie 546
    my $opt_mergePaths;
311 dpurdie 547
 
548
    #
549
    #   Other globals
550
    #
551
    my $url_label;
379 dpurdie 552
    my $url_branch;
311 dpurdie 553
 
2764 dpurdie 554
    my $filesBase = 0;                  # Files in Base workspace
555
    my $filesDeleted = 0;               # Files Deleted
556
    my $filesAdded = 0;                 # Files Added
557
    my $filesTransferred = 0;           # Files Copied
558
    my $dirsDeleted = 0;                # Directories Deleted
559
    my $dirsAdded = 0;                  # Directories Added
560
    my $dirsTransferred = 0;            # Directories Copied
561
 
562
 
311 dpurdie 563
    #
564
    #   Configuration options
565
    #
566
    my $result = GetOptions (
379 dpurdie 567
                    'help:+'        => \$opt_help,
568
                    'manual:3'      => \$opt_help,
569
                    'verbose:+'     => \$opt_verbose,
570
                    'package=s'     => \$opt_package,
571
                    'dir=s'         => \$opt_dir,
572
                    'label=s'       => \$opt_label,
573
                    'branch=s'      => \$opt_branch,
574
                    'replace'       => \$opt_replace,
575
                    'reuse'         => \$opt_reuse,
576
                    'workspace=s'   => \$opt_workdir,
577
                    'delete!'       => \$opt_delete,
1403 dpurdie 578
                    'printfiles=i'  => \$opt_printfiles,
379 dpurdie 579
                    'author=s'      => \$opt_author,
580
                    'date=s'        => \$opt_date,
581
                    'log=s'         => \$opt_log,
582
                    'datafile=s'    => \$opt_datafile,
2429 dpurdie 583
                    'commit!'       => \$opt_commit,
2764 dpurdie 584
                    'mergePaths=s'  => \$opt_mergePaths,
311 dpurdie 585
 
586
                    #
587
                    #   Update documentation at the end of the file
588
                    #
589
                    ) || Error ("Invalid command line" );
590
 
591
    #
592
    #   Insert defaults
341 dpurdie 593
    #   User can specify base package via -package or a non-options argument
311 dpurdie 594
    #
595
    $opt_package = $ARGV[0] unless ( $opt_package );
379 dpurdie 596
    unlink $opt_datafile if ( defined $opt_datafile );
2049 dpurdie 597
 
311 dpurdie 598
    #
599
    #   Subcommand specific help
600
    #
601
    SubCommandHelp( $opt_help, "Import directory to a Package")
602
        if ($opt_help || ! $opt_package );
603
 
604
    #
369 dpurdie 605
    #   Alter the error reporting parameters
311 dpurdie 606
    #
607
    ErrorConfig( 'verbose' => $opt_verbose );
608
 
609
    #
610
    #   Configure the error reporting process now that we have the user options
611
    #
612
    Error ("No package URL specified") unless ( $opt_package );
613
    Error ("No base directory specified") unless ( $opt_dir );
614
    Error ("Invalid base directory: $opt_dir") unless ( -d $opt_dir );
2429 dpurdie 615
    Error ("Cannot label if not committing") if ( $opt_label && ! $opt_commit );
311 dpurdie 616
 
617
    #
618
    #   Create an SVN session
619
    #
620
    my $svn = NewSessionByUrl ( $opt_package );
621
 
622
    #
623
    #   Ensure that the required label is available
624
    #
625
    if ( $opt_label )
626
    {
627
        $opt_label = SvnIsaSimpleLabel ($opt_label);
628
        $url_label = $svn->BranchName( $opt_label, 'tags' );
629
        $svn->SvnValidateTarget (
630
                        'target' => $url_label,
631
                        'available' => 1,
632
                        ) unless ( $opt_replace );
633
    }
634
 
635
    #
379 dpurdie 636
    #   Validate the required branch
637
    #   It will be created if it doesn't exist
638
    #
639
    if ( $opt_branch )
640
    {
641
        $opt_branch = SvnIsaSimpleLabel($opt_branch);
642
        $url_branch = $svn->BranchName( $opt_branch, 'branches' );
385 dpurdie 643
        my $rv = $svn->SvnValidateTarget (
644
                        'cmd'    => 'SvnImporter. Create branch',
379 dpurdie 645
                        'target' => $url_branch,
646
                        'create' => 1,
647
                        );
385 dpurdie 648
        if ( $rv == 2 )
649
        {
650
            $svn->setRepoProperty('svn:author', $opt_author) if (defined ($opt_author));
651
            $svn->setRepoProperty('svn:date', $opt_date) if (defined ($opt_date));
652
        }
379 dpurdie 653
    }
654
 
655
    #
311 dpurdie 656
    #   Create a workspace based on the users package
657
    #   Allow the workspace to be reused to speed up multiple
658
    #   operations
659
    #
660
    unless ( $opt_reuse && -d $opt_workdir )
661
    {
662
        Message ("Creating Workspace");
663
        rmtree( $opt_workdir );
664
 
665
        $svn->SvnValidatePackageRoot ();
666
        #DebugDumpData( 'Svn', $svn );
667
        $svn->SvnValidateTarget (
668
                            'cmd'    => 'SvnImporter',
669
                            'target' => $svn->Full,
670
                            'require' => 1,
671
                            );
672
 
379 dpurdie 673
        my $url_co = $opt_branch ? $url_branch : $svn->Full . '/trunk';
1403 dpurdie 674
        $svn->SvnCo ( $url_co, $opt_workdir, 'print' => $opt_printfiles );
311 dpurdie 675
        Error ("Cannot locate the created Workspace")
676
            unless ( -d $opt_workdir );
677
    }
678
    else
679
    {
680
        Message ("Reusing Workspace");
681
    }
2049 dpurdie 682
 
311 dpurdie 683
    #
684
    #   Determine differences between the two folders
685
    #       Create structures for each directory
686
    #
687
    Message ("Determine Files in packages");
688
 
689
    my $search = JatsLocateFiles->new("--Recurse=1",
690
                                       "--DirsToo",
691
                                       "--FilterOutRe=/\.svn/",
692
                                       "--FilterOutRe=/\.svn\$",
693
                                       "--FilterOutRe=^/${opt_workdir}\$",
694
                                       "--FilterOutRe=^/${opt_workdir}/",
695
                                       );
696
    my @ws = $search->search($opt_workdir);
697
    my @dir = $search->search($opt_dir);
698
 
1329 dpurdie 699
    #
700
    #   Scan for a source file
701
    #   Trying to detect empty views
702
    #   Look for file, not directory
2764 dpurdie 703
    #       Keep a count for reporting
1329 dpurdie 704
    #
705
    {
2764 dpurdie 706
        foreach ( @ws )
707
        {
708
            $filesBase++ unless ( m~/$~ );
709
        }
710
 
1329 dpurdie 711
        my $fileFound = 0;
712
        foreach ( @dir )
713
        {
714
            next if ( m~/$~ );
2764 dpurdie 715
            $fileFound = 1;
1329 dpurdie 716
            last;
717
        }
718
 
719
        unless ( $fileFound )
720
        {
721
            Warning ("No source files found in source view");
722
            $opr_done = 1;
723
            return;
724
        }
725
    }
726
 
311 dpurdie 727
    #Information ("WS Results", @ws);
728
    #Information ("DIR Results", @dir);
1329 dpurdie 729
    #Information ("WS Results: ", scalar @ws);
730
    #Information ("DIR Results:", scalar @dir);
311 dpurdie 731
 
4086 dpurdie 732
 
311 dpurdie 733
    #
734
    #   Create a hash the Workspace and the User dir
735
    #   The key will be file names
736
    #
737
    my %ws;  map ( $ws{$_} = 1 , @ws );
738
    my %dir; map ( $dir{$_} = 1 , @dir );
739
 
740
    #
4086 dpurdie 741
    #   Create hash of paths to persist
742
    #       build/*   -> Persist directory. Keep dir tree if not
743
    #                    being imported, otherwise delete.
744
    #
745
    my %persistPaths;
746
    if ( $opt_mergePaths )
747
    {
748
        foreach ( split(',', $opt_mergePaths) )
749
        {
750
            if ( m~(.+/)\*$~ )
751
            {
752
                my $base = $1;
753
                $persistPaths{$base} = 1 unless( exists $dir{$base});
754
            }
755
        }
756
        Verbose0("Persist Paths:" , sort keys %persistPaths);
757
    }
758
 
759
    #
311 dpurdie 760
    #   Create a hash of common elements
761
    #   Removing then from the other two
762
    #
763
    my %common;
764
    foreach ( keys %ws )
765
    {
766
        next unless ( exists $dir{$_} );
767
        $common{$_} = 1;
768
        delete $ws{$_};
769
        delete $dir{$_};
770
    }
771
 
2764 dpurdie 772
    #
773
    #   Now have:
774
    #       %ws     - Hash of paths that are only in the Workspace
775
    #       %dir    - Hash of paths that are only in New Import
776
    #       %common - Hash of paths that are common to both
777
    #
311 dpurdie 778
    #DebugDumpData( 'WS', \%ws );
779
    #DebugDumpData( 'DIR', \%dir );
780
    #DebugDumpData( 'COMMON', \%common );
781
 
2764 dpurdie 782
 
311 dpurdie 783
    #
379 dpurdie 784
    #   Need to consider the case where a file has been replaced with a directory
785
    #   and visa-versa. Delete files and directories first.
786
    #
787
    #
788
    #   Remove files
789
    #   Sort in reverse. This will ensure that we process directory
790
    #   contents before directories
791
    #
2764 dpurdie 792
 
379 dpurdie 793
    my @rm_files = reverse sort keys %ws;
794
    if ( @rm_files )
795
    {
2764 dpurdie 796
        #
797
        #   Calculate new top level paths
798
        #   These are of the form xxxxx/
799
        #
800
        my @newTldPaths;
801
        if ( $opt_mergePaths )
802
        {
4086 dpurdie 803
            foreach (@rm_files)
2764 dpurdie 804
            {
805
                push (@newTldPaths, $1 ) if ( m~^([^/]+)/$~ );
806
            }
807
        }
808
 
809
        my @processedFiles;
379 dpurdie 810
        foreach my $file ( @rm_files  )
811
        {
2764 dpurdie 812
            #
813
            #   Detect items that are to be retained
814
            #   Do not delete items that are a part of a top level path that
3347 dpurdie 815
            #   are not present in the New Import
2764 dpurdie 816
            #
817
            if ( $opt_mergePaths )
818
            {
819
                my $keep = 0;
4086 dpurdie 820
                ##
821
                ##  Following removed because it did the wrong thing and I'm not too sure
822
                ##  under what conditions its needed.
823
                ##  It did the wrong thing when used with '++,XXXX/**'
824
                ##  Perhaps its only these that cause problems
825
 
826
                ##
827
                ##foreach ( @newTldPaths )
828
                ##{
829
                ##    if ( $file =~ m~^$_/~ )
830
                ##    {
831
                ##        Verbose("Merge Retain(0): $file, $_");
832
                ##        $keep = 1;
833
                ##        last;
834
                ##    }
835
                ##}
836
 
837
                if ( $file =~ m~(^.*/)~ )
2764 dpurdie 838
                {
4086 dpurdie 839
                    my $tpath = $1;
840
                    foreach ( keys %persistPaths)
2764 dpurdie 841
                    {
4086 dpurdie 842
                        if ( $file =~ m~^$_~ )
843
                        {
844
                            Verbose0("Merge Retain(1): $file");
845
                            $keep = 1;
846
                            last;
847
                        }
2764 dpurdie 848
                    }
849
                }
3347 dpurdie 850
 
851
                #
852
                #   Examine $opt_mergPaths and process entries that look like
853
                #       build/**  -> keep the directory and every think under it
4086 dpurdie 854
                #       build/*   -> Persist directory. Keep dir tree if not
855
                #                    being imported, otherwise delete.
3347 dpurdie 856
                #
857
                foreach ( split(',', $opt_mergePaths) )
858
                {
859
                    if ( m~(.+/)\*\*$~ )
860
                    {
861
                        my $base = $1;
862
                        if ( $file =~ m~^$base~ )
863
                        {
4086 dpurdie 864
                            Verbose0("Merge Retain(2): $file");
3347 dpurdie 865
                            $keep = 1;
866
                            last;
867
                        }
868
                    }
869
                }
870
 
2764 dpurdie 871
                next if ($keep);
872
            }
873
 
4086 dpurdie 874
            Verbose0("Removing $file");
2764 dpurdie 875
            $filesDeleted++ unless ( $file =~ m~/$~ );
876
            $dirsDeleted++ if ( $file =~ m~/$~ );
379 dpurdie 877
            unlink "$opt_workdir/$file";
2764 dpurdie 878
            push @processedFiles, $file;
379 dpurdie 879
        }
2764 dpurdie 880
        @rm_files = @processedFiles;
379 dpurdie 881
 
882
        #
883
        #   Inform Subversion about the removed files
884
        #
885
        my $base = 0;
886
        my $num = $#rm_files;
2764 dpurdie 887
        Message ("Update the workspace: Removed $filesDeleted Files, $dirsDeleted directories");
379 dpurdie 888
 
889
        while ( $base <= $num )
890
        {
891
            my $end = $base + 200;
892
            $end = $num if ( $end > $num );
893
 
894
            $svn->SvnCmd ( 'delete', map ("$opt_workdir/$_@", @rm_files[$base .. $end] ),
895
                            { 'error' => 'Deleting files from workspace' } );
2049 dpurdie 896
 
379 dpurdie 897
            $base = $end + 1;
898
        }
899
    }
2049 dpurdie 900
 
379 dpurdie 901
    #
311 dpurdie 902
    #   Add New Files
903
    #   Won't add empty directories at this point
904
    #
905
    #   Process by sorted list
906
    #   This will ensure we process parent directories first
907
    #
908
    my @added = sort keys %dir;
909
    if ( @added )
910
    {
2764 dpurdie 911
        my @processedFiles;
311 dpurdie 912
        foreach my $file ( @added  )
913
        {
2764 dpurdie 914
            #
915
            #   Detect items that are to be merged
916
            #   Only specified top level paths are to be imported
3347 dpurdie 917
            #   Special mergePath names
918
            #       ++              - All files and directories
919
            #       +               - All files in the root
920
            #       path/**         - Keep all items under path
921
            #       Otherwise       - name of a directory
2764 dpurdie 922
            #
923
            if ( $opt_mergePaths )
924
            {
925
                my $discard = 1;
926
                foreach ( split(',', $opt_mergePaths) )
927
                {
3347 dpurdie 928
                    next if ( m ~\*\*$~ );
929
                    if ( $_ eq '++' )
2764 dpurdie 930
                    {
3347 dpurdie 931
                        $discard = 0;
932
                        last;
933
                    }
934
                    elsif ( $_ eq '+' )
935
                    {
2764 dpurdie 936
                        if ( ($file =~ tr~/~/~) eq 0 )
937
                        {
938
                            $discard = 0;
939
                            last;
940
                        }
941
                    }
942
                    elsif ( $file =~ m~^$_/~ )
943
                    {
944
                        $discard = 0;
945
                        last;
946
                    }
947
                }
4086 dpurdie 948
                Verbose0("Not Importing: $file") if ( $discard ) ;
2764 dpurdie 949
                next if ( $discard );
950
            }
951
 
311 dpurdie 952
            my $src = "$opt_dir/$file";
953
            my $target = "$opt_workdir/$file";
2764 dpurdie 954
            $filesAdded++ unless ( $file =~ m~/$~ );
955
            $dirsAdded++ if ( $file =~ m~/$~ );
956
            push @processedFiles, $file;
311 dpurdie 957
 
958
            if ( -d $src )
959
            {
4086 dpurdie 960
                Verbose0("Adding directory: $file");
311 dpurdie 961
                mkdir ( $target ) unless (-d $target);
962
            }
963
            else
964
            {
965
 
966
                my $path = dirname ( $target);
967
                mkdir ( $path ) unless (-d $path);
968
 
4086 dpurdie 969
                Verbose0("Adding $file");
311 dpurdie 970
                unless (File::Copy::copy( $src, $target ))
971
                {
972
                    Error("Failed to transfer file [$file]: $!");
973
                }
974
            }
975
        }
2764 dpurdie 976
        @added = @processedFiles;
977
 
311 dpurdie 978
        #
979
        #   Inform Subversion about the added files
980
        #   The command line does have a finite length, so add them 200 at a
981
        #   time.
982
        #
983
 
984
        my $base = 0;
985
        my $num = $#added;
2764 dpurdie 986
        Message ("Update the workspace: Added $filesAdded Files, $dirsAdded directories");
311 dpurdie 987
 
988
        while ( $base <= $num )
989
        {
990
            my $end = $base + 200;
991
            $end = $num if ( $end > $num );
992
 
993
            $svn->SvnCmd ( 'add'
994
                            , '--depth=empty'
995
                            , '--parents'
379 dpurdie 996
                            , map ("$opt_workdir/$_@", @added[$base .. $end] ),
311 dpurdie 997
                            { 'error' => 'Adding files to workspace' } );
998
 
999
            $base = $end + 1;
1000
        }
1001
    }
1002
 
1003
    #
1004
    #   The common files may have changed
1005
    #   Simply copy them all in and let subversion figure it out
1006
    #
1007
    foreach my $file ( sort keys %common  )
1008
    {
1009
        my $src = "$opt_dir/$file";
1010
        my $target = "$opt_workdir/$file";
1011
 
2764 dpurdie 1012
        $filesTransferred++ unless ( $file =~ m~/$~ );
1013
        $dirsTransferred++ if ( $file =~ m~/$~ );
1014
 
311 dpurdie 1015
        next if ( -d $src );
1016
        if ( File::Compare::compare ($src, $target) )
1017
        {
1018
            Verbose ("Transfer $file");
1019
            unlink $target;
1020
            unless (File::Copy::copy( $src, $target ))
1021
            {
1022
                Error("Failed to transfer file [$file]: $!",
1023
                      "Src: $src",
1024
                      "Tgt: $target");
1025
            }
1026
        }
1027
    }
2764 dpurdie 1028
    Message ("Update the workspace: Transferred $filesTransferred Files, $dirsTransferred directories")
1029
        if ($filesTransferred);
311 dpurdie 1030
 
1031
    #
1032
    #   Commit the workspace
1033
    #   This will go back onto the trunk
1034
    #
2429 dpurdie 1035
    if ( $opt_commit )
1036
    {
1037
        $svn = NewSessionByWS( $opt_workdir );
1038
        my $pkgPath = $svn->Path();
387 dpurdie 1039
 
2429 dpurdie 1040
        my $ciComment = "$pkgPath: Checkin by Svn Import";
1041
        $ciComment .= "\n" . $opt_log if ( $opt_log );
1042
        $ciComment =~ s~\r\n~\n~g;
1043
        $ciComment =~ s~\r~\n~g;
1044
        $ciComment = encode('UTF-8', $ciComment, Encode::FB_DEFAULT);
387 dpurdie 1045
 
2429 dpurdie 1046
        $svn->SvnCi ('comment' => $ciComment, 'allowSame' => 1 );
1047
        Message ("Repository Ref: " . $svn->RmRef) unless( $opt_label );
4076 dpurdie 1048
        unless ($svn->{NoRepoChanges}) {
1049
            $svn->setRepoProperty('svn:author', $opt_author) if (defined ($opt_author));
1050
            $svn->setRepoProperty('svn:date', $opt_date) if (defined ($opt_date));
1051
        }
2429 dpurdie 1052
 
1053
        #
1054
        #   Label the result
1055
        #   The workspace will have been updated, so we can use it as the base for
1056
        #   the labeling process
1057
        #
1058
        if ( $opt_label )
1059
        {
4076 dpurdie 1060
            my $tagComment = "$pkgPath: Tagged by Jats Svn Import";
1061
            if ($svn->{NoRepoChanges} && $opt_log )
1062
            {
1063
                $tagComment .= "\nNo Repository changes on last commit. Comment was:";
1064
                $tagComment .= "\n" . $opt_log;
1065
                $tagComment =~ s~\r\n~\n~g;
1066
                $tagComment =~ s~\r~\n~g;
1067
                $tagComment = encode('UTF-8', $tagComment, Encode::FB_DEFAULT);
1068
            }
2429 dpurdie 1069
            $svn->SvnCopyWs (
1070
                           target => $url_label,
1071
                           'noswitch' => 1,
1072
                           'replace' => $opt_replace,
4076 dpurdie 1073
                           'comment' => $tagComment,
2429 dpurdie 1074
                           );
1075
            Message ("Repository Ref: " . $svn->RmRef);
1076
            Message ("Vcs Tag       : " . $svn->SvnTag);
1077
            $svn->setRepoProperty('svn:author', $opt_author) if (defined ($opt_author));
1078
            $svn->setRepoProperty('svn:date', $opt_date) if (defined ($opt_date));
1079
        }
311 dpurdie 1080
    }
2429 dpurdie 1081
    else
1082
    {
1083
        Message ("Workspace not commited","Workspace: $opt_workdir");
1084
    }
311 dpurdie 1085
 
1086
    #
1087
    #   Clean up
1088
    #
2429 dpurdie 1089
    if ( $opt_delete && ! $opt_reuse  && $opt_commit )
311 dpurdie 1090
    {
1091
        Message ("Delete Workspace");
1092
        rmtree( $opt_workdir );
1093
    }
379 dpurdie 1094
 
1095
    #
1096
    #   Automation data transfer
1097
    #
1098
    if ( defined $opt_datafile )
1099
    {
1100
        my $data = JatsProperties::New();
1101
 
1102
        $data->setProperty('Command'        , 'ImportPackage');
1103
        $data->setProperty('Label'          , $opt_label);
1403 dpurdie 1104
        $data->setProperty('subversion.url' , $svn->RmRef);
1105
        $data->setProperty('subversion.tag' , $svn->SvnTag);
379 dpurdie 1106
 
2764 dpurdie 1107
        $data->setProperty('files.base'     , $filesBase);
1108
        $data->setProperty('files.removed'  , $filesDeleted);
1109
        $data->setProperty('files.added'    , $filesAdded);
1110
 
379 dpurdie 1111
        $data->Dump('InfoFile') if ($opt_verbose);
1112
        $data->store( $opt_datafile );
1113
    }
1114
 
311 dpurdie 1115
    $opr_done = 1;
1116
}
1117
 
1118
#-------------------------------------------------------------------------------
385 dpurdie 1119
# Function        : DeleteBranch
1120
#
1121
# Description     : Delete the branch that a workspace is based upon
1122
#
2049 dpurdie 1123
# Inputs          :
385 dpurdie 1124
#
2049 dpurdie 1125
# Returns         :
385 dpurdie 1126
#
1127
sub DeleteBranch
1128
{
1129
    my $opt_path;
1130
    my $opt_error = 0;
1131
    #
1132
    #   Parse more options
1133
    #
1134
    GetOptions (
1135
                "help:+"        => \$opt_help,
1136
                "manual:3"      => \$opt_help,
1137
                "path:s"        => \$opt_path,
1138
                ) || Error ("Invalid command line" );
1139
 
1140
    #
1141
    #   Subcommand specific help
1142
    #
1143
    SubCommandHelp( $opt_help, "Delete Branch") if ($opt_help);
1144
 
1145
    #
1146
    #   Sanity Tests
1147
    #
2429 dpurdie 1148
    Message ("Delete Workspace Branchs" );
385 dpurdie 1149
 
1150
    #
1151
    #   Do all the hard work
1152
    #
1153
    $opt_path = '.' unless ( defined $opt_path );
1154
    my $uref = NewSessionByWS($opt_path, 0, 1);
1155
    my $ws_root = $uref->SvnLocateWsRoot(1);
1156
    my $ws_url = $uref->FullWs();
1157
 
1158
    #
2931 dpurdie 1159
    #   What we do depends what arguments the user provided
385 dpurdie 1160
    #
2429 dpurdie 1161
    unless ( @ARGV )
1162
    {
1163
        #
1164
        #   If no branch was specified - then display the workspace branch
1165
        #
1166
        Error ('The workspace is not based on a branch')
1167
            unless ( $ws_url =~ m ~/branches/(.*)~ );
1168
        Message('The workspace is based on the branch: '. $1);
1169
    }
1170
    else
1171
    {
1172
        #
1173
        #   Delete all specified branches
1174
        #
1175
        foreach my $branch ( @ARGV )
1176
        {
1177
            Message ("Deleting: " . $branch );
1178
            my $target = join( '/', $uref->FullPath(), 'branches', $branch);
1179
            if ( $uref->SvnDelete (
1180
                              'target'    => $target,
1181
                              'comment'   => [$uref->Path().": Delete Branch",'Deleted by user command: jats svn delete-branch'],
1182
                              'noerror'   => 1,
1183
                              )
1184
               )
1185
            {
1186
                Warning ("Branch deletion failed: $branch");
1187
            }
1188
        }
1189
    }
385 dpurdie 1190
    $opr_done = 1;
1191
}
1192
 
2049 dpurdie 1193
#-------------------------------------------------------------------------------
1194
# Function        : CreateBranch
1195
#
1196
# Description     : Branch a workspace and then switch to the new branch
1197
#
1198
# Inputs          :
1199
#
1200
# Returns         :
1201
#
1202
sub CreateBranch
1203
{
1204
    my $opt_path;
1205
    my $opt_comment;
1206
    my $opt_switch = 1;
1207
    my $opt_branch;
385 dpurdie 1208
 
2049 dpurdie 1209
    #
1210
    #   Parse more options
1211
    #
1212
    GetOptions (
1213
                "help:+"        => \$opt_help,
1214
                "manual:3"      => \$opt_help,
1215
                "path:s"        => \$opt_path,
1216
                "switch!"       => \$opt_switch,
1217
                "comment:s"     => \$opt_comment,
1218
                ) || Error ("Invalid command line" );
1219
 
1220
    #
1221
    #   Subcommand specific help
1222
    #
1223
    SubCommandHelp( $opt_help, "Create Branch") if ($opt_help);
1224
 
1225
    #
1226
    #   Sanity Tests
1227
    #
1228
    Message ("Create Workspace Branch" );
1229
    Error ("Too many arguments: @ARGV") if ( $#ARGV > 0 );
1230
    Error ("Not enough arguments. No branch name specified") if ( $#ARGV < 0 );
1231
 
1232
    #
1233
    #   Sanity test the label
1234
    #
1235
    $opt_branch = SvnIsaSimpleLabel ($ARGV[0] );
1236
 
1237
    #
1238
    #   Do all the hard work
1239
    #
1240
    $opt_path = '.' unless ( defined $opt_path );
1241
    my $uref = NewSessionByWS($opt_path, 0, 1);
1242
    my $ws_root = $uref->SvnLocateWsRoot(1);
1243
    my $ws_url = $uref->Full();
1244
 
1245
    #
2931 dpurdie 1246
    #   Use the version of the branch that has been committed as the base of the
1247
    #   copy. If the user has modified files, then they won't be committed
2049 dpurdie 1248
    #
1249
    #   This operation will be server-side only
1250
    #
1251
    Message ("Creating branch: $opt_branch");
1252
    my $repoLink = $uref->{InfoWs}{URL} . '@' . $uref->{InfoWs}{Revision};
1253
    $uref->{DEVBRANCH} =  join ('/', 'branches', $opt_branch);
1254
    my $branch_tag = $uref->SvnCopy (
1255
                'old' => $repoLink,
1256
                'new' => join ('/', $ws_url, $uref->{DEVBRANCH} ),
5073 dpurdie 1257
                'comment' => $opt_comment ? $opt_comment : ('Created by Jats svn branch:' . $opt_branch),
2049 dpurdie 1258
                'replace' => 0,
6653 dpurdie 1259
                'parents' => 1,
2049 dpurdie 1260
                );
1261
 
2054 dpurdie 1262
 
2049 dpurdie 1263
    if ( $opt_switch )
1264
    {
1265
        Verbose ("Switching to new branch: $opt_branch");
1266
        $branch_tag = SvnPath2Url($branch_tag);
2054 dpurdie 1267
        chdir ($ws_root) || Error ("Cannot cd to: " .$ws_root);
1268
        $uref->SvnSwitch ($branch_tag, $opt_path, '--Print', '--KeepWs' );
2049 dpurdie 1269
    }
1270
    else
1271
    {
1272
        Warning ("Using existing workspace, not the created branch");
1273
    }
1274
    Message ("Repository Ref: " . $uref->RmRef);
1275
    Message ("Vcs Tag       : " . $uref->SvnTag);
1276
 
1277
#    #
1278
#    #   The copy operation *should* be a server side operation only
2931 dpurdie 1279
#    #   If the user has committed changes, but not yet updated the local
2049 dpurdie 1280
#    #   workspace, then subversion will do a client side copy
1281
#    #   This is not good.
1282
#    #
1283
#    $uref->SvnCopyWs (
1284
#                   target => join ('/', $ws_url, 'branches', $opt_branch),
1285
#                   'allowLocalMods' => 1,
1286
#                   'noupdatecheck' => 1,
1287
#                   'noswitch' => ! $opt_switch,
1288
#                   'replace' => 0,
5073 dpurdie 1289
#                   'comment' => $opt_comment ? $opt_comment : ('Created by Jats svn branch:' . $opt_branch),
2049 dpurdie 1290
#                   );
1291
#
1292
#    Message ("Repository Ref: " . $uref->RmRef);
1293
#    Message ("Vcs Tag       : " . $uref->SvnTag);
1294
 
1295
    $opr_done = 1;
1296
}
1297
 
385 dpurdie 1298
#-------------------------------------------------------------------------------
2049 dpurdie 1299
# Function        : SwitchBranch
1300
#
1301
# Description     : Switch to a specified branch
1302
#
1303
# Inputs          :
1304
#
1305
# Returns         :
1306
#
1307
sub SwitchBranch
1308
{
1309
    my $opt_path = '.';
1310
    my $opt_branch;
1311
 
1312
    #
1313
    #   Parse more options
1314
    #
1315
    GetOptions (
1316
                "help:+"        => \$opt_help,
1317
                "manual:3"      => \$opt_help,
1318
                "path:s"        => \$opt_path,
1319
                ) || Error ("Invalid command line" );
1320
 
1321
    #
1322
    #   Subcommand specific help
1323
    #
1324
    SubCommandHelp( $opt_help, "Switch Branch") if ($opt_help);
1325
    return ShowBranches($opt_path) if ( $#ARGV < 0 );
1326
 
1327
    #
1328
    #   Sanity Tests
1329
    #
1330
    Error ("Too many arguments: @ARGV") if ( $#ARGV > 0 );
1331
 
1332
    #
1333
    #   Calculate the target name
1334
    #       trunk is special
1335
    #       tags/... is special
1336
    $opt_branch = $ARGV[0];
1337
    if ( $opt_branch eq 'trunk' ) {
1338
    } elsif ( $opt_branch =~ m~tags/.+~ ) {
1339
    } else {
1340
        $opt_branch = join ('/', 'branches', $opt_branch);
1341
    }
1342
    Message ("Switching to new branch: $opt_branch");
1343
 
1344
    #
1345
    #   Do all the hard work
1346
    #
1347
    my $uref = NewSessionByWS($opt_path, 0, 1);
2054 dpurdie 1348
    my $ws_root = $uref->SvnLocateWsRoot(1);
2049 dpurdie 1349
    my $ws_url = $uref->Full();
1350
    my $branch_tag = join ('/', $ws_url, $opt_branch);
1351
 
1352
    #
1353
    #   Validate the branch
1354
    #
1355
    $uref->SvnValidateTarget (
1356
                        'cmd'    => 'svn switch',
1357
                        'target' => $branch_tag,
1358
                        'require' => 1,
1359
                        );
1360
 
2054 dpurdie 1361
    #
1362
    #   Must Change directory before we switch
2931 dpurdie 1363
    #   Otherwise we will import changes into the wrong place
2054 dpurdie 1364
    #
1365
    chdir ($ws_root) || Error ("Cannot cd to: " . $ws_root);
1366
    $uref->SvnSwitch ($branch_tag, $opt_path, '--Print', '--KeepWs' );
2049 dpurdie 1367
    $opr_done = 1;
1368
}
1369
 
1370
#-------------------------------------------------------------------------------
7217 dpurdie 1371
# Function        : SvnMerge 
1372
#
1373
# Description     : Perform an svn merge 
1374
#                       - with sanity checking
1375
#                       - auto deterine the correct 'head' to merge from
1376
#                  
1377
#
1378
# Inputs          : None
1379
#
1380
# Returns         : 
1381
#
1382
sub SvnMerge
1383
{
1384
    my $opt_path = '.';
1385
    my $opt_info;
1386
    my @mergeOpts;
1387
    my $opt_dryRun;
1388
 
1389
    #
1390
    #   Parse more options
1391
    #
1392
    Getopt::Long::Configure('pass_through');
1393
    GetOptions (
1394
                "help:+"        => \$opt_help,
1395
                "manual:3"      => \$opt_help,
1396
                "path:s"        => \$opt_path,
1397
                'info'          => \$opt_info,
1398
                'dry-run'       => \$opt_dryRun,
1399
                ) || Error ("Invalid command line" );
1400
 
1401
    #
1402
    #   Subcommand specific help
1403
    #
1404
    SubCommandHelp( $opt_help, "Sync Merge") if ($opt_help);
1405
 
1406
    #
1407
    #   Save merge options
1408
    #   Error if a non-option is present
1409
    #
1410
    foreach (@ARGV) {
1411
        if (m~^-~) {
1412
            push @mergeOpts, $_;
1413
        } else {
1414
            Error ("Only options must be passed to Merge: $_");
1415
        }
1416
    }
1417
 
1418
    #
1419
    #   We intercepted the dry-run option
1420
    #   Put the option back into the stream.
1421
    if ($opt_dryRun) {
1422
        push @mergeOpts, '--dry-run';
1423
    }
1424
 
1425
    #   Check we are in a workspace
1426
    #   Create an SVN session
1427
    #   
1428
    my $uref = NewSessionByWS($opt_path, 0, 1);
1429
#    DebugDumpData("uref", $uref);
1430
 
1431
    #
1432
    #   Warn user if the command is being executed from within a subdirectory of the workspace
1433
    #   It might work, but if the directory is deleted it will go badly
1434
    #
1435
    my $ws_root = mustBeWsRoot($uref);
1436
 
1437
    #
1438
    #   Determine the source of the merge
1439
    #   Get some more workspace information
1440
    # 
1441
    $uref->getWsExtraInfo();
1442
    my $logInfo = $uref->{InfoWsExtra};
1443
#DebugDumpData("getWsExtraInfo", $logInfo);
1444
 
1445
    # A bit of sanity testing
1446
    Error("Workspace does not appear to be a branch") unless (exists $logInfo->{'copyfrom-path'}); 
1447
    Error("Workspace does not appear to be a branch") unless (exists $logInfo->{'target'}); 
1448
    Error("Workspace is a trunk") if ($logInfo->{'target'} =~ m~/trunk$~);
1449
    Error("Workspace is a raw branch") if ($logInfo->{'target'} =~ m~/branches$~);
1450
    Error("Workspace is a raw tag") if ($logInfo->{'target'} =~ m~/tags$~);
1451
    Error("Workspace is a within a tag") if ($logInfo->{'target'} =~ m~/tags/~);
1452
 
1453
    #   Ensure the source is a branch and not a trunk
1454
    #   Ensure this workspace is not on the same bit (trunk or branch) 
1455
    #   
1456
    Message ("Merge Info - No merge performed") if $opt_info;
1457
    Message ("RepoRoot: " . $uref->{InfoWs}{'Repository Root'});
1458
    Message ("Parent: " . $logInfo->{'copyfrom-path'});
1459
    Message ("Workspace: " . $logInfo->{'target'});
1460
 
1461
    unless ($opt_info) {
1462
        #
1463
        #   $logInfo->{'copyfrom-path'} is the parent of the branch in the workspace
1464
        #   use merge ^/<copyfrom-path> to merge the data into this workspace
1465
        #
1466
        #   Perform an interactive command so that the user can accept conflicts - if they want
1467
        my $rv = SvnUserCmd( 'merge',
1468
                @mergeOpts,
1469
                '^' . $logInfo->{'copyfrom-path'},
1470
                $opt_path,
1471
                { 'credentials' => 1 });
1472
 
1473
        exit $rv;
1474
    }
1475
    $opr_done = 1;
1476
}
1477
 
1478
#-------------------------------------------------------------------------------
1479
# Function        : SvnReintegrate
1480
#
1481
# Description     : Perform an svn merge --reintegrate
1482
#                       - with much sanity checking
1483
#                       - auto deterine the correct 'head' to merge from
1484
#                       - will delete the branch
1485
#                  
1486
#
1487
# Inputs          : None
1488
#
1489
# Returns         : 
1490
#
1491
sub SvnReintegrate
1492
{
1493
    my $opt_path = '.';
1494
    my $opt_info;
1495
    my @mergeOpts;
1496
    my $opt_reintegrate;
1497
    my $opt_dryRun;
1498
 
1499
    #
1500
    #   Parse more options
1501
    #
1502
    Getopt::Long::Configure('pass_through');
1503
    GetOptions (
1504
                "help:+"        => \$opt_help,
1505
                "manual:3"      => \$opt_help,
1506
                "path:s"        => \$opt_path,
1507
                'info'          => \$opt_info,
1508
                'reintegrate!'  => \$opt_reintegrate,
1509
                'dry-run'       => \$opt_dryRun,
1510
                ) || Error ("Invalid command line" );
1511
 
1512
    #
1513
    #   Subcommand specific help
1514
    #
1515
    SubCommandHelp( $opt_help, "Reintegrate Merge") if ($opt_help);
1516
 
1517
    #
1518
    #   Save merge options
1519
    #   Error if a non-option is present
1520
    #
1521
    foreach (@ARGV) {
1522
        if (m~^-~) {
1523
            push @mergeOpts, $_;
1524
        } else {
1525
            Error ("Only options must be passed to Reintegrate: $_");
1526
        }
1527
    }
1528
 
1529
    #
1530
    #   We intercepted the dry-run option, so that we know not to delete the Branch
1531
    #   Put the option back into the stream.
1532
    if ($opt_dryRun) {
1533
        push @mergeOpts, '--dry-run';
1534
        $opt_reintegrate = 1;
1535
    }
1536
 
1537
    #   Check we are in a workspace
1538
    #   Create an SVN session
1539
    #   
1540
    my $uref = NewSessionByWS($opt_path, 0, 1);
1541
#    DebugDumpData("uref", $uref);
1542
 
1543
    #
1544
    #   Warn user if the command is being executed from within a subdirectory of the workspace
1545
    #   It might work, but if the directory is deleted it will go badly
1546
    #
1547
    my $ws_root = mustBeWsRoot($uref);
1548
 
1549
    #
1550
    #   Determine the source of the merge
1551
    #   Get some more workspace information
1552
    # 
1553
    $uref->getWsExtraInfo();
1554
    my $logInfo = $uref->{InfoWsExtra};
1555
#DebugDumpData("getWsExtraInfo", $logInfo);
1556
 
1557
    # A bit of sanity testing
1558
    Error("Workspace does not appear to be a branch") unless (exists $logInfo->{'copyfrom-path'}); 
1559
    Error("Workspace does not appear to be a branch") unless (exists $logInfo->{'target'}); 
1560
    Error("Workspace is a trunk") if ($logInfo->{'target'} =~ m~/trunk$~);
1561
    Error("Workspace is a raw branch") if ($logInfo->{'target'} =~ m~/branches$~);
1562
    Error("Workspace is a raw tag") if ($logInfo->{'target'} =~ m~/tags$~);
1563
    Error("Workspace is a within a tag") if ($logInfo->{'target'} =~ m~/tags/~);
1564
 
1565
    #   Ensure the source is a branch and not a trunk
1566
    #   Ensure this workspace is not on the same bit (trunk or branch) 
1567
    #   
1568
    Message ("Reintegrate Info - No merge performed") if ($opt_info || !$opt_reintegrate);
1569
    Message ("RepoRoot: " . $uref->{InfoWs}{'Repository Root'});
1570
    Message ("Parent Branch: " . $logInfo->{'copyfrom-path'});
1571
    Message ("Workspace Branch: " . $logInfo->{'target'} . " <<-- WILL BE DELETED");
1572
    Message ("No merge performed.","Use '-reintegrate' to acknolowedge the operation, or '-dry-run'") if (!$opt_info && !$opt_reintegrate);
1573
 
1574
    #
1575
    #   Examine the workspace and ensure that there are no modified
1576
    #   files - unless they are expected
1577
    #   
1578
    #   Prevent the user from merging into a WS that has not been committed
1579
    #
1580
    $uref->SvnWsModified ( 'cmd' => 'Reintegrate' );
1581
 
1582
    unless ($opt_info || !$opt_reintegrate) {
1583
        #
1584
        #   Switch the workspace to the parent
1585
        #       Must Change directory before we switch
1586
        #       Otherwise we will import changes into the wrong place
1587
        #
1588
        Message ("Switching workspace to : " . $logInfo->{'copyfrom-path'} );
1589
        chdir ($ws_root) || Error ("Cannot cd to: " . $ws_root);
1590
        $uref->SvnSwitch ( '^' . $logInfo->{'copyfrom-path'}, '.', '--Print', '--KeepWs' );
1591
 
1592
        #
1593
        #   $logInfo->{'target'} is the branch the workspace was on - before the switch
1594
        #   use merge --reintegrate ^/<target> to merge the data into this workspace
1595
        #
1596
        #   Perform an interactive command so that the user can accept conflicts - if they want
1597
        #
1598
        Message ("Reintegrate Merge from " . $logInfo->{'target'} . " to " .  $logInfo->{'copyfrom-path'} );
1599
        my $rv = SvnUserCmd( 'merge', '--reintegrate',
1600
                @mergeOpts,
1601
                '^' . $logInfo->{'target'},
1602
                '.',
1603
                { 'credentials' => 1 });
1604
 
1605
        Error ("Merge error", "Workspace has been switched to $logInfo->{'copyfrom-path'}", "Its state is unknown.") if $rv;
1606
 
1607
        unless ($opt_dryRun) {
1608
            #
1609
            #   The merge appears to be good
1610
            #   Delete the branch we merged from. Svn Red Book says that it can't be reused ( without a bit more work )
1611
            #
1612
            Message("Deleting feature branch: $logInfo->{'target'}");
1613
 
1614
            $rv = $uref->SvnDelete (
1615
                              'target'      => '^' . $logInfo->{'target'},
1616
                              'comment'   => [$uref->Path().": Delete Branch",'Deleted by user command: jats svn reintegrate as the branch is no longer usable'],
1617
                              'noerror'   => 1,
1618
                              );
1619
            if ($rv) {
1620
                Error ('SvnReintegrate: Branch not deleted');
1621
            }
1622
 
1623
            Message("Reintegration Merge complete",
1624
                     "The branch has been deleted: svn $logInfo->{'target'}",
1625
                     "The workspace has been switched to: $logInfo->{'copyfrom-path'}",
1626
                     "The workspace needs to be verified and committed."
1627
                     );
1628
            }
1629
        else
1630
        {
1631
            Message("Dry Run of the integration merge is complete",
1632
                   "Quietly switching back to $logInfo->{'target'}");
1633
            $uref->SvnSwitch ( '^' . $logInfo->{'target'}, '.', '--NoPrint', '--KeepWs' );
1634
        }
1635
        exit 0;
1636
    }
1637
    $opr_done = 1;
1638
}
1639
 
1640
#-------------------------------------------------------------------------------
1641
# Function        : mustBeWsRoot 
1642
#
1643
# Description     : Ensure that the user is not in a subdirectory of a workspace 
1644
#
1645
# Inputs          : $uref   - A Svn session handle
1646
#
1647
# Returns         : Will not return on error
1648
#                   Return the workspace root as provided by SvnLocateWsRoot
1649
#
1650
sub mustBeWsRoot
1651
{
1652
    my ($uref) = @_;
1653
 
1654
    my $ws_root = $uref->SvnLocateWsRoot(0);
1655
    my $pathToRoot = RelPath($ws_root);
1656
    if ( $pathToRoot =~ m~^..~) {
1657
        Error("This command cannot be executed within a subdirectory of the workspace",
1658
                "It can be executed in the root of the workspace: $pathToRoot",
1659
                "It can be executed externally with the -path option");
1660
    }
1661
 
1662
    return $ws_root;
1663
}
1664
 
1665
#-------------------------------------------------------------------------------
2049 dpurdie 1666
# Function        : ShowBranches
1667
#
1668
# Description     : Show branches in current workspace
1669
#                   Internal use only
1670
#
1671
# Inputs          : $opt_path           - Optional path
1672
#
1673
# Returns         :
1674
#
1675
sub ShowBranches
1676
{
1677
    my ($opt_path) = @_;
1678
 
1679
    my $uref = NewSessionByWS($opt_path, 0, 1);
1680
    my $ws_url = $uref->Full();
1681
 
1682
    #
2931 dpurdie 1683
    #   Display the packages full URL - allow the user to manually look at more
1684
    #   List the branches
2049 dpurdie 1685
    #
1686
    Message ("Url: $ws_url", 'Available Branches');
1687
    SvnUserCmd( 'ls', join ('/', $ws_url, 'branches'), { 'credentials' => 1 });
1688
    $opr_done = 1;
1689
}
1690
#-------------------------------------------------------------------------------
311 dpurdie 1691
# Function        : SubCommandHelp
1692
#
1693
# Description     : Provide help on a subcommand
1694
#
1695
# Inputs          : $help_level             - Help Level 1,2,3
1696
#                   $topic                  - Topic Name
1697
#
1698
# Returns         : This function does not return
1699
#
1700
sub SubCommandHelp
1701
{
1702
    my ($help_level, $topic) = @_;
1703
    my @sections;
1704
    #
1705
    #   Spell out the section we want to display
1706
    #
1707
    #   Note:
1708
    #   Due to bug in pod2usage can't use 'head1' by itself
1709
    #   Each one needs a subsection.
1710
    #
1711
    push @sections, qw( NAME SYNOPSIS ) ;
1712
    push @sections, qw( ARGUMENTS OPTIONS ) if ( $help_level > 1 );
1713
    push @sections, qw( DESCRIPTION )       if ( $help_level > 2 );
1714
 
1715
    #
1716
    #   Extract section from the POD
1717
    #
1718
    pod2usage({-verbose => 99,
1719
               -noperldoc => 1,
1720
               -sections => $topic . '/' . join('|', @sections) } );
1721
}
1722
 
1723
#-------------------------------------------------------------------------------
1724
#   Documentation
1725
#   NOTE
1726
#
1727
#   Each subcommand MUST have
1728
#   head1 section as used by the subcommand
1729
#       This should be empty, as the contents will NOT be displayed
1730
#   head2 sections called
1731
#       NAME SYNOPSIS ARGUMENTS OPTIONS DESCRIPTION
1732
#
1733
#=head1 xxxxxx
1734
#=head2 NAME
1735
#=head2 SYNOPSIS
1736
#=head2 ARGUMENTS
1737
#=head2 OPTIONS
1738
#=head2 DESCRIPTION
1739
#
1740
 
1741
=pod
1742
 
361 dpurdie 1743
=for htmltoc    GENERAL::Subversion::
1744
 
311 dpurdie 1745
=head1 NAME
1746
 
1747
jats svn - Miscellaneous SubVersion Operations
1748
 
1749
=head1 SYNOPSIS
1750
 
1751
jats svn [options] command [command options]
1752
 
1753
 Options:
1754
    -help[=n]              - Help message, [n=1,2,3]
1755
    -man                   - Full documentation [-help=3]
1756
    -verbose[=n]           - Verbose command operation
1757
 
1758
 Common Command Options:
1759
    All command support suboptions to provide command specific help
1760
 
1761
    -help[=n]              - Help message, [n=1,2,3]
1762
    -man                   - Full documentation [-help=3]
1763
 
1764
 Commands are:
363 dpurdie 1765
    test                   - Test access to subversion
369 dpurdie 1766
    paths                  - Display Subversion tag to URL conversions
311 dpurdie 1767
    ls URL                 - List Repo contents for URL
369 dpurdie 1768
    tag [URL]              - Convert URL or Path to a Release Manager Tag
1769
    url [TAG]              - Convert TAG or Path to a Subversion URL
2049 dpurdie 1770
    create-package URL     - Create a new package at URL
311 dpurdie 1771
    delete-package URL     - Delete Package Subtree
2049 dpurdie 1772
    branch BRANCH          - Create a Development Branch
1773
    switch [BRANCH]        - Switch to a Development Branch
385 dpurdie 1774
    delete-branch          - Delete a Development Branch
311 dpurdie 1775
    import URL             - Import files to package at URL
7217 dpurdie 1776
    merge                  - Merge head into a feature branch
1777
    reintegrate            - Integrate a feature branch to its head
311 dpurdie 1778
 
7217 dpurdie 1779
 
311 dpurdie 1780
 Use the command
1781
    jats svn command -h
1782
 for command specific help
1783
 
1784
=head1 OPTIONS
1785
 
1786
=over
1787
 
1788
=item B<-help[=n]>
1789
 
1790
Print a help message and exit. The level of help may be either 1, 2 or
1791
3 for a full manual.
1792
 
1793
This option may be specified multiple times to increment the help level, or
1794
the help level may be directly specified as a number.
1795
 
1796
=item B<-man>
1797
 
1798
This is the same as '-help=3'.
1799
The complete help is produced in a man page format.
1800
 
2429 dpurdie 1801
=item B<-verbose[=n]>
311 dpurdie 1802
 
1803
This option will increase the level of verbosity of the commands.
1804
 
1805
If an argument is provided, then it will be used to set the level, otherwise the
1806
existing level will be incremented. This option may be specified multiple times.
1807
 
1808
=back
1809
 
1810
=head1 DESCRIPTION
1811
 
1812
This program provides a number of useful Subversion based operations.
1813
 
363 dpurdie 1814
=head1 Test Subversion
1815
 
1816
=head2 NAME
1817
 
1818
Test Subversion
1819
 
1820
=head2 SYNOPSIS
1821
 
1822
    jats svn test
1823
 
1824
=head2 DESCRIPTION
1825
 
1826
This command will ensure that the subversion command line utility can be
1827
located. The command will report the version of the svn client found.
1828
 
369 dpurdie 1829
=head1 Subversion Paths
1830
 
1831
=head2 NAME
1832
 
1833
Subversion Paths
1834
 
1835
=head2 SYNOPSIS
1836
 
1837
    jats svn paths
1838
 
1839
=head2 DESCRIPTION
1840
 
1841
This command will display the base Tags and associated URLs that are used by
1842
JATS to convert a 'Subversion Tag' into a full URLs that will be used to access
1843
a physical repository.
1844
 
1845
The 'Tags' configuration is site-specific.
1846
 
311 dpurdie 1847
=head1 List Repository
1848
 
363 dpurdie 1849
=head2 NAME
1850
 
1851
List Repository
1852
 
1853
=head2 SYNOPSIS
1854
 
1855
    jats svn ls <URL>
1856
 
1857
=head2 DESCRIPTION
1858
 
311 dpurdie 1859
This command will take a URL and perform a 'svn' list operation. The URL will
1860
be expanded to include the site specific repository.
1861
 
369 dpurdie 1862
=head1 Url to Tag
1863
 
1864
=head2 NAME
1865
 
1866
Url to Tag
1867
 
1868
=head2 SYNOPSIS
1869
 
1870
    jats svn tag [Option] [tag]
1871
 
1872
 Options:
1873
    -help[=n]              - Help message, [n=1,2,3]
1874
    -man                   - Full documentation [-help=3]
1875
    -path=path             - Convert specified path
1876
    -url=url               - Convert specified URL
1877
 
1878
=head2 DESCRIPTION
1879
 
1880
This command will convert a URL or a PATH to a Subversion Tag that can
1881
be used within the remainder of the build system. If no PATH or URL is provided,
1882
then the command uses a path of the current directory.
1883
 
1884
The command will convert either a PATH or a URL. It will not do both.
1885
 
1886
The command will use the configured Subversion URL prefixes to create the Tag.
1887
 
1888
If a PATH is to be converted, then the PATH must address a Subversion workspace.
1889
The conversion will return a Tag to the root of the Workspace and Peg it to
1890
the last committed version. The command will not determine if the workspace
1891
contains modified files.
1892
 
1893
If a URL is to be converted, then the resultant value should be used with
1894
caution. The result is only as good as the provided URL and may not address
1895
the root of a package.
1896
 
1897
=head1 Tag to Url
1898
 
1899
=head2 NAME
1900
 
1901
Tag to Url
1902
 
1903
=head2 SYNOPSIS
1904
 
1905
    jats svn url [Option] [url]
1906
 
1907
 Options:
1908
    -help[=n]              - Help message, [n=1,2,3]
1909
    -man                   - Full documentation [-help=3]
1910
    -path=path             - Convert specified path
1911
    -url=url               - Convert specified URL
1912
 
1913
=head2 DESCRIPTION
1914
 
1915
This command will convert a TAG or a PATH to a full URL that can be used
1916
directly by Subversion. If no PATH or TAG is provided, then the command uses a
1917
path of the current directory.
1918
 
2429 dpurdie 1919
The command will convert either a TAG or a PATH. It will not do both.
369 dpurdie 1920
 
1921
The command will use the configured Subversion URL prefixes to expand the TAG.
1922
 
1923
If a PATH is to be converted, then the PATH must address a Subversion workspace.
1924
The conversion will return a URL to the root of the Workspace and Peg it to
1925
the last committed version. The command will not determine if the workspace
1926
contains modified files.
1927
 
1928
If a TAG is to be converted, then the resultant value should be used with
1929
caution. The result is only as good as the provided URL and may not address
1930
the root of a package.
1931
 
2429 dpurdie 1932
=head3 Examples
1933
 
1934
To display the URL of the current workspace
1935
 
1936
    jats svn url
1937
 
1938
To display the URL of a known workspace
1939
 
1940
    jats svn url -path=myWorkSpace
1941
 
1942
To convert a TAG from Release Manager or other JATS commands
1943
 
1944
    jats svn url AUPERASVN01/COTS
1945
    jats svn url SVN::AUPERASVN01/COTS/bouncycastle/trunk::bouncycastle_1.3.1.cots@502
1946
 
2049 dpurdie 1947
=head1 Create a Package Version
1948
 
1949
=head2 NAME
1950
 
1951
Create a Package Version
1952
 
1953
=head2 SYNOPSIS
1954
 
1955
jats svn [options] create-package URL [command options]
1956
 
1957
 Options:
1958
    -help[=n]               - Help message, [n=1,2,3]
1959
    -man                    - Full documentation [-help=3]
1960
    -verbose[=n]            - Verbose command operation
1961
 
1962
 Command Options
1963
    -help[=n]               - Provide command specific help
1964
    -new                    - Package must not exist
1965
    -replace                - Replace any existing versions
2429 dpurdie 1966
    -import=path            - Import directory tree
2049 dpurdie 1967
    -label=nnn              - Label imported package
1968
    -trunk                  - Import to trunk (default)
1969
    -tags=nnn               - Import to tags
1970
    -branch=nnn             - Import to branches
1971
 
1972
=head2 ARGUMENTS
1973
 
1974
The command takes one argument: The URL of the desired package.
1975
This may be be:
1976
 
1977
=over
1978
 
1979
=item * A full URL
1980
 
1981
Complete with protocol and path information.
1982
 
1983
=item * A simple URL
1984
 
1985
JATS will prepend the site-specific repository location to the user provided URL
1986
 
1987
=back
1988
 
1989
=head2 OPTIONS
1990
 
1991
=over
1992
 
1993
=item -help[=n]
1994
 
1995
Print a help message and exit. The level of help may be either 1, 2 or 3.
1996
 
1997
This option may be specified multiple times to increment the help level, or
1998
the help level may be directly specified as a number.
1999
 
2000
=item -new
2001
 
2002
This option specifies that the named package MUST not exist at all.
2003
 
2004
=item -replace
2005
 
2006
This option allows the program to replace any existing versions of the
2007
imported source. It will allow the deletion of any existing trunk, tags or
2008
branches.
2009
 
2429 dpurdie 2010
=item -import=path
2049 dpurdie 2011
 
2012
This option specifies the path of a subdirectory tree to import into the newly
2013
created package. In not provided, then only a package skeleton will be created.
2014
 
2429 dpurdie 2015
All files and directories below, but not including, the named path will be
2016
imported into the package.
2017
 
4096 dpurdie 2018
The imported directory tree will be scanned to ensure that the following subdirectories
2019
do not exist: .svn, .hg, .git, .cvs, tags, trunk and branches. These directories are
2020
either reserved or indicative that the import tree is already version controlled.
2021
 
2049 dpurdie 2022
=item -label=nnn
2023
 
2024
This option specifies a label to place the imported source.
2025
 
2026
=item -trunk
2027
 
2028
This option specifies that imported source will be placed on the trunk of the
2029
package. This is the default mode of import.
2030
 
2031
The options -trunk, -tags and -branch are mutually exclusive.
2032
 
2033
=item -tags=nnn
2034
 
2035
This option specifies that imported source will be placed directly on the
2036
named tag of the package.
2037
 
2038
The options -trunk, -tags and -branch are mutually exclusive.
2039
 
2040
=item -branch=nnn
2041
 
2042
This option specifies that imported source will be placed directly on the
2043
named branch of the package.
2044
 
2045
The options -trunk, -tags and -branch are mutually exclusive.
2046
 
2047
=back
2048
 
2049
=head2 DESCRIPTION
2050
 
2051
This command will create a new package within a repository. It will ensure
2052
that the package contains the three required subdirectories: trunk, tags and
2053
branches.
2054
 
2055
The command will also ensure that packages are not placed at inappropriate
2056
locations within the repository. It is not correct to place a package within
2057
another package.
2058
 
2059
The command will, optionally, import a directory tree into the repository and,
2060
optionally, label the package.
2061
 
2062
The package body may be imported to the 'trunk' or to a branch or a tag.
2063
By default the data will be imported to the trunk and may be labeled (tagged).
2064
 
2065
Options allow the targets to be deleted if they exist or to ensure that they
2066
are not present.
2067
 
2068
The command does not attempt to merge file versions within the repository. It
2069
may result in multiple instances of a file within the repository. Use only for
2070
simple imports. Use the 'import' command for more sophisticated import requirements.
2071
 
2429 dpurdie 2072
=head3 Examples
2073
 
2074
To create a package skeleton in the Perth MREF_Package repository for a package
2075
called 'VIXmyPackage':
2076
 
2077
    jats svn create-package AUPERASVN01/MREF_Package/VIXmyPackage
2078
 
2079
To create a package skeleton in the Perth MREF_Package repository, import code
2080
into the trunk of the package and label (tag) it:
2081
 
2082
    jats svn create-package \
2083
           AUPERASVN01/MREF_Package/VIXmyPackage \
2084
           -import=VIXmyNewPackage \
2085
           -label=VIXmyPackage.WIP
2086
 
311 dpurdie 2087
=head1 Delete a Package
2088
 
2089
=head2 NAME
2090
 
2091
Delete a Package
2092
 
2093
=head2 SYNOPSIS
2094
 
2095
jats svn delete-package URL [options]
2096
 
2097
 Options:
2098
    -help[=n]              - Help message, [n=1,2,3]
2099
    -man                   - Full documentation [-help=3]
2100
    -verbose[=n]           - Verbose command operation
2101
 
2102
=head2 ARGUMENTS
2103
 
2104
The command takes one argument: The URL of the desired package.
2105
This may be be:
2106
 
2107
=over
2108
 
2109
=item * A full URL
2110
 
2111
Complete with protocol and path information.
2112
 
2113
=item * A simple URL
2114
 
2115
JATS will prepend the site-specific repository location to the user provided URL
2116
 
2117
=back
2118
 
2119
=head2 OPTIONS
2120
 
2121
This command has no significant options, other than the general help options.
2122
 
2123
=head2 DESCRIPTION
2124
 
2125
This command will delete a package from the repository. It will ensure
2126
that the package is a valid package, before it is deleted.
2127
 
2128
The command is intended to be used by test scripts, rather than users.
2129
 
2049 dpurdie 2130
=head1 Create Branch
385 dpurdie 2131
 
2132
=head2 NAME
2133
 
2049 dpurdie 2134
Create a Workspace Branch
385 dpurdie 2135
 
2136
=head2 SYNOPSIS
2137
 
2049 dpurdie 2138
jats svn branch branch-name [options]
385 dpurdie 2139
 
2140
 Options:
2141
    -help[=n]              - Help message, [n=1,2,3]
2142
    -man                   - Full documentation [-help=3]
2143
    -verbose[=n]           - Verbose command operation
2144
    -path=path             - Target workspace
2049 dpurdie 2145
    -[no]switch            - Switch to new branch(default)
2146
    -comment=text          - Comment to apply to the new branch
385 dpurdie 2147
 
2148
=head2 ARGUMENTS
2149
 
2049 dpurdie 2150
The command takes one argument. The name of the branch to be created.
385 dpurdie 2151
 
2152
=head2 OPTIONS
2153
 
2154
=over
2155
 
2156
=item B<-path=path>
2157
 
2158
This options specifies the path of the target workspace. If not provided the
2159
command will use the current directory.
2160
 
2049 dpurdie 2161
=item B<-[no]switch>
2162
 
2163
If enabled (the default) the workspace will be switched to the new branch at
2164
the end of the process.
2165
 
2166
=item B<-comment=text>
2167
 
2168
If present, the specified text will be used as a Subversion comment when the
2169
branch is created.
2170
 
2171
If not provided, then JATS will provide a basic comment.
2172
 
385 dpurdie 2173
=back
2174
 
2175
=head2 DESCRIPTION
2176
 
2049 dpurdie 2177
This command will create a named branch associated with the workspace in the
2178
specified path. It is intended to simplify the creation of Private or
385 dpurdie 2179
Development branches.
2180
 
2049 dpurdie 2181
If the named branch already exists, then the command will fail.
385 dpurdie 2182
 
2049 dpurdie 2183
The command performs a server-side copy. It will not commit any locally
2184
modified files. Nor will it inform you if there are any.
311 dpurdie 2185
 
2049 dpurdie 2186
By default, the user is 'switched' to the newly created branch.
2187
 
2188
=head1 Switch Branch
2189
 
311 dpurdie 2190
=head2 NAME
2191
 
2049 dpurdie 2192
Switch a Workspace Branch
311 dpurdie 2193
 
2194
=head2 SYNOPSIS
2195
 
2049 dpurdie 2196
jats svn switch [branch-name] [options]
311 dpurdie 2197
 
2198
 Options:
2049 dpurdie 2199
    -help[=n]              - Help message, [n=1,2,3]
2200
    -man                   - Full documentation [-help=3]
2201
    -verbose[=n]           - Verbose command operation
2202
    -path=path             - Target workspace
311 dpurdie 2203
 
2204
=head2 ARGUMENTS
2205
 
2049 dpurdie 2206
The command takes one optional argument. The name of the target branch.
311 dpurdie 2207
 
2049 dpurdie 2208
=head2 OPTIONS
2209
 
311 dpurdie 2210
=over
2211
 
2049 dpurdie 2212
=item B<-path=path>
311 dpurdie 2213
 
2049 dpurdie 2214
This options specifies the path of the target workspace. If not provided the
2215
command will use the current directory.
311 dpurdie 2216
 
2049 dpurdie 2217
=back
311 dpurdie 2218
 
2049 dpurdie 2219
=head2 DESCRIPTION
311 dpurdie 2220
 
2049 dpurdie 2221
This command will switch the users workspace to the named branch. This is
2222
identical to the Subversion switch command, except it is easier to user and
2223
has several validity checks and other enhancements.
311 dpurdie 2224
 
2049 dpurdie 2225
The command has two modes of operation:
311 dpurdie 2226
 
2049 dpurdie 2227
=over 4
311 dpurdie 2228
 
2049 dpurdie 2229
=item   1. Display a list of branched in the current package.
311 dpurdie 2230
 
2049 dpurdie 2231
If no branch is specified, then the utility will display a list of branches in
2232
the packages 'branches' directory.
311 dpurdie 2233
 
2049 dpurdie 2234
=item   2. Switch to the named branch.
311 dpurdie 2235
 
2049 dpurdie 2236
The named branch must exists otherwise the command will fail.
311 dpurdie 2237
 
2429 dpurdie 2238
There are two special variants of the branch name:
311 dpurdie 2239
 
2049 dpurdie 2240
=over 4
311 dpurdie 2241
 
2049 dpurdie 2242
=item trunk
311 dpurdie 2243
 
2049 dpurdie 2244
If the branch is named 'trunk' then it will refer to the packages truck
1403 dpurdie 2245
 
2049 dpurdie 2246
=item tags
1403 dpurdie 2247
 
2049 dpurdie 2248
If the branch name starts with 'tags/', then the command will refer to
2249
a tag within the package and not a branch.
1403 dpurdie 2250
 
2049 dpurdie 2251
=back
1403 dpurdie 2252
 
2049 dpurdie 2253
The command will add and remove unmodified files from the workspace during this
2254
operation.
311 dpurdie 2255
 
2049 dpurdie 2256
=back
311 dpurdie 2257
 
2049 dpurdie 2258
=head3 Examples
311 dpurdie 2259
 
2049 dpurdie 2260
To switch to the packages trunk
311 dpurdie 2261
 
2049 dpurdie 2262
    jats svn switch trunk
311 dpurdie 2263
 
2049 dpurdie 2264
To switch to the a branch called MyBranch
311 dpurdie 2265
 
2049 dpurdie 2266
    jats svn switch MyBranch
311 dpurdie 2267
 
2049 dpurdie 2268
To switch to a tagged version of the package
311 dpurdie 2269
 
2049 dpurdie 2270
    jats svn switch tags/MyPackage_1.0.0000.cr
311 dpurdie 2271
 
2049 dpurdie 2272
To display a list of available branches (not tags)
311 dpurdie 2273
 
2049 dpurdie 2274
    jats svn switch
311 dpurdie 2275
 
2049 dpurdie 2276
=head1 Delete Branch
311 dpurdie 2277
 
2049 dpurdie 2278
=head2 NAME
311 dpurdie 2279
 
2049 dpurdie 2280
Delete the Workspace Branch
311 dpurdie 2281
 
2049 dpurdie 2282
=head2 SYNOPSIS
311 dpurdie 2283
 
2429 dpurdie 2284
jats svn delete-branch [options] [branch-list]
311 dpurdie 2285
 
2049 dpurdie 2286
 Options:
2287
    -help[=n]              - Help message, [n=1,2,3]
2288
    -man                   - Full documentation [-help=3]
2289
    -verbose[=n]           - Verbose command operation
2290
    -path=path             - Target workspace
311 dpurdie 2291
 
2049 dpurdie 2292
=head2 ARGUMENTS
2293
 
2429 dpurdie 2294
The command may take zero or more arguments. If provided the arguments will be
2295
branch names to be deleted.
2049 dpurdie 2296
 
2297
=head2 OPTIONS
2298
 
2299
=over
2300
 
2301
=item B<-path=path>
2302
 
2303
This options specifies the path of the target workspace. If not provided the
2304
command will use the current directory.
2305
 
2306
=back
2307
 
2308
=head2 DESCRIPTION
2309
 
2429 dpurdie 2310
This command can display the branch associated with the workspace or it can
2311
delete one or more branches. It is intended to simplify the deletion of Private
2312
or Development branches.
2049 dpurdie 2313
 
2429 dpurdie 2314
=over 4
2315
 
2316
=item 1 Arguments are provided
2317
 
2318
The command will delete all the named branches. If a named branch does not exist
2319
then the command will issue a warning message.
2320
 
2321
=item 2 No arguments provided
2322
 
2323
The command will display the branch associated with the workspace
2324
 
2049 dpurdie 2325
If the workspace is not linked to a 'branch' then the command will fail.
2326
 
2429 dpurdie 2327
=back
2328
 
311 dpurdie 2329
=head1 Import directory to a Package
2330
 
2331
=head2 NAME
2332
 
2333
Import directory to a Package
2334
 
2335
=head2 SYNOPSIS
2336
 
2337
jats svn [options] import URL [command options]
2338
 
2339
 Options:
2340
    -help[=n]               - Help message, [n=1,2,3]
2341
    -man                    - Full documentation [-help=3]
2342
    -verbose[=n]            - Verbose command operation
2343
 
2344
 Command Options
2345
    -help[=n]               - Command specific help, [n=1,2,3]
2346
    -verbose[=n]            - Verbose operation
2347
    -package=name           - Name of source package
2348
    -dir=path               - Path to new version
379 dpurdie 2349
    -label=label            - Label the result
2350
    -branch=branchName      - Base import on a branch
311 dpurdie 2351
    -replace                - Allow the label to be replaced
2352
    -reuse                  - Reuse the import directory
2353
    -workspace=path         - Path and name of alternate workspace
2354
    -[no]delete             - Deletes workspace after use. Default:yes
379 dpurdie 2355
    -author=name            - Force author of changes
2356
    -date=dateString        - Force date of changes
2357
    -log=text               - Append text to the commit message
2358
    -datafile=path          - Export tag data for automation
2931 dpurdie 2359
    -[no]commit             - Prevent changes being committed. Default:Yes
2429 dpurdie 2360
    -printfiles=n           - Control commit verbosity
2931 dpurdie 2361
    -mergePaths=dirList     - Comma separated list of directories to merge
311 dpurdie 2362
 
2363
=head2 ARGUMENTS
2364
 
2365
The command takes one argument: The URL of the desired package.
2366
This may be be:
2367
 
2368
=over
2369
 
2370
=item * A full URL
2371
 
2372
Complete with protocol and path information.
2373
 
2374
=item * A simple URL
2375
 
2376
JATS will prepend the site-specific repository location to the user provided URL
2377
 
2378
=back
2379
 
2380
=head2 OPTIONS
2381
 
2382
=over
2383
 
2384
=item -help[=n]
2385
 
2386
Print a help message and exit. The level of help may be either 1, 2 or 3.
2387
 
2388
This option may be specified multiple times to increment the help level, or
2389
the help level may be directly specified as a number.
2390
 
2391
=item -verbose[=n]
2392
 
2393
This option will increase the level of verbosity of the utility.
2394
 
2395
If an argument is provided, then it will be used to set the level, otherwise the
2396
existing level will be incremented. This option may be specified multiple times.
2397
 
2398
=item -package=name
2399
 
2400
Either this option or a bare URL on the command line must be provided. It
2401
specifies the repository and package to be used as a basis for the work.
2402
 
2403
=item -dir=path
2404
 
2405
This option is mandatory. It specifies the path to a local directory that
2406
contains a version of the software to be checked in.
2407
 
2408
=item -label=name
2409
 
2410
The resulting software version will be labeled with this tag, if it is provided.
2411
 
383 dpurdie 2412
A label name of TIMESTAMP will be treated in special manner. The name will be
2413
replaced with a unique name based on the users name and the current date time.
2414
 
379 dpurdie 2415
=item -branch=branchName
2416
 
2417
This option will cause the importation to be referenced to the named branch.
2418
If the branch does not exist it will be created. If it does exist then it will
2419
be used.
2420
 
2421
If this option is not specified, then the importation will be based on the 'trunk'.
2422
 
2423
If the Workspace is provided, then it will be used independently of this option.
2424
 
383 dpurdie 2425
A branchName of TIMESTAMP will be treated in special manner. The name will be
2426
replaced with a unique name based on the users name and the current date time.
2427
 
311 dpurdie 2428
=item -replace
2429
 
2430
This option, if provided, allows the label to be replaced.
2431
 
2432
=item -reuse
2433
 
2434
This option can be used to speed the creation of multiple versions in a scripted
2435
environment. The option allows the utility to reuse the workspace if it exists.
2436
 
2437
=item -workspace=path
2438
 
2439
This option specifies an alternate workspace directory to create and use. The
2440
default directory is "SvnImportDir" within the users current directory.
2441
 
2442
=item [no]delete
2443
 
341 dpurdie 2444
This option control the deletion of the workspace directory. By default the
311 dpurdie 2445
directory will be deleted, unless re-use is also used.
2446
 
379 dpurdie 2447
=item -author=name
2448
 
2449
This option will force the author of changes as recorded in the repository.
385 dpurdie 2450
The repository must be configured to allow such changes.
379 dpurdie 2451
 
2452
This option may not work for non-admin users.
2453
 
2454
=item -date=dateString
2455
 
2456
This option will force the date of the changes as recorded in the repository.
385 dpurdie 2457
The repository must be configured to allow such changes.
379 dpurdie 2458
The dateString is in a restricted ISO 8601 format: ie 2009-02-12T00:44:04.921324Z
2459
 
2460
This option may not work for non-admin users.
2461
 
2462
=item -log=text
2463
 
2464
This option will append the specified text to the commit message.
2465
The first line of the commit message is fixed by the import tool.
2466
 
2467
=item -datafile=path
2468
 
2469
This option will cause the utility to create a data file to record the import
2470
tag. It is used for automation of the import process.
2471
 
2429 dpurdie 2472
=item -[no]commit
2473
 
2474
This option will prevent the final workspace from being committed to the
2475
Repository. This allows inspection of the results.
2476
 
2477
The default operation is to commit and label the results of the import.
2478
 
2479
=item -printfiles=n
2480
 
2481
This option controls commit verbosity. The default operation is to display
2482
the files added and removed during the commit.
2483
 
2484
Suitable numbers are: None, 0 (No Display) and 1 (Full Display).
2485
 
2764 dpurdie 2486
=item -mergePaths=dirList
2487
 
2931 dpurdie 2488
This option specifies a Comma separated list of directories to be merged
3967 dpurdie 2489
during the import process. This works via the following mechanism:
2764 dpurdie 2490
 
2491
If the named directory exists in the 'new' image it will replace that in the
2492
'initial' workspace.
2493
 
2494
If the named directory does not exist in the 'new' image, but does exist in the
2495
'initial' image then it will be retained in the 'final' image.
2496
 
2497
Directories other than those named will not be imported.
2498
 
311 dpurdie 2499
=back
2500
 
2501
=head2 DESCRIPTION
2502
 
2503
Import a new version of a package to the trunk of the package. The utility
2504
will only import changed files so that file history is preserved within the
2505
repository.
2506
 
2507
This utility is used import software from another version control system
2508
The utility will:
2509
 
2510
=over
2511
 
361 dpurdie 2512
=item *
311 dpurdie 2513
 
361 dpurdie 2514
Create a Work Space based on the current package version
2515
 
379 dpurdie 2516
The 'trunk' of the named package will be used as the base for the workspace,
2517
unless modified with the -branch option.
311 dpurdie 2518
 
361 dpurdie 2519
=item *
311 dpurdie 2520
 
361 dpurdie 2521
Update files and directories
2522
 
311 dpurdie 2523
Determines the files and directories that have been added and deleted and
2524
update the Workspace to reflect the new structure.
2525
 
361 dpurdie 2526
=item *
311 dpurdie 2527
 
361 dpurdie 2528
Check in the new version
311 dpurdie 2529
 
361 dpurdie 2530
=item *
2531
 
2532
Label the new version
2533
 
311 dpurdie 2534
=back
2535
 
7217 dpurdie 2536
=head1 Sync Merge
2537
 
2538
=head2 NAME
2539
 
2540
Perform a Feature Branch Sync Merge
2541
 
2542
=head2 SYNOPSIS
2543
 
2544
jats svn merge [options]
2545
 
2546
 Options:
2547
    -help[=n]              - Help message, [n=1,2,3]
2548
    -man                   - Full documentation [-help=3]
2549
    -verbose[=n]           - Verbose command operation
2550
    -info                  - Displays merge info only
2551
    -dry-run               - Perform a dry run of the merge
2552
    -path=path             - Target workspace
2553
    ...                    - Other options are passed to the merge
2554
 
2555
=head2 ARGUMENTS
2556
 
2557
The command takes no arguments, just options.
2558
 
2559
=head2 OPTIONS
2560
 
2561
=over
2562
 
2563
=item B<-path=path>
2564
 
2565
This options specifies the path of the target workspace. If not provided the
2566
command will use the current directory.
2567
 
2568
=item B<-info>
2569
 
2570
This option will display information about the proposed merge, but it will not do the merge.
2571
This is not the same as a '-dry-run' as it shows information that the command has recovered from
2572
the workspace.
2573
 
2574
=item B<-dry-run>
2575
 
2576
This option will perform a dry run of the actual merge. It will not modify the workspace.
2577
 
2578
=item B<...>
2579
 
2580
Options that are not processed by this command will be passed through to the underlying
2581
'svn merge' command. Available options include:
2582
 
2583
=over 8
2584
 
2585
=item * --accept=mf (mine-full)
2586
 
2587
=item * --accept=mc (mine-conflict)
2588
 
2589
=back
2590
 
2591
=back
2592
 
2593
=head2 DESCRIPTION
2594
 
2595
This command implements the common operation of merging the release branch 
2596
head (normally trunk) onto a private development branch in the current working copy. 
2597
 
2598
The main goal of this command is to avoid situations where developers accidentally merge 
2599
from the wrong branch, or end up with (to them) inexplicable merge failures and thus 
2600
lose confidence in Subversion. 
2601
 
2602
It will fail if the current working copy is actually on the trunk, and not a branch.
2603
 
2604
=head1 Reintegrate Merge
2605
 
2606
=head2 NAME
2607
 
2608
Reintegrate a Feature Branch
2609
 
2610
=head2 SYNOPSIS
2611
 
2612
jats svn reintegrate [options]
2613
 
2614
 Options:
2615
    -help[=n]              - Help message, [n=1,2,3]
2616
    -man                   - Full documentation [-help=3]
2617
    -verbose[=n]           - Verbose command operation
2618
    -path=path             - Target workspace
2619
    -info                  - Displays merge info only
2620
    -dry-run               - Perform a dry run of the merge
2621
    -reintegrate           - Option to ensure user is aware of the action
2622
    ...                    - Other options are passed to the merge
2623
 
2624
=head2 ARGUMENTS
2625
 
2626
The command takes no arguments, just options.
2627
 
2628
=head2 OPTIONS
2629
 
2630
=over
2631
 
2632
=item B<-path=path>
2633
 
2634
This options specifies the path of the target workspace. If not provided the
2635
command will use the current directory.
2636
 
2637
=item B<-info>
2638
 
2639
This option will display information about the proposed merge, but it will not do the merge.
2640
This is not the same as a '--dry-run' as it shows information that the command has recovered from
2641
the workspace.
2642
 
2643
=item B<-dry-run>
2644
 
2645
This option will perform a dry run of the actual merge. It will NOT deleted the feature branch. It will
2646
switch the workspace and after the dry run of the merge it will switch it back.
2647
 
2648
This option implies '-reintegrate'.
2649
 
2650
=item B<-reintegrate>
2651
 
2652
This option will cause the utility to perform the merge. Without it the utility will provide
2653
some sanity checking, but will not switch the workspace nor delete the feature branch.
2654
 
2655
By using this option the user acknowledges that the are aware of the changes that will be made.
2656
 
2657
=item B<...>
2658
 
2659
Options that are not processed by this command will be passed through to the underlying
2660
'svn merge' command. Available options include:
2661
 
2662
=over 8
2663
 
2664
=item * --accept=mf (mine-full)
2665
 
2666
=item * --accept=mc (mine-conflict)
2667
 
2668
=back
2669
 
2670
=head2 DESCRIPTION
2671
 
2672
This command implements the common operation of merging a private branch back into the main
2673
development branch (normally the trunk).
2674
 
2675
The main goal of this command is to avoid situations where developers accidentally merge 
2676
from the wrong branch, or end up with (to them) inexplicable merge failures and thus 
2677
lose confidence in Subversion. 
2678
 
2679
It will fail if the current working copy is actually on the trunk, and not a branch
2680
 
2681
The command will do the following operations:
2682
 
2683
=over 8
2684
 
2685
=item * 
2686
 
2687
Ensure that the path address a subversion workspace and that the user is not in a sundirectory
2688
of the workspace.
2689
 
2690
=item * 
2691
 
2692
Ensure the workspace is a branch. This command assumes that the workspace contains the feature branch.
2693
 
2694
=item * 
2695
 
2696
Ensure the workspace contains no modified files
2697
 
2698
=item * 
2699
 
2700
Switch to the branches parent, which may not be the trunk.
2701
 
2702
=item * 
2703
 
2704
Perform the reintegration merge
2705
 
2706
=item * 
2707
 
2708
Delete the branch, in subversion. Once an reintegration merge has been performed the branch 
2709
can no longer be used. It's not able to correctly absorb new trunk changes, nor can it be properly 
2710
reintegrated to trunk again. The user may create another branch with the same name, if required.
2711
 
2712
=back
2713
 
2714
At the end of the reintegration merge the workspace will be associated with the parent of the branch, which may be called 'trunk'.
2715
The workspace will contain modified files. It is up to the user to verify that the merge has had the desired result and to commit the
2716
changes. It is not recommended that development occur in the workspace. A new branch should be created for further development.
2717
 
311 dpurdie 2718
=cut
2719