Subversion Repositories DevTools

Rev

Rev 7217 | 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
#
7236 dpurdie 1481
# Description     : Simulate an svn merge --reintegrate (which is now deprecated)
1482
#                       - Assume the user has the 'trunk' in a workspace
1483
#                       - Ensure there are no uncommitted files
1484
#                       - Ensure it is upto date with thr REpo server
7217 dpurdie 1485
#                       - with much sanity checking
7236 dpurdie 1486
#                       - verify the named branch
1487
#                       - Ensure the named branch is derived from the workspace
1488
#                       - perform a simple merge
7217 dpurdie 1489
#
1490
# Inputs          : None
1491
#
1492
# Returns         : 
1493
#
1494
sub SvnReintegrate
1495
{
1496
    my $opt_path = '.';
1497
    my $opt_info;
1498
    my @mergeOpts;
1499
    my $opt_reintegrate;
1500
    my $opt_dryRun;
7236 dpurdie 1501
    my $opt_branch;
7217 dpurdie 1502
 
1503
    #
1504
    #   Parse more options
1505
    #
1506
    Getopt::Long::Configure('pass_through');
1507
    GetOptions (
1508
                "help:+"        => \$opt_help,
1509
                "manual:3"      => \$opt_help,
1510
                "path:s"        => \$opt_path,
1511
                'info'          => \$opt_info,
1512
                'reintegrate!'  => \$opt_reintegrate,
1513
                'dry-run'       => \$opt_dryRun,
7236 dpurdie 1514
                'branch:s'      => \$opt_branch,
7217 dpurdie 1515
                ) || Error ("Invalid command line" );
1516
 
1517
    #
1518
    #   Subcommand specific help
1519
    #
1520
    SubCommandHelp( $opt_help, "Reintegrate Merge") if ($opt_help);
1521
 
1522
    #
1523
    #   Save merge options
7236 dpurdie 1524
    #   Extract the named branch ( if not provided via the -branch ) option
7217 dpurdie 1525
    #
1526
    foreach (@ARGV) {
1527
        if (m~^-~) {
1528
            push @mergeOpts, $_;
1529
        } else {
7236 dpurdie 1530
            Error ("Source branh for the merge must only be specified once") if (defined($opt_branch));
1531
            $opt_branch = $_;
7217 dpurdie 1532
        }
1533
    }
1534
 
7236 dpurdie 1535
    Error("No branch specified") unless defined $opt_branch;
1536
    Error("Branch name looks bad") unless ($opt_branch =~ m~[-/a-zA-Z0-9]~i);
1537
 
7217 dpurdie 1538
    #
7236 dpurdie 1539
    #   We intercepted the dry-run option,
7217 dpurdie 1540
    #   Put the option back into the stream.
1541
    if ($opt_dryRun) {
1542
        push @mergeOpts, '--dry-run';
1543
    }
1544
 
7236 dpurdie 1545
    #
1546
    #   Calculate the target name
1547
    #       trunk is special
1548
    #       tags/... is special
1549
    if ( $opt_branch eq 'trunk' ) {
1550
    } elsif ( $opt_branch =~ m~tags/.+~ ) {
1551
    } else {
1552
        $opt_branch = join ('/', 'branches', $opt_branch);
1553
    }
1554
 
1555
    #
7217 dpurdie 1556
    #   Check we are in a workspace
1557
    #   Create an SVN session
7236 dpurdie 1558
    #
7217 dpurdie 1559
    my $uref = NewSessionByWS($opt_path, 0, 1);
7236 dpurdie 1560
    $uref->{WSURL} =~ m~[^/](/.*)~;
1561
    $uref->{target} = $1;
7217 dpurdie 1562
 
1563
    #
1564
    #   Warn user if the command is being executed from within a subdirectory of the workspace
1565
    #   It might work, but if the directory is deleted it will go badly
1566
    #
1567
    my $ws_root = mustBeWsRoot($uref);
7236 dpurdie 1568
#DebugDumpData("uref", $uref);
7217 dpurdie 1569
 
1570
    #
7236 dpurdie 1571
    #   Validate the branch the user has specified - it must exist
1572
    #
1573
    my $ws_url = $uref->Full();
1574
    my $branch_tag = join ('/', $ws_url, $opt_branch);
1575
    $uref->SvnValidateTarget (
1576
                        'cmd'    => 'svn reintegrate',
1577
                        'target' => $branch_tag,
1578
                        'require' => 1,
1579
                        );
7217 dpurdie 1580
 
7236 dpurdie 1581
    #
1582
    #   Verify the source of the merge
1583
    #   Need to get data about the branch, not the current workspace
1584
    #
1585
    my $branchRef = NewSessionByUrl($branch_tag);
1586
    $branchRef->getWsExtraInfo();
1587
    my $branchLogInfo = $branchRef->{InfoWsExtra};
1588
#DebugDumpData("getWsExtraInfo", $branchLogInfo);
1589
 
7217 dpurdie 1590
    # A bit of sanity testing
7236 dpurdie 1591
    Error("Branch does not appear to be a branch") unless (exists $branchLogInfo->{'copyfrom-path'}); 
1592
    Error("Branch does not appear to be a branch") unless (exists $branchLogInfo->{'target'}); 
1593
    Warning("Branch is a trunk") if ($branchLogInfo->{'target'} =~ m~/trunk$~);
1594
    Error("Branch is a raw branch") if ($branchLogInfo->{'target'} =~ m~/branches$~);
1595
    Error("Branch is a raw tag") if ($branchLogInfo->{'target'} =~ m~/tags$~);
1596
    Warning("Branch is a within a tag") if ($branchLogInfo->{'target'} =~ m~/tags/~);
1597
    Error ("Merging to myself") if ($uref->{target} eq $branchLogInfo->{'target'});
1598
    Error ("Branch not taken from this trunk", "Workspace: $uref->{'target'}","Branch: $branchLogInfo->{'copyfrom-path'}") unless ($uref->{'target'} eq $branchLogInfo->{'copyfrom-path'});
7217 dpurdie 1599
 
7236 dpurdie 1600
    Message ("Reintegrate Info - No merge performed") if ($opt_info );
7217 dpurdie 1601
    Message ("RepoRoot: " . $uref->{InfoWs}{'Repository Root'});
7236 dpurdie 1602
    Message ("Source Branch: " . $branchLogInfo->{'target'});
1603
    Message ("Workspace Branch: " . $uref->{'target'} );
1604
    Message ("Reintegrate from $branchLogInfo->{'target'} to $uref->{'target'}");
7217 dpurdie 1605
 
1606
    #
1607
    #   Examine the workspace and ensure that there are no modified
1608
    #   files - unless they are expected
1609
    #   
1610
    #   Prevent the user from merging into a WS that has not been committed
1611
    #
1612
    $uref->SvnWsModified ( 'cmd' => 'Reintegrate' );
1613
 
7236 dpurdie 1614
    unless ($opt_info) {
7217 dpurdie 1615
 
1616
        #
7236 dpurdie 1617
        #   $branchLogInfo->{'target'} is the branch of the specified branch
1618
        #   $uref->{target} - should be the same
1619
        #   
1620
        #   use merge ^/<target> to merge the data into this workspace
7217 dpurdie 1621
        #
1622
        #   Perform an interactive command so that the user can accept conflicts - if they want
1623
        #
1624
        my $rv = SvnUserCmd( 'merge', '--reintegrate',
1625
                @mergeOpts,
7236 dpurdie 1626
                '^' . $branchLogInfo->{'target'},
7217 dpurdie 1627
                '.',
1628
                { 'credentials' => 1 });
1629
 
1630
    }
1631
    $opr_done = 1;
1632
}
1633
 
