Skip to content

Commit befc9ad

Browse files
author
Eric Wong
committed
git-svn: fix useSvmProps, hopefully for the last time
svm:mirror is not useful at all for us. Parts of the old unit test were broken and based on my misunderstanding of the svm:mirror property. When we read svm:source; make sure we correctly handle the '!' in it: it is used to separate the path of the repository root from the virtual path within the repository. We don't need to make that distinction, honestly! We also ensure that subdirectories are also mirrored with the correct URL if we're using useSvmProps. We have a new test that uses dumped repo that was really created using SVN::Mirror to avoid ambiguities and mis-understandings about the svm: properties. Note: trailing whitespace in the svm.dump file is unfortunately a reality and required by SVN; so please ignore it when applying this patch. Also, ensure that the -R/--remote/--svn-remote flag is always in effect if explicitly passed via the command-line. This allows us to track logically different mirrors sharing the same URL (probably common with SVN::Mirror/SVK users). Signed-off-by: Eric Wong <normalperson@yhbt.net>
1 parent 62e349d commit befc9ad

File tree

4 files changed

+619
-140
lines changed

4 files changed

+619
-140
lines changed

git-svn.perl

Lines changed: 57 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,9 @@ BEGIN
164164
my $rv = GetOptions(%opts, 'help|H|h' => \$_help, 'version|V' => \$_version,
165165
'minimize-connections' => \$Git::SVN::Migration::_minimize,
166166
'id|i=s' => \$Git::SVN::default_ref_id,
167-
'svn-remote|remote|R=s' => \$Git::SVN::default_repo_id);
167+
'svn-remote|remote|R=s' => sub {
168+
$Git::SVN::no_reuse_existing = 1;
169+
$Git::SVN::default_repo_id = $_[1] });
168170
exit 1 if (!$rv && $cmd ne 'log');
169171

