summaryrefslogtreecommitdiff
path: root/git-svn.perl
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2007-02-17 10:53:07 (GMT)
committerEric Wong <normalperson@yhbt.net>2007-02-23 08:57:13 (GMT)
commitbefc9adc0ced7d3e1c1316d6420007357d50b202 (patch)
tree186451798759ca705c03be77d95e4bee5db5b954 /git-svn.perl
parent62e349d235ecbb20c5338de5d4cbff9ce5c6aa66 (diff)
downloadgit-befc9adc0ced7d3e1c1316d6420007357d50b202.zip
git-befc9adc0ced7d3e1c1316d6420007357d50b202.tar.gz
git-befc9adc0ced7d3e1c1316d6420007357d50b202.tar.bz2
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>
Diffstat (limited to 'git-svn.perl')
-rwxr-xr-xgit-svn.perl91
1 files changed, 57 insertions, 34 deletions
diff --git a/git-svn.perl b/git-svn.perl
index 7563eea..1bcf058 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -164,7 +164,9 @@ read_repo_config(\%opts);
my $rv = GetOptions(%opts, 'help|H|h' => \$_help, 'version|V' => \$_version,
'minimize-connections' => \$Git::SVN::Migration::_minimize,
'id|i=s' => \$Git::SVN::default_ref_id,
- 'svn-remote|remote|R=s' => \$Git::SVN::default_repo_id);
+ 'svn-remote|remote|R=s' => sub {
+ $Git::SVN::no_reuse_existing = 1;
+ $Git::SVN::default_repo_id = $_[1] });
exit 1 if (!$rv && $cmd ne 'log');
usage(0) if $_help;
@@ -749,7 +751,7 @@ use strict;
use warnings;
use vars qw/$default_repo_id $default_ref_id $_no_metadata $_follow_parent
$_repack $_repack_flags $_use_svm_props $_head
- $_use_svnsync_props/;
+ $_use_svnsync_props $no_reuse_existing/;
use Carp qw/croak/;
use File::Path qw/mkpath/;
use File::Copy qw/copy/;
@@ -944,6 +946,7 @@ sub sanitize_remote_name {
sub find_existing_remote {
my ($url, $remotes) = @_;
+ return undef if $no_reuse_existing;
my $existing;
foreach my $repo_id (keys %$remotes) {
my $u = $remotes->{$repo_id}->{url} or next;
@@ -1116,9 +1119,12 @@ sub svm {
$svm = {
source => tmp_config('--get', "$section.svm-source"),
uuid => tmp_config('--get', "$section.svm-uuid"),
+ replace => tmp_config('--get', "$section.svm-replace"),
}
};
- $self->{svm} = $svm if ($svm && $svm->{source} && $svm->{uuid});
+ if ($svm && $svm->{source} && $svm->{uuid} && $svm->{replace}) {
+ $self->{svm} = $svm;
+ }
$self->{svm};
}
@@ -1127,64 +1133,76 @@ sub _set_svm_vars {
return $ra if $self->svm;
my @err = ( "useSvmProps set, but failed to read SVM properties\n",
- "(svm:source, svm:mirror, svm:mirror) ",
+ "(svm:source, svm:uuid) ",
"from the following URLs:\n" );
sub read_svm_props {
- my ($self, $props) = @_;
+ my ($self, $ra, $path, $r) = @_;
+ my $props = ($ra->get_dir($path, $r))[2];
my $src = $props->{'svm:source'};
- my $mirror = $props->{'svm:mirror'};
my $uuid = $props->{'svm:uuid'};
- return undef if (!$src || !$mirror || !$uuid);
+ return undef if (!$src || !$uuid);
- chomp($src, $mirror, $uuid);
+ chomp($src, $uuid);
$uuid =~ m{^[0-9a-f\-]{30,}$}
or die "doesn't look right - svm:uuid is '$uuid'\n";
- # don't know what a '!' is there for, also the
- # username is of no interest
- $src =~ s{/?!$}{$mirror};
+
+ # the '!' is used to mark the repos_root!/relative/path
+ $src =~ s{/?!/?}{/};
$src =~ s{/+$}{}; # no trailing slashes please
+ # username is of no interest
$src =~ s{(^[a-z\+]*://)[^/@]*@}{$1};
+ my $replace = $ra->{url};
+ $replace .= "/$path" if length $path;
+
my $section = "svn-remote.$self->{repo_id}";
- tmp_config('--add', "$section.svm-source", $src);
- tmp_config('--add', "$section.svm-uuid", $uuid);
- $self->{svm} = { source => $src , uuid => $uuid };
- return 1;
+ tmp_config("$section.svm-source", $src);
+ tmp_config("$section.svm-replace", $replace);
+ tmp_config("$section.svm-uuid", $uuid);
+ $self->{svm} = {
+ source => $src,
+ uuid => $uuid,
+ replace => $replace
+ };
}
my $r = $ra->get_latest_revnum;
my $path = $self->{path};
- my @tried_a = ($path);
+ my %tried;
while (length $path) {
- if ($self->read_svm_props(($ra->get_dir($path, $r))[2])) {
- return $ra;
+ unless ($tried{"$self->{url}/$path"}) {
+ return $ra if $self->read_svm_props($ra, $path, $r);
+ $tried{"$self->{url}/$path"} = 1;
}
- $path =~ s#/?[^/]+$## && push @tried_a, $path;
- }
- if ($self->read_svm_props(($ra->get_dir('', $r))[2])) {
- return $ra;
+ $path =~ s#/?[^/]+$##;
}
+ die "Path: '$path' should be ''\n" if $path ne '';
+ return $ra if $self->read_svm_props($ra, $path, $r);
+ $tried{"$self->{url}/$path"} = 1;
if ($ra->{repos_root} eq $self->{url}) {
- die @err, map { " $self->{url}/$_\n" } @tried_a, "\n";
+ die @err, (map { " $_\n" } keys %tried), "\n";
}
# nope, make sure we're connected to the repository root:
my $ok;
my @tried_b;
$path = $ra->{svn_path};
- $path =~ s#/?[^/]+$##; # we already tried this one above
$ra = Git::SVN::Ra->new($ra->{repos_root});
while (length $path) {
- $ok = $self->read_svm_props(($ra->get_dir($path, $r))[2]);
- last if $ok;
- $path =~ s#/?[^/]+$## && push @tried_b, $path;
+ unless ($tried{"$ra->{url}/$path"}) {
+ $ok = $self->read_svm_props($ra, $path, $r);
+ last if $ok;
+ $tried{"$ra->{url}/$path"} = 1;
+ }
+ $path =~ s#/?[^/]+$##;
}
- $ok = $self->read_svm_props(($ra->get_dir('', $r))[2]) unless $ok;
+ die "Path: '$path' should be ''\n" if $path ne '';
+ $ok ||= $self->read_svm_props($ra, $path, $r);
+ $tried{"$ra->{url}/$path"} = 1;
if (!$ok) {
- die @err, map { " $self->{url}/$_\n" } @tried_a, "\n",
- map { " $ra->{url}/$_\n" } @tried_b, "\n"
+ die @err, (map { " $_\n" } keys %tried), "\n";
}
Git::SVN::Ra->new($self->{url});
}
@@ -1779,13 +1797,18 @@ sub make_log_entry {
"options set!\n";
}
my ($uuid, $r) = $headrev =~ m{^([a-f\d\-]{30,}):(\d+)$};
- if ($uuid ne $self->{svm}->{uuid}) {
+ # we don't want "SVM: initializing mirror for junk" ...
+ return undef if $r == 0;
+ my $svm = $self->svm;
+ if ($uuid ne $svm->{uuid}) {
die "UUID mismatch on SVM path:\n",
- "expected: $self->{svm}->{uuid}\n",
+ "expected: $svm->{uuid}\n",
" got: $uuid\n";
}
- my $full_url = $self->{svm}->{source};
- $full_url .= "/$self->{path}" if length $self->{path};
+ my $full_url = $self->full_url;
+ $full_url =~ s#^\Q$svm->{replace}\E(/|$)#$svm->{source}$1# or
+ die "Failed to replace '$svm->{replace}' with ",
+ "'$svm->{source}' in $full_url\n";
$log_entry{metadata} = "$full_url\@$r $uuid";
$log_entry{svm_revision} = $r;
$email ||= "$author\@$uuid"