1634
#-------------------------------------------------------------------------------
1635
# Function        : mustBeWsRoot 
1636
#
1637
# Description     : Ensure that the user is not in a subdirectory of a workspace 
1638
#
1639
# Inputs          : $uref   - A Svn session handle
1640
#
1641
# Returns         : Will not return on error
1642
#                   Return the workspace root as provided by SvnLocateWsRoot
1643
#
1644
sub mustBeWsRoot
1645
{
1646
    my ($uref) = @_;
1647
 
1648
    my $ws_root = $uref->SvnLocateWsRoot(0);
1649
    my $pathToRoot = RelPath($ws_root);
1650
    if ( $pathToRoot =~ m~^..~) {
1651
        Error("This command cannot be executed within a subdirectory of the workspace",
1652
                "It can be executed in the root of the workspace: $pathToRoot",
1653
                "It can be executed externally with the -path option");
1654
    }
1655
 
1656
    return $ws_root;
1657
}
1658
 
1659
#-------------------------------------------------------------------------------
2049 dpurdie 1660
# Function        : ShowBranches
1661
#
1662
# Description     : Show branches in current workspace
1663
#                   Internal use only
1664
#
1665
# Inputs          : $opt_path           - Optional path
1666
#
1667
# Returns         :
1668
#
1669
sub ShowBranches
1670
{
1671
    my ($opt_path) = @_;
1672
 
1673
    my $uref = NewSessionByWS($opt_path, 0, 1);
1674
    my $ws_url = $uref->Full();
1675
 
1676
    #
2931 dpurdie 1677
    #   Display the packages full URL - allow the user to manually look at more
1678
    #   List the branches
2049 dpurdie 1679
    #
1680
    Message ("Url: $ws_url", 'Available Branches');
1681
    SvnUserCmd( 'ls', join ('/', $ws_url, 'branches'), { 'credentials' => 1 });
1682
    $opr_done = 1;
1683
}
1684
#-------------------------------------------------------------------------------
311 dpurdie 1685
# Function        : SubCommandHelp
1686
#
1687
# Description     : Provide help on a subcommand
1688
#
1689
# Inputs          : $help_level             - Help Level 1,2,3
1690
#                   $topic                  - Topic Name
1691
#
1692
# Returns         : This function does not return
1693
#
1694
sub SubCommandHelp
1695
{
1696
    my ($help_level, $topic) = @_;
1697
    my @sections;
1698
    #
1699
    #   Spell out the section we want to display
1700
    #
1701
    #   Note:
1702
    #   Due to bug in pod2usage can't use 'head1' by itself
1703
    #   Each one needs a subsection.
1704
    #
1705
    push @sections, qw( NAME SYNOPSIS ) ;
1706
    push @sections, qw( ARGUMENTS OPTIONS ) if ( $help_level > 1 );
1707
    push @sections, qw( DESCRIPTION )       if ( $help_level > 2 );
1708
 
1709
    #
1710
    #   Extract section from the POD
1711
    #
1712
    pod2usage({-verbose => 99,
1713
               -noperldoc => 1,
1714
               -sections => $topic . '/' . join('|', @sections) } );
1715
}
1716
 
1717
#-------------------------------------------------------------------------------
1718
#   Documentation
1719
#   NOTE
1720
#
1721
#   Each subcommand MUST have
1722
#   head1 section as used by the subcommand
1723
#       This should be empty, as the contents will NOT be displayed
1724
#   head2 sections called
1725
#       NAME SYNOPSIS ARGUMENTS OPTIONS DESCRIPTION
1726
#
1727
#=head1 xxxxxx
1728
#=head2 NAME
1729
#=head2 SYNOPSIS
1730
#=head2 ARGUMENTS
1731
#=head2 OPTIONS
1732
#=head2 DESCRIPTION
1733
#
1734
 
1735
=pod
1736
 
361 dpurdie 1737
=for htmltoc    GENERAL::Subversion::
1738
 
311 dpurdie 1739
=head1 NAME
1740
 
