Skip to content

Commit

Permalink
git-svn: correctly handle do_{switch,update} in deep directories
Browse files Browse the repository at this point in the history
The do_update or do_switch functions in SVN only allow for a
single path component; so 'path/to/deep/dir' would be
interpreted as 'path'.

SVN 1.4.x has a reparent function that can let us change the
session to use a higher-level root of the repository, so we can
use that for do_switch (which still doesn't seem to work in SVN
1.4.3 (a fix was attempted, but they missed the rest of the
typemap changes needed in trunk...)).

On the do_update side, we can use set_path on higher level
directories and set them to a newer revision so they don't get
updated.  We can't do this with do_switch, either, because the
relative path we're tracking can change (directory moving into
a child of itself).

Because of these changes, we need to double check that our Fetch
editor is correctly performing stripping on any prefixed paths
from update, otherwise we'll just die() because that would be
a bug.

Added a test case which helped me notice and fix problems with
do_switch, too.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
  • Loading branch information
Eric Wong committed Feb 23, 2007
1 parent 2fa6a23 commit 2b27f6c
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 8 deletions.
46 changes: 38 additions & 8 deletions git-svn.perl
Original file line number Diff line number Diff line change
Expand Up @@ -1153,7 +1153,7 @@ sub find_parent_branch {
if ($self->ra->can_do_switch) {
print STDERR "Following parent with do_switch\n";
# do_switch works with svn/trunk >= r22312, but that
# is not included with SVN 1.4.2 (the latest version
# is not included with SVN 1.4.3 (the latest version
# at the moment), so we can't rely on it
$self->{last_commit} = $parent;
$ed = SVN::Git::Fetcher->new($self);
Expand Down Expand Up @@ -1621,7 +1621,10 @@ sub open_directory {

sub git_path {
my ($self, $path) = @_;
$path =~ s!$self->{path_strip}!! if $self->{path_strip};
if ($self->{path_strip}) {
$path =~ s!$self->{path_strip}!! or
die "Failed to strip path '$path' ($self->{path_strip})\n";
}
$path;
}

Expand Down Expand Up @@ -2249,25 +2252,52 @@ sub gs_do_update {
my ($self, $rev_a, $rev_b, $path, $recurse, $editor) = @_;
my $pool = SVN::Pool->new;
$editor->set_path_strip($path);
my $reporter = $self->do_update($rev_b, $path, $recurse,
$editor, $pool);
my (@pc) = split m#/#, $path;
my $reporter = $self->do_update($rev_b, (@pc ? shift @pc : ''),
$recurse, $editor, $pool);
my @lock = $SVN::Core::VERSION ge '1.2.0' ? (undef) : ();

# Since we can't rely on svn_ra_reparent being available, we'll
# just have to do some magic with set_path to make it so
# we only want a partial path.
my $sp = '';
my $final = join('/', @pc);
while (@pc) {
$reporter->set_path($sp, $rev_b, 0, @lock, $pool);
$sp .= '/' if length $sp;
$sp .= shift @pc;
}
die "BUG: '$sp' != '$final'\n" if ($sp ne $final);

my $new = ($rev_a == $rev_b);
$reporter->set_path('', $rev_a, $new, @lock, $pool);
$reporter->set_path($sp, $rev_a, $new, @lock, $pool);

$reporter->finish_report($pool);
$pool->clear;
$editor->{git_commit_ok};
}

# this requires SVN 1.4.3 or later (do_switch didn't work before 1.4.3, and
# svn_ra_reparent didn't work before 1.4)
sub gs_do_switch {
my ($self, $rev_a, $rev_b, $path, $recurse, $url_b, $editor) = @_;
my $pool = SVN::Pool->new;
$editor->set_path_strip($path);
my $reporter = $self->do_switch($rev_b, $path, $recurse,
$url_b, $editor, $pool);

my $full_url = $self->{url};
my $old_url = $full_url;
$full_url .= "/$path" if length $path;
SVN::_Ra::svn_ra_reparent($self->{session}, $full_url, $pool);
$self->{url} = $full_url;

my $reporter = $self->do_switch($rev_b, '',
$recurse, $url_b, $editor, $pool);
my @lock = $SVN::Core::VERSION ge '1.2.0' ? (undef) : ();
$reporter->set_path('', $rev_a, 0, @lock, $pool);
$reporter->finish_report($pool);

SVN::_Ra::svn_ra_reparent($self->{session}, $old_url, $pool);
$self->{url} = $old_url;

$pool->clear;
$editor->{git_commit_ok};
}
Expand Down
31 changes: 31 additions & 0 deletions t/t9104-git-svn-follow-parent.sh
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,37 @@ test_expect_success 'follow deleted directory' "
test -z \"\`git ls-tree -z refs/remotes/glob\`\"
"

# ref: r9270 of the Subversion repository: (http://svn.collab.net/repos/svn)
# in trunk/subversion/bindings/swig/perl
test_expect_success '' "
mkdir -p import/trunk/subversion/bindings/swig/perl/t &&
for i in a b c ; do \
echo \$i > import/trunk/subversion/bindings/swig/perl/\$i.pm &&
echo _\$i > import/trunk/subversion/bindings/swig/perl/t/\$i.t; \
done &&
echo 'bad delete test' > \
import/trunk/subversion/bindings/swig/perl/t/larger-parent &&
echo 'bad delete test 2' > \
import/trunk/subversion/bindings/swig/perl/another-larger &&
cd import &&
svn import -m 'r9270 test' . $svnrepo/r9270 &&
cd .. &&
svn co $svnrepo/r9270/trunk/subversion/bindings/swig/perl r9270 &&
cd r9270 &&
svn mkdir native &&
svn mv t native/t &&
for i in a b c; do svn mv \$i.pm native/\$i.pm; done &&
echo z >> native/t/c.t &&
svn commit -m 'reorg test' &&
cd .. &&
git-svn init -i r9270-t \
$svnrepo/r9270/trunk/subversion/bindings/swig/perl/native/t &&
git-svn fetch -i r9270-t --follow-parent &&
test \`git rev-list r9270-t | wc -l\` -eq 2 &&
test \"\`git ls-tree --name-only r9270-t~1\`\" = \
\"\`git ls-tree --name-only r9270-t\`\"
"

test_debug 'gitk --all &'

test_done

0 comments on commit 2b27f6c

Please sign in to comment.