170172
usage(0) if $_help;
@@ -749,7 +751,7 @@ package Git::SVN;
749751
use warnings;
750752
use vars qw/$default_repo_id $default_ref_id $_no_metadata $_follow_parent
751753
$_repack $_repack_flags $_use_svm_props $_head
752-
$_use_svnsync_props/;
754+
$_use_svnsync_props $no_reuse_existing/;
753755
use Carp qw/croak/;
754756
use File::Path qw/mkpath/;
755757
use File::Copy qw/copy/;
@@ -944,6 +946,7 @@ sub sanitize_remote_name {
944946

945947
sub find_existing_remote {
946948
my ($url, $remotes) = @_;
949+
return undef if $no_reuse_existing;
947950
my $existing;
948951
foreach my $repo_id (keys %$remotes) {
949952
my $u = $remotes->{$repo_id}->{url} or next;
@@ -1116,9 +1119,12 @@ sub svm {
11161119
$svm = {
11171120
source => tmp_config('--get', "$section.svm-source"),
11181121
uuid => tmp_config('--get', "$section.svm-uuid"),
1122+
replace => tmp_config('--get', "$section.svm-replace"),
11191123
}
11201124
};
1121-
$self->{svm} = $svm if ($svm && $svm->{source} && $svm->{uuid});
1125+
if ($svm && $svm->{source} && $svm->{uuid} && $svm->{replace}) {
1126+
$self->{svm} = $svm;
1127+
}
11221128
$self->{svm};
11231129
}
11241130

@@ -1127,64 +1133,76 @@ sub _set_svm_vars {
11271133
return $ra if $self->svm;
11281134

11291135
my @err = ( "useSvmProps set, but failed to read SVM properties\n",
1130-
"(svm:source, svm:mirror, svm:mirror) ",
1136+
"(svm:source, svm:uuid) ",
11311137
"from the following URLs:\n" );
11321138
sub read_svm_props {
1133-
my ($self, $props) = @_;
1139+
my ($self, $ra, $path, $r) = @_;
1140+
my $props = ($ra->get_dir($path, $r))[2];
11341141
my $src = $props->{'svm:source'};
1135-
my $mirror = $props->{'svm:mirror'};
11361142
my $uuid = $props->{'svm:uuid'};
1137-
return undef if (!$src || !$mirror || !$uuid);
1143+
return undef if (!$src || !$uuid);
11381144

1139-
chomp($src, $mirror, $uuid);
1145+
chomp($src, $uuid);
11401146

11411147
$uuid =~ m{^[0-9a-f\-]{30,}$}
11421148
or die "doesn't look right - svm:uuid is '$uuid'\n";
1143-
# don't know what a '!' is there for, also the
1144-
# username is of no interest
1145-
$src =~ s{/?!$}{$mirror};
1149+
1150+
# the '!' is used to mark the repos_root!/relative/path
1151+
$src =~ s{/?!/?}{/};
11461152
$src =~ s{/+$}{}; # no trailing slashes please
1153+
# username is of no interest
11471154
$src =~ s{(^[a-z\+]*://)[^/@]*@}{$1};
11481155

1156+
my $replace = $ra->{url};
1157+
$replace .= "/$path" if length $path;
1158+
11491159
my $section = "svn-remote.$self->{repo_id}";
1150-
tmp_config('--add', "$section.svm-source", $src);
1151-
tmp_config('--add', "$section.svm-uuid", $uuid);
1152-
$self->{svm} = { source => $src , uuid => $uuid };
1153-
return 1;
1160+
tmp_config("$section.svm-source", $src);
1161+
tmp_config("$section.svm-replace", $replace);
1162+
tmp_config("$section.svm-uuid", $uuid);
1163+
$self->{svm} = {
1164+
source => $src,
1165+
uuid => $uuid,
1166+
replace => $replace
1167+
};
11541168
}
11551169

11561170
my $r = $ra->get_latest_revnum;
11571171
my $path = $self->{path};
1158-
my @tried_a = ($path);
1172+
my %tried;
11591173
while (length $path) {
1160-
if ($self->read_svm_props(($ra->get_dir($path, $r))[2])) {
1161-
return $ra;
1174+
unless ($tried{"$self->{url}/$path"}) {
1175+
return $ra if $self->read_svm_props($ra, $path, $r);
1176+
$tried{"$self->{url}/$path"} = 1;
11621177
}
1163-
$path =~ s#/?[^/]+$## && push @tried_a, $path;
1164-
}
1165-
if ($self->read_svm_props(($ra->get_dir('', $r))[2])) {
1166-
return $ra;
1178+
$path =~ s#/?[^/]+$##;
11671179
}
1180+
die "Path: '$path' should be ''\n" if $path ne '';
1181+
return $ra if $self->read_svm_props($ra, $path, $r);
1182+
$tried{"$self->{url}/$path"} = 1;
11681183

11691184
if ($ra->{repos_root} eq $self->{url}) {
1170-
die @err, map { " $self->{url}/$_\n" } @tried_a, "\n";
1185+
die @err, (map { " $_\n" } keys %tried), "\n";
11711186
}
11721187

11731188
# nope, make sure we're connected to the repository root:
11741189
my $ok;
11751190
my @tried_b;
11761191
$path = $ra->{svn_path};
1177-
$path =~ s#/?[^/]+$##; # we already tried this one above
11781192
$ra = Git::SVN::Ra->new($ra->{repos_root});
11791193
while (length $path) {
1180-
$ok = $self->read_svm_props(($ra->get_dir($path, $r))[2]);
1181-
last if $ok;
1182-
$path =~ s#/?[^/]+$## && push @tried_b, $path;
1194+
unless ($tried{"$ra->{url}/$path"}) {
1195+
$ok = $self->read_svm_props($ra, $path, $r);
1196+
last if $ok;
1197+
$tried{"$ra->{url}/$path"} = 1;
1198+
}
1199+
$path =~ s#/?[^/]+$##;
11831200
}
1184-
$ok = $self->read_svm_props(($ra->get_dir('', $r))[2]) unless $ok;
1201+
die "Path: '$path' should be ''\n" if $path ne '';
1202+
$ok ||= $self->read_svm_props($ra, $path, $r);
1203+
$tried{"$ra->{url}/$path"} = 1;
11851204
if (!$ok) {
1186-
die @err, map { " $self->{url}/$_\n" } @tried_a, "\n",
1187-
map { " $ra->{url}/$_\n" } @tried_b, "\n"
1205+
die @err, (map { " $_\n" } keys %tried), "\n";
11881206
}
11891207
Git::SVN::Ra->new($self->{url});
11901208
}
@@ -1779,13 +1797,18 @@ sub make_log_entry {
17791797
"options set!\n";
17801798
}
17811799
my ($uuid, $r) = $headrev =~ m{^([a-f\d\-]{30,}):(\d+)$};
1782-
if ($uuid ne $self->{svm}->{uuid}) {
1800+
# we don't want "SVM: initializing mirror for junk" ...
1801+
return undef if $r == 0;
1802+
my $svm = $self->svm;
1803+
if ($uuid ne $svm->{uuid}) {
17831804
die "UUID mismatch on SVM path:\n",
1784-
"expected: $self->{svm}->{uuid}\n",
1805+
"expected: $svm->{uuid}\n",
17851806
" got: $uuid\n";
17861807
}
1787-
my $full_url = $self->{svm}->{source};
1788-
$full_url .= "/$self->{path}" if length $self->{path};
1808+
my $full_url = $self->full_url;
1809+
$full_url =~ s#^\Q$svm->{replace}\E(/|$)#$svm->{source}$1# or
1810+
die "Failed to replace '$svm->{replace}' with ",
1811+
"'$svm->{source}' in $full_url\n";
17891812
$log_entry{metadata} = "$full_url\@$r $uuid";
17901813
$log_entry{svm_revision} = $r;
17911814
$email ||= "$author\@$uuid"

t/t9109-git-svn-svk-mirrorpaths.sh

Lines changed: 0 additions & 106 deletions
This file was deleted.

t/t9110-git-svn-use-svm-props.sh

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#!/bin/sh
2+
#
3+
# Copyright (c) 2007 Eric Wong
4+
#
5+
6+
test_description='git-svn useSvmProps test'
7+
8+
. ./lib-git-svn.sh
9+
10+
test_expect_success 'load svm repo' "
11+
svnadmin load -q $rawsvnrepo < ../t9110/svm.dump &&
12+
git-svn init -R arr -i bar $svnrepo/mirror/arr &&
13+
git-svn init -R argh -i dir $svnrepo/mirror/argh &&
14+
git-svn init -R argh -i e $svnrepo/mirror/argh/a/b/c/d/e &&
15+
git-config svn.useSvmProps true &&
16+
git-svn fetch --all
17+
"
18+
19+
uuid=161ce429-a9dd-4828-af4a-52023f968c89
20+
21+
bar_url=http://mayonaise/svnrepo/bar
22+
test_expect_success 'verify metadata for /bar' "
23+
git-cat-file commit refs/remotes/bar | \
24+
grep '^git-svn-id: $bar_url@12 $uuid$' &&
25+
git-cat-file commit refs/remotes/bar~1 | \
26+
grep '^git-svn-id: $bar_url@11 $uuid$' &&
27+
git-cat-file commit refs/remotes/bar~2 | \
28+
grep '^git-svn-id: $bar_url@10 $uuid$' &&
29+
git-cat-file commit refs/remotes/bar~3 | \
30+
grep '^git-svn-id: $bar_url@9 $uuid$' &&
31+
git-cat-file commit refs/remotes/bar~4 | \
32+
grep '^git-svn-id: $bar_url@6 $uuid$' &&
33+
git-cat-file commit refs/remotes/bar~5 | \
34+
grep '^git-svn-id: $bar_url@1 $uuid$'
35+
"
36+
37+
e_url=http://mayonaise/svnrepo/dir/a/b/c/d/e
38+
test_expect_success 'verify metadata for /dir/a/b/c/d/e' "
39+
git-cat-file commit refs/remotes/e | \
40+
grep '^git-svn-id: $e_url@1 $uuid$'
41+
"
42+
43+
dir_url=http://mayonaise/svnrepo/dir
44+
test_expect_success 'verify metadata for /dir' "
45+
git-cat-file commit refs/remotes/dir | \
46+
grep '^git-svn-id: $dir_url@2 $uuid$' &&
47+
git-cat-file commit refs/remotes/dir~1 | \
48+
grep '^git-svn-id: $dir_url@1 $uuid$'
49+
"
50+
51+
test_done

0 commit comments

Comments
 (0)