1741
jats svn - Miscellaneous SubVersion Operations
1742
 
1743
=head1 SYNOPSIS
1744
 
1745
jats svn [options] command [command options]
1746
 
1747
 Options:
1748
    -help[=n]              - Help message, [n=1,2,3]
1749
    -man                   - Full documentation [-help=3]
1750
    -verbose[=n]           - Verbose command operation
1751
 
1752
 Common Command Options:
1753
    All command support suboptions to provide command specific help
1754
 
1755
    -help[=n]              - Help message, [n=1,2,3]
1756
    -man                   - Full documentation [-help=3]
1757
 
1758
 Commands are:
363 dpurdie 1759
    test                   - Test access to subversion
369 dpurdie 1760
    paths                  - Display Subversion tag to URL conversions
311 dpurdie 1761
    ls URL                 - List Repo contents for URL
369 dpurdie 1762
    tag [URL]              - Convert URL or Path to a Release Manager Tag
1763
    url [TAG]              - Convert TAG or Path to a Subversion URL
2049 dpurdie 1764
    create-package URL     - Create a new package at URL
311 dpurdie 1765
    delete-package URL     - Delete Package Subtree
2049 dpurdie 1766
    branch BRANCH          - Create a Development Branch
1767
    switch [BRANCH]        - Switch to a Development Branch
385 dpurdie 1768
    delete-branch          - Delete a Development Branch
311 dpurdie 1769
    import URL             - Import files to package at URL
7217 dpurdie 1770
    merge                  - Merge head into a feature branch
1771
    reintegrate            - Integrate a feature branch to its head
311 dpurdie 1772
 
7217 dpurdie 1773
 
311 dpurdie 1774
 Use the command
1775
    jats svn command -h
1776
 for command specific help
1777
 
1778
=head1 OPTIONS
1779
 
1780
=over
1781
 
1782
=item B<-help[=n]>
1783
 
1784
Print a help message and exit. The level of help may be either 1, 2 or
1785
3 for a full manual.
1786
 
1787
This option may be specified multiple times to increment the help level, or
1788
the help level may be directly specified as a number.
1789
 
1790
=item B<-man>
1791
 
1792
This is the same as '-help=3'.
1793
The complete help is produced in a man page format.
1794
 
2429 dpurdie 1795
=item B<-verbose[=n]>
311 dpurdie 1796
 
1797
This option will increase the level of verbosity of the commands.
1798
 
1799
If an argument is provided, then it will be used to set the level, otherwise the
1800
existing level will be incremented. This option may be specified multiple times.
1801
 
1802
=back
1803
 
1804
=head1 DESCRIPTION
1805
 
1806
This program provides a number of useful Subversion based operations.
1807
 
363 dpurdie 1808
=head1 Test Subversion
1809
 
1810
=head2 NAME
1811
 
1812
Test Subversion
1813
 
1814
=head2 SYNOPSIS
1815
 
1816
    jats svn test
1817
 
1818
=head2 DESCRIPTION
1819
 
1820
This command will ensure that the subversion command line utility can be
1821
located. The command will report the version of the svn client found.
1822
 
369 dpurdie 1823
=head1 Subversion Paths
1824
 
1825
=head2 NAME
1826
 
1827
Subversion Paths
1828
 
1829
=head2 SYNOPSIS
1830
 
1831
    jats svn paths
1832
 
1833
=head2 DESCRIPTION
1834
 
1835
This command will display the base Tags and associated URLs that are used by
1836
JATS to convert a 'Subversion Tag' into a full URLs that will be used to access
1837
a physical repository.
1838
 
1839
The 'Tags' configuration is site-specific.
1840
 
311 dpurdie 1841
=head1 List Repository
1842
 
363 dpurdie 1843
=head2 NAME
1844
 
1845
List Repository
1846
 
1847
=head2 SYNOPSIS
1848
 
1849
    jats svn ls <URL>
1850
 
1851
=head2 DESCRIPTION
1852
 
311 dpurdie 1853
This command will take a URL and perform a 'svn' list operation. The URL will
1854
be expanded to include the site specific repository.
1855
 
369 dpurdie 1856
=head1 Url to Tag
1857
 
1858
=head2 NAME
1859
 
1860
Url to Tag
1861
 
1862
=head2 SYNOPSIS
1863
 
1864
    jats svn tag [Option] [tag]
1865
 
1866
 Options:
1867
    -help[=n]              - Help message, [n=1,2,3]
1868
    -man                   - Full documentation [-help=3]
1869
    -path=path             - Convert specified path
1870
    -url=url               - Convert specified URL
1871
 
1872
=head2 DESCRIPTION
1873
 
1874
This command will convert a URL or a PATH to a Subversion Tag that can
1875
be used within the remainder of the build system. If no PATH or URL is provided,
1876
then the command uses a path of the current directory.
1877
 
1878
The command will convert either a PATH or a URL. It will not do both.
1879
 
1880
The command will use the configured Subversion URL prefixes to create the Tag.
1881
 
1882
If a PATH is to be converted, then the PATH must address a Subversion workspace.
1883
The conversion will return a Tag to the root of the Workspace and Peg it to
1884
the last committed version. The command will not determine if the workspace
1885
contains modified files.
1886
 
1887
If a URL is to be converted, then the resultant value should be used with
1888
caution. The result is only as good as the provided URL and may not address
1889
the root of a package.
1890
 
1891
=head1 Tag to Url
1892
 
1893
=head2 NAME
1894
 
1895
Tag to Url
1896
 
1897
=head2 SYNOPSIS
1898
 
1899
    jats svn url [Option] [url]
1900
 
1901
 Options:
1902
    -help[=n]              - Help message, [n=1,2,3]
1903
    -man                   - Full documentation [-help=3]
1904
    -path=path             - Convert specified path
1905
    -url=url               - Convert specified URL
1906
 
1907
=head2 DESCRIPTION
1908
 
