While fixing the other bug, I discovered another quirk. When tagging a
directory with fully-contained externals, those externals are not
repointed, but merely pinned to the current revision. It would be more
aesthetically clean if it repointed them inside the tagged copy as well.
So I made the changes in the attached patch to allow simultaneous
branching and tagging. When svncopy.pl is called with both --branch and
--tag as arguments, it will repoint any fully-contained externals to be
within the copy, and pin the revisions of any other externals. (The
former are not pinned.)
--
Anthony Foglia
Princeton Consultants
(609) 987-8787 x233
diff --git a/svncopy.README b/svncopy.README
index 215545b..4e5cea0 100644
--- a/svncopy.README
+++ b/svncopy.README
@@ -291,6 +291,45 @@ Note: you *must* branch all affected directories simultaneously. If you
branch them one at a time, the script will not know which externals refer
to other components of the same project, and will leave them unchanged.
+Example 7 - branching and tagging combined
+------------------------------------------
+
+If you try to tag a directory with both externals both fully-contained
+and not, you need to both branch (repoint externals pointing within
+the copy source) and tag (pin externals pointing outside the source).
+
+$ perl svncopy.pl --branch --tag http://svn/repos/trunk \
+ http://svn/repos/tags/release_3.2
+
+Result:
+
+trunk/
+ [ as above]
+tags/
+ release_3.2/
+ common/
+ common1.c
+ common2.c
+ inc/
+ common1.h
+ common2.h
+ proj_foo/
+ foo1.c
+ foo2.c
+ X common -r 4997 http://svn/repos/trunk/common
+ X inc http://svn/repos/tags/release_3.2/inc
+ proj_bar/
+ bar1.c
+ bar2.c
+ bar2.h
+ X common http://svn/repos/tags/release_3.2/common
+ X inc http://svn/repos/tags/release_3.2/inc
+ X public -r 17753 http://someserver/repos/public
+
+The svn:externals that originally pointed within the source are now
+pointing to the corresponding directories in the newly-created tag,
+while the svn:external that pointed outside has been pinned.
+
Testing svncopy.pl
==================
diff --git a/svncopy.pl.in b/svncopy.pl.in
index c03cac2..f0ee839 100644
--- a/svncopy.pl.in
+++ b/svncopy.pl.in
@@ -545,6 +545,7 @@ sub UpdateExternalsOnDir
# Only update if it's not pinned to a version
if ( !$ext_rev )
{
+ my $is_fully_contained = 0;
if ( $update_externals )
{
my $old_external = $external;
@@ -565,10 +566,14 @@ sub UpdateExternalsOnDir
$external = "$ext_dir$spacing$ext_val";
info( " - updated '$old_external' to '$external'\n" );
$changed{$old_external} = $external;
+ $is_fully_contained = 1;
}
}
}
- elsif ( $pin_externals )
+
+ # If we didn't update it, it's an external to something we
+ # didn't copy, so check to pin it.
+ if ( ( ! $is_fully_contained ) && $pin_externals )
{
# Find the last revision of the destination and pin to that.
my $old_external = $external;