1909
This command will convert a TAG or a PATH to a full URL that can be used
1910
directly by Subversion. If no PATH or TAG is provided, then the command uses a
1911
path of the current directory.
1912
 
2429 dpurdie 1913
The command will convert either a TAG or a PATH. It will not do both.
369 dpurdie 1914
 
1915
The command will use the configured Subversion URL prefixes to expand the TAG.
1916
 
1917
If a PATH is to be converted, then the PATH must address a Subversion workspace.
1918
The conversion will return a URL to the root of the Workspace and Peg it to
1919
the last committed version. The command will not determine if the workspace
1920
contains modified files.
1921
 
1922
If a TAG is to be converted, then the resultant value should be used with
1923
caution. The result is only as good as the provided URL and may not address
1924
the root of a package.
1925
 
2429 dpurdie 1926
=head3 Examples
1927
 
1928
To display the URL of the current workspace
1929
 
1930
    jats svn url
1931
 
1932
To display the URL of a known workspace
1933
 
1934
    jats svn url -path=myWorkSpace
1935
 
1936
To convert a TAG from Release Manager or other JATS commands
1937
 
1938
    jats svn url AUPERASVN01/COTS
1939
    jats svn url SVN::AUPERASVN01/COTS/bouncycastle/trunk::bouncycastle_1.3.1.cots@502
1940
 
2049 dpurdie 1941
=head1 Create a Package Version
1942
 
1943
=head2 NAME
1944
 
1945
Create a Package Version
1946
 
1947
=head2 SYNOPSIS
1948
 
1949
jats svn [options] create-package URL [command options]
1950
 
1951
 Options:
1952
    -help[=n]               - Help message, [n=1,2,3]
1953
    -man                    - Full documentation [-help=3]
1954
    -verbose[=n]            - Verbose command operation
1955
 
1956
 Command Options
1957
    -help[=n]               - Provide command specific help
1958
    -new                    - Package must not exist
1959
    -replace                - Replace any existing versions
2429 dpurdie 1960
    -import=path            - Import directory tree
2049 dpurdie 1961
    -label=nnn              - Label imported package
1962
    -trunk                  - Import to trunk (default)
1963
    -tags=nnn               - Import to tags
1964
    -branch=nnn             - Import to branches
1965
 
1966
=head2 ARGUMENTS
1967
 
1968
The command takes one argument: The URL of the desired package.
1969
This may be be:
1970
 
1971
=over
1972
 
1973
=item * A full URL
1974
 
1975
Complete with protocol and path information.
1976
 
1977
=item * A simple URL
1978
 
1979
JATS will prepend the site-specific repository location to the user provided URL
1980
 
1981
=back
1982
 
1983
=head2 OPTIONS
1984
 
1985
=over
1986
 
1987
=item -help[=n]
1988
 
1989
Print a help message and exit. The level of help may be either 1, 2 or 3.
1990
 
1991
This option may be specified multiple times to increment the help level, or
1992
the help level may be directly specified as a number.
1993
 
1994
=item -new
1995
 
1996
This option specifies that the named package MUST not exist at all.
1997
 
1998
=item -replace
1999
 
2000
This option allows the program to replace any existing versions of the
2001
imported source. It will allow the deletion of any existing trunk, tags or
2002
branches.
2003
 
2429 dpurdie 2004
=item -import=path
2049 dpurdie 2005
 
2006
This option specifies the path of a subdirectory tree to import into the newly
2007
created package. In not provided, then only a package skeleton will be created.
2008
 
2429 dpurdie 2009
All files and directories below, but not including, the named path will be
2010
imported into the package.
2011
 
4096 dpurdie 2012
The imported directory tree will be scanned to ensure that the following subdirectories
2013
do not exist: .svn, .hg, .git, .cvs, tags, trunk and branches. These directories are
2014
either reserved or indicative that the import tree is already version controlled.
2015
 
2049 dpurdie 2016
=item -label=nnn
2017
 
2018
This option specifies a label to place the imported source.
2019
 
2020
=item -trunk
2021
 
2022
This option specifies that imported source will be placed on the trunk of the
2023
package. This is the default mode of import.
2024
 
2025
The options -trunk, -tags and -branch are mutually exclusive.
2026
 
2027
=item -tags=nnn
2028
 
2029
This option specifies that imported source will be placed directly on the
2030
named tag of the package.
2031
 
2032
The options -trunk, -tags and -branch are mutually exclusive.
2033
 
2034
=item -branch=nnn
2035
 
2036
This option specifies that imported source will be placed directly on the
2037
named branch of the package.
2038
 
2039
The options -trunk, -tags and -branch are mutually exclusive.
2040
 
2041
=back
2042
 
2043
=head2 DESCRIPTION
2044
 
2045
This command will create a new package within a repository. It will ensure
2046
that the package contains the three required subdirectories: trunk, tags and
2047
branches.
2048
 
2049
The command will also ensure that packages are not placed at inappropriate
2050
locations within the repository. It is not correct to place a package within
2051
another package.
2052
 
2053
The command will, optionally, import a directory tree into the repository and,
2054
optionally, label the package.
2055
 
2056
The package body may be imported to the 'trunk' or to a branch or a tag.
2057
By default the data will be imported to the trunk and may be labeled (tagged).
2058
 
2059
Options allow the targets to be deleted if they exist or to ensure that they
2060
are not present.
2061
 
2062
The command does not attempt to merge file versions within the repository. It
2063
may result in multiple instances of a file within the repository. Use only for
2064
simple imports. Use the 'import' command for more sophisticated import requirements.
2065
 
2429 dpurdie 2066
=head3 Examples
2067
 
2068
To create a package skeleton in the Perth MREF_Package repository for a package
2069
called 'VIXmyPackage':
2070
 
2071
    jats svn create-package AUPERASVN01/MREF_Package/VIXmyPackage
2072
 
2073
To create a package skeleton in the Perth MREF_Package repository, import code
2074
into the trunk of the package and label (tag) it:
2075
 
2076
    jats svn create-package \
2077
           AUPERASVN01/MREF_Package/VIXmyPackage \
2078
           -import=VIXmyNewPackage \
2079
           -label=VIXmyPackage.WIP
2080
 
311 dpurdie 2081
=head1 Delete a Package
2082
 
2083
=head2 NAME
2084
 
2085
Delete a Package
2086
 
2087
=head2 SYNOPSIS
2088
 
2089
jats svn delete-package URL [options]
2090
 
2091
 Options:
2092
    -help[=n]              - Help message, [n=1,2,3]
2093
    -man                   - Full documentation [-help=3]
2094
    -verbose[=n]           - Verbose command operation
2095
 
2096
=head2 ARGUMENTS
2097
 
2098
The command takes one argument: The URL of the desired package.
2099
This may be be:
2100
 
2101
=over
2102
 
2103
=item * A full URL
2104
 
2105
Complete with protocol and path information.
2106
 
2107
=item * A simple URL
2108
 
2109
JATS will prepend the site-specific repository location to the user provided URL
2110
 
2111
=back
2112
 
2113
=head2 OPTIONS
2114
 
2115
This command has no significant options, other than the general help options.
2116
 
2117
=head2 DESCRIPTION
2118
 
2119
This command will delete a package from the repository. It will ensure
2120
that the package is a valid package, before it is deleted.
2121
 
2122
The command is intended to be used by test scripts, rather than users.
2123
 
2049 dpurdie 2124
=head1 Create Branch
385 dpurdie 2125
 
2126
=head2 NAME
2127
 
2049 dpurdie 2128
Create a Workspace Branch
385 dpurdie 2129
 
2130
=head2 SYNOPSIS
2131
 
2049 dpurdie 2132
jats svn branch branch-name [options]
385 dpurdie 2133
 
2134
 Options:
2135
    -help[=n]              - Help message, [n=1,2,3]
2136
    -man                   - Full documentation [-help=3]
2137
    -verbose[=n]           - Verbose command operation
2138
    -path=path             - Target workspace
2049 dpurdie 2139
    -[no]switch            - Switch to new branch(default)
2140
    -comment=text          - Comment to apply to the new branch
385 dpurdie 2141
 
2142
=head2 ARGUMENTS
2143
 
2049 dpurdie 2144
The command takes one argument. The name of the branch to be created.
385 dpurdie 2145
 
2146
=head2 OPTIONS
2147
 
2148
=over
2149
 
2150
=item B<-path=path>
2151
 
2152
This options specifies the path of the target workspace. If not provided the
2153
command will use the current directory.
2154
 
2049 dpurdie 2155
=item B<-[no]switch>
2156
 
2157
If enabled (the default) the workspace will be switched to the new branch at
2158
the end of the process.
2159
 
2160
=item B<-comment=text>
2161
 
2162
If present, the specified text will be used as a Subversion comment when the
2163
branch is created.
2164
 
2165
If not provided, then JATS will provide a basic comment.
2166
 
385 dpurdie 2167
=back
2168
 
2169
=head2 DESCRIPTION
2170
 
2049 dpurdie 2171
This command will create a named branch associated with the workspace in the
2172
specified path. It is intended to simplify the creation of Private or
385 dpurdie 2173
Development branches.
2174
 
2049 dpurdie 2175
If the named branch already exists, then the command will fail.
385 dpurdie 2176
 
2049 dpurdie 2177
The command performs a server-side copy. It will not commit any locally
2178
modified files. Nor will it inform you if there are any.
311 dpurdie 2179
 
2049 dpurdie 2180
By default, the user is 'switched' to the newly created branch.
2181
 
2182
=head1 Switch Branch
2183
 
311 dpurdie 2184
=head2 NAME
2185
 
2049 dpurdie 2186
Switch a Workspace Branch
311 dpurdie 2187
 
2188
=head2 SYNOPSIS
2189
 
2049 dpurdie 2190
jats svn switch [branch-name] [options]
311 dpurdie 2191
 
2192
 Options:
2049 dpurdie 2193
    -help[=n]              - Help message, [n=1,2,3]
2194
    -man                   - Full documentation [-help=3]
2195
    -verbose[=n]           - Verbose command operation
2196
    -path=path             - Target workspace
311 dpurdie 2197
 
2198
=head2 ARGUMENTS
2199
 
2049 dpurdie 2200
The command takes one optional argument. The name of the target branch.
311 dpurdie 2201
 
2049 dpurdie 2202
=head2 OPTIONS
2203
 
311 dpurdie 2204
=over
2205
 
2049 dpurdie 2206
=item B<-path=path>
311 dpurdie 2207
 
2049 dpurdie 2208
This options specifies the path of the target workspace. If not provided the
2209
command will use the current directory.
311 dpurdie 2210
 
2049 dpurdie 2211
=back
311 dpurdie 2212
 
2049 dpurdie 2213
=head2 DESCRIPTION
311 dpurdie 2214
 
2049 dpurdie 2215
This command will switch the users workspace to the named branch. This is
2216
identical to the Subversion switch command, except it is easier to user and
2217
has several validity checks and other enhancements.
311 dpurdie 2218
 
2049 dpurdie 2219
The command has two modes of operation:
311 dpurdie 2220
 
2049 dpurdie 2221
=over 4
311 dpurdie 2222
 
2049 dpurdie 2223
=item   1. Display a list of branched in the current package.
311 dpurdie 2224
 
2049 dpurdie 2225
If no branch is specified, then the utility will display a list of branches in
2226
the packages 'branches' directory.
311 dpurdie 2227
 
2049 dpurdie 2228
=item   2. Switch to the named branch.
311 dpurdie 2229
 
2049 dpurdie 2230
The named branch must exists otherwise the command will fail.
311 dpurdie 2231
 
2429 dpurdie 2232
There are two special variants of the branch name:
311 dpurdie 2233
 
2049 dpurdie 2234
=over 4
311 dpurdie 2235
 
2049 dpurdie 2236
=item trunk
311 dpurdie 2237
 
2049 dpurdie 2238
If the branch is named 'trunk' then it will refer to the packages truck
1403 dpurdie 2239
 
2049 dpurdie 2240
=item tags
1403 dpurdie 2241
 
2049 dpurdie 2242
If the branch name starts with 'tags/', then the command will refer to
2243
a tag within the package and not a branch.
1403 dpurdie 2244
 
2049 dpurdie 2245
=back
1403 dpurdie 2246
 
2049 dpurdie 2247
The command will add and remove unmodified files from the workspace during this
2248
operation.
311 dpurdie 2249
 
2049 dpurdie 2250
=back
311 dpurdie 2251
 
2049 dpurdie 2252
=head3 Examples
311 dpurdie 2253
 
2049 dpurdie 2254
To switch to the packages trunk
311 dpurdie 2255
 
2049 dpurdie 2256
    jats svn switch trunk
311 dpurdie 2257
 
2049 dpurdie 2258
To switch to the a branch called MyBranch
311 dpurdie 2259
 
2049 dpurdie 2260
    jats svn switch MyBranch
311 dpurdie 2261
 
2049 dpurdie 2262
To switch to a tagged version of the package
311 dpurdie 2263
 
2049 dpurdie 2264
    jats svn switch tags/MyPackage_1.0.0000.cr
311 dpurdie 2265
 
2049 dpurdie 2266
To display a list of available branches (not tags)
311 dpurdie 2267
 
2049 dpurdie 2268
    jats svn switch
311 dpurdie 2269
 
2049 dpurdie 2270
=head1 Delete Branch
311 dpurdie 2271
 
2049 dpurdie 2272
=head2 NAME
311 dpurdie 2273
 
2049 dpurdie 2274
Delete the Workspace Branch
311 dpurdie 2275
 
2049 dpurdie 2276
=head2 SYNOPSIS
311 dpurdie 2277
 
2429 dpurdie 2278
jats svn delete-branch [options] [branch-list]
311 dpurdie 2279
 
2049 dpurdie 2280
 Options:
2281
    -help[=n]              - Help message, [n=1,2,3]
2282
    -man                   - Full documentation [-help=3]
2283
    -verbose[=n]           - Verbose command operation
2284
    -path=path             - Target workspace
311 dpurdie 2285
 
2049 dpurdie 2286
=head2 ARGUMENTS
2287
 
2429 dpurdie 2288
The command may take zero or more arguments. If provided the arguments will be
2289
branch names to be deleted.
2049 dpurdie 2290
 
2291
=head2 OPTIONS
2292
 
2293
=over
2294
 
2295
=item B<-path=path>
2296
 
2297
This options specifies the path of the target workspace. If not provided the
2298
command will use the current directory.
2299
 
2300
=back
2301
 
2302
=head2 DESCRIPTION
2303
 
2429 dpurdie 2304
This command can display the branch associated with the workspace or it can
2305
delete one or more branches. It is intended to simplify the deletion of Private
2306
or Development branches.
2049 dpurdie 2307
 
2429 dpurdie 2308
=over 4
2309
 
2310
=item 1 Arguments are provided
2311
 
2312
The command will delete all the named branches. If a named branch does not exist
2313
then the command will issue a warning message.
2314
 
2315
=item 2 No arguments provided
2316
 
2317
The command will display the branch associated with the workspace
2318
 
2049 dpurdie 2319
If the workspace is not linked to a 'branch' then the command will fail.
2320
 
2429 dpurdie 2321
=back
2322
 
311 dpurdie 2323
=head1 Import directory to a Package
2324
 
2325
=head2 NAME
2326
 
2327
Import directory to a Package
2328
 
2329
=head2 SYNOPSIS
2330
 
2331
jats svn [options] import URL [command options]
2332
 
2333
 Options:
2334
    -help[=n]               - Help message, [n=1,2,3]
2335
    -man                    - Full documentation [-help=3]
2336
    -verbose[=n]            - Verbose command operation
2337
 
2338
 Command Options
2339
    -help[=n]               - Command specific help, [n=1,2,3]
2340
    -verbose[=n]            - Verbose operation
2341
    -package=name           - Name of source package
2342
    -dir=path               - Path to new version
379 dpurdie 2343
    -label=label            - Label the result
2344
    -branch=branchName      - Base import on a branch
311 dpurdie 2345
    -replace                - Allow the label to be replaced
2346
    -reuse                  - Reuse the import directory
2347
    -workspace=path         - Path and name of alternate workspace
2348
    -[no]delete             - Deletes workspace after use. Default:yes
379 dpurdie 2349
    -author=name            - Force author of changes
2350
    -date=dateString        - Force date of changes
2351
    -log=text               - Append text to the commit message
2352
    -datafile=path          - Export tag data for automation
2931 dpurdie 2353
    -[no]commit             - Prevent changes being committed. Default:Yes
2429 dpurdie 2354
    -printfiles=n           - Control commit verbosity
2931 dpurdie 2355
    -mergePaths=dirList     - Comma separated list of directories to merge
311 dpurdie 2356
 
2357
=head2 ARGUMENTS
2358
 
2359
The command takes one argument: The URL of the desired package.
2360
This may be be:
2361
 
2362
=over
2363
 
2364
=item * A full URL
2365
 
2366
Complete with protocol and path information.
2367
 
2368
=item * A simple URL
2369
 
2370
JATS will prepend the site-specific repository location to the user provided URL
2371
 
2372
=back
2373
 
2374
=head2 OPTIONS
2375
 
2376
=over
2377
 
2378
=item -help[=n]
2379
 
2380
Print a help message and exit. The level of help may be either 1, 2 or 3.
2381
 
2382
This option may be specified multiple times to increment the help level, or
2383
the help level may be directly specified as a number.
2384
 
2385
=item -verbose[=n]
2386
 
2387
This option will increase the level of verbosity of the utility.
2388
 
2389
If an argument is provided, then it will be used to set the level, otherwise the
2390
existing level will be incremented. This option may be specified multiple times.
2391
 
2392
=item -package=name
2393
 
2394
Either this option or a bare URL on the command line must be provided. It
2395
specifies the repository and package to be used as a basis for the work.
2396
 
2397
=item -dir=path
2398
 
2399
This option is mandatory. It specifies the path to a local directory that
2400
contains a version of the software to be checked in.
2401
 
2402
=item -label=name
2403
 
2404
The resulting software version will be labeled with this tag, if it is provided.
2405
 
383 dpurdie 2406
A label name of TIMESTAMP will be treated in special manner. The name will be
2407
replaced with a unique name based on the users name and the current date time.
2408
 
379 dpurdie 2409
=item -branch=branchName
2410
 
2411
This option will cause the importation to be referenced to the named branch.
2412
If the branch does not exist it will be created. If it does exist then it will
2413
be used.
2414
 
2415
If this option is not specified, then the importation will be based on the 'trunk'.
2416
 
2417
If the Workspace is provided, then it will be used independently of this option.
2418
 
383 dpurdie 2419
A branchName of TIMESTAMP will be treated in special manner. The name will be
2420
replaced with a unique name based on the users name and the current date time.
2421
 
311 dpurdie 2422
=item -replace
2423
 
2424
This option, if provided, allows the label to be replaced.
2425
 
2426
=item -reuse
2427
 
2428
This option can be used to speed the creation of multiple versions in a scripted
2429
environment. The option allows the utility to reuse the workspace if it exists.
2430
 
2431
=item -workspace=path
2432
 
2433
This option specifies an alternate workspace directory to create and use. The
2434
default directory is "SvnImportDir" within the users current directory.
2435
 
2436
=item [no]delete
2437
 
341 dpurdie 2438
This option control the deletion of the workspace directory. By default the
311 dpurdie 2439
directory will be deleted, unless re-use is also used.
2440
 
379 dpurdie 2441
=item -author=name
2442
 
2443
This option will force the author of changes as recorded in the repository.
385 dpurdie 2444
The repository must be configured to allow such changes.
379 dpurdie 2445
 
2446
This option may not work for non-admin users.
2447
 
2448
=item -date=dateString
2449
 
2450
This option will force the date of the changes as recorded in the repository.
385 dpurdie 2451
The repository must be configured to allow such changes.
379 dpurdie 2452
The dateString is in a restricted ISO 8601 format: ie 2009-02-12T00:44:04.921324Z
2453
 
2454
This option may not work for non-admin users.
2455
 
2456
=item -log=text
2457
 
2458
This option will append the specified text to the commit message.
2459
The first line of the commit message is fixed by the import tool.
2460
 
2461
=item -datafile=path
2462
 
2463
This option will cause the utility to create a data file to record the import
2464
tag. It is used for automation of the import process.
2465
 
2429 dpurdie 2466
=item -[no]commit
2467
 
2468
This option will prevent the final workspace from being committed to the
2469
Repository. This allows inspection of the results.
2470
 
2471
The default operation is to commit and label the results of the import.
2472
 
2473
=item -printfiles=n
2474
 
2475
This option controls commit verbosity. The default operation is to display
2476
the files added and removed during the commit.
2477
 
2478
Suitable numbers are: None, 0 (No Display) and 1 (Full Display).
2479
 
2764 dpurdie 2480
=item -mergePaths=dirList
2481
 
2931 dpurdie 2482
This option specifies a Comma separated list of directories to be merged
3967 dpurdie 2483
during the import process. This works via the following mechanism:
2764 dpurdie 2484
 
2485
If the named directory exists in the 'new' image it will replace that in the
2486
'initial' workspace.
2487
 
2488
If the named directory does not exist in the 'new' image, but does exist in the
2489
'initial' image then it will be retained in the 'final' image.
2490
 
2491
Directories other than those named will not be imported.
2492
 
311 dpurdie 2493
=back
2494
 
2495
=head2 DESCRIPTION
2496
 
2497
Import a new version of a package to the trunk of the package. The utility
2498
will only import changed files so that file history is preserved within the
2499
repository.
2500
 
2501
This utility is used import software from another version control system
2502
The utility will:
2503
 
2504
=over
2505
 
361 dpurdie 2506
=item *
311 dpurdie 2507
 
361 dpurdie 2508
Create a Work Space based on the current package version
2509
 
379 dpurdie 2510
The 'trunk' of the named package will be used as the base for the workspace,
2511
unless modified with the -branch option.
311 dpurdie 2512
 
361 dpurdie 2513
=item *
311 dpurdie 2514
 
361 dpurdie 2515
Update files and directories
2516
 
311 dpurdie 2517
Determines the files and directories that have been added and deleted and
2518
update the Workspace to reflect the new structure.
2519
 
361 dpurdie 2520
=item *
311 dpurdie 2521
 
361 dpurdie 2522
Check in the new version
311 dpurdie 2523
 
361 dpurdie 2524
=item *
2525
 
2526
Label the new version
2527
 
311 dpurdie 2528
=back
2529
 
7217 dpurdie 2530
=head1 Sync Merge
2531
 
2532
=head2 NAME
2533
 
2534
Perform a Feature Branch Sync Merge
2535
 
2536
=head2 SYNOPSIS
2537
 
2538
jats svn merge [options]
2539
 
2540
 Options:
2541
    -help[=n]              - Help message, [n=1,2,3]
2542
    -man                   - Full documentation [-help=3]
2543
    -verbose[=n]           - Verbose command operation
2544
    -info                  - Displays merge info only
2545
    -dry-run               - Perform a dry run of the merge
2546
    -path=path             - Target workspace
2547
    ...                    - Other options are passed to the merge
2548
 
2549
=head2 ARGUMENTS
2550
 
2551
The command takes no arguments, just options.
2552
 
2553
=head2 OPTIONS
2554
 
2555
=over
2556
 
2557
=item B<-path=path>
2558
 
2559
This options specifies the path of the target workspace. If not provided the
2560
command will use the current directory.
2561
 
2562
=item B<-info>
2563
 
2564
This option will display information about the proposed merge, but it will not do the merge.
2565
This is not the same as a '-dry-run' as it shows information that the command has recovered from
2566
the workspace.
2567
 
2568
=item B<-dry-run>
2569
 
2570
This option will perform a dry run of the actual merge. It will not modify the workspace.
2571
 
2572
=item B<...>
2573
 
2574
Options that are not processed by this command will be passed through to the underlying
2575
'svn merge' command. Available options include:
2576
 
2577
=over 8
2578
 
2579
=item * --accept=mf (mine-full)
2580
 
2581
=item * --accept=mc (mine-conflict)
2582
 
2583
=back
2584
 
2585
=back
2586
 
2587
=head2 DESCRIPTION
2588
 
2589
This command implements the common operation of merging the release branch 
2590
head (normally trunk) onto a private development branch in the current working copy. 
2591
 
2592
The main goal of this command is to avoid situations where developers accidentally merge 
2593
from the wrong branch, or end up with (to them) inexplicable merge failures and thus 
2594
lose confidence in Subversion. 
2595
 
2596
It will fail if the current working copy is actually on the trunk, and not a branch.
2597
 
2598
=head1 Reintegrate Merge
2599
 
2600
=head2 NAME
2601
 
2602
Reintegrate a Feature Branch
2603
 
2604
=head2 SYNOPSIS
2605
 
7236 dpurdie 2606
jats svn reintegrate [options] [branch name]
7217 dpurdie 2607
 
2608
 Options:
2609
    -help[=n]              - Help message, [n=1,2,3]
2610
    -man                   - Full documentation [-help=3]
2611
    -verbose[=n]           - Verbose command operation
2612
    -path=path             - Target workspace
2613
    -info                  - Displays merge info only
2614
    -dry-run               - Perform a dry run of the merge
7236 dpurdie 2615
    -branch=name           - The branch to be used as the merge source
7217 dpurdie 2616
    ...                    - Other options are passed to the merge
2617
 
2618
=head2 ARGUMENTS
2619
 
7236 dpurdie 2620
If an argument is provided then it will be used as the name of the branch to be merged into
2621
the current workspace. This is the same as using the -branch option.
7217 dpurdie 2622
 
2623
=head2 OPTIONS
2624
 
2625
=over
2626
 
2627
=item B<-path=path>
2628
 
2629
This options specifies the path of the target workspace. If not provided the
2630
command will use the current directory.
2631
 
2632
=item B<-info>
2633
 
2634
This option will display information about the proposed merge, but it will not do the merge.
2635
This is not the same as a '--dry-run' as it shows information that the command has recovered from
2636
the workspace.
2637
 
2638
=item B<-dry-run>
2639
 
2640
This option will perform a dry run of the actual merge. It will NOT deleted the feature branch. It will
2641
switch the workspace and after the dry run of the merge it will switch it back.
2642
 
2643
This option implies '-reintegrate'.
2644
 
7236 dpurdie 2645
=item B<-branch>
7217 dpurdie 2646
 
7236 dpurdie 2647
This option provides an alternate method for specifying the source of the merge.
7217 dpurdie 2648
 
2649
=item B<...>
2650
 
2651
Options that are not processed by this command will be passed through to the underlying
2652
'svn merge' command. Available options include:
2653
 
2654
=over 8
2655
 
2656
=item * --accept=mf (mine-full)
2657
 
2658
=item * --accept=mc (mine-conflict)
2659
 
2660
=back
2661
 
2662
=head2 DESCRIPTION
2663
 
2664
This command implements the common operation of merging a private branch back into the main
2665
development branch (normally the trunk).
2666
 
2667
The main goal of this command is to avoid situations where developers accidentally merge 
2668
from the wrong branch, or end up with (to them) inexplicable merge failures and thus 
2669
lose confidence in Subversion. 
2670
 
7236 dpurdie 2671
It will fail if the specified branch was not tacken from the package's trunk.
7217 dpurdie 2672
 
2673
The command will do the following operations:
2674
 
2675
=over 8
2676
 
2677
=item * 
2678
 
2679
Ensure that the path address a subversion workspace and that the user is not in a sundirectory
2680
of the workspace.
2681
 
2682
=item * 
2683
 
7236 dpurdie 2684
Ensure the specified branch exists within the package.
7217 dpurdie 2685
 
2686
=item * 
2687
 
2688
Ensure the workspace contains no modified files
2689
 
2690
=item * 
2691
 
7236 dpurdie 2692
Ensure that the specified branch was taken from the branch (often the trunk) on which the 
2693
workspace is based. A number of other sanity checks are also performed
7217 dpurdie 2694
 
7236 dpurdie 2695
 
7217 dpurdie 2696
=item * 
2697
 
7236 dpurdie 2698
Perform the reintegration merge.
7217 dpurdie 2699
 
7236 dpurdie 2700
This is, strictly speaking a 'svn merge --reintegrate' as that operation has been deprecated
2701
and was problematic. The effect is the same.
7217 dpurdie 2702
 
2703
=back
2704
 
7236 dpurdie 2705
At the end of the reintegration merge the workspace will conatin modified files. The user should verify 
2706
that the merge has had the desired result and to commit the changes.
7217 dpurdie 2707
 
311 dpurdie 2708
=cut
2709