diff --git a/git-svn.perl b/git-svn.perl index de026b4e4c..d290a0d8ee 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -748,35 +748,78 @@ sub sanitize_remote_name { $name; } +sub find_existing_remote { + my ($url, $remotes) = @_; + my $existing; + foreach my $repo_id (keys %$remotes) { + my $u = $remotes->{$repo_id}->{url} or next; + next if $u ne $url; + $existing = $repo_id; + last; + } + $existing; +} + +sub init_remote_config { + my ($self, $url) = @_; + $url =~ s!/+$!!; # strip trailing slash + my $r = read_all_remotes(); + my $existing = find_existing_remote($url, $r); + if ($existing) { + print STDERR "Using existing ", + "[svn-remote \"$existing\"]\n"; + $self->{repo_id} = $existing; + } else { + my $min_url = Git::SVN::Ra->new($url)->minimize_url; + $existing = find_existing_remote($min_url, $r); + if ($existing) { + print STDERR "Using existing ", + "[svn-remote \"$existing\"]\n"; + $self->{repo_id} = $existing; + } + if ($min_url ne $url) { + print STDERR "Using higher level of URL: ", + "$url => $min_url\n"; + my $old_path = $self->{path}; + $self->{path} = $url; + $self->{path} =~ s!^\Q$min_url\E/*!!; + if (length $old_path) { + $self->{path} .= "/$old_path"; + } + $url = $min_url; + } + } + my $orig_url; + if (!$existing) { + # verify that we aren't overwriting anything: + $orig_url = eval { + command_oneline('config', '--get', + "svn-remote.$self->{repo_id}.url") + }; + if ($orig_url && ($orig_url ne $url)) { + die "svn-remote.$self->{repo_id}.url already set: ", + "$orig_url\nwanted to set to: $url\n"; + } + } + my ($xrepo_id, $xpath) = find_ref($self->refname); + if (defined $xpath) { + die "svn-remote.$xrepo_id.fetch already set to track ", + "$xpath:refs/remotes/", $self->refname, "\n"; + } + command_noisy('config', + "svn-remote.$self->{repo_id}.url", $url); + command_noisy('config', '--add', + "svn-remote.$self->{repo_id}.fetch", + "$self->{path}:".$self->refname); + $self->{url} = $url; +} + sub init { my ($class, $url, $path, $repo_id, $ref_id) = @_; my $self = _new($class, $repo_id, $ref_id, $path); if (defined $url) { - $url =~ s!/+$!!; # strip trailing slash - - # verify that we aren't overwriting anything: - my $orig_url = eval { - command_oneline('config', '--get', - "svn-remote.$repo_id.url") - }; - if ($orig_url && ($orig_url ne $url)) { - die "svn-remote.$repo_id.url already set: ", - "$orig_url\nwanted to set to: $url\n"; - } - my ($xrepo_id, $xpath) = find_ref($self->refname); - if (defined $xpath) { - die "svn-remote.$xrepo_id.fetch already set to track ", - "$xpath:refs/remotes/", $self->refname, "\n"; - } - if (!$orig_url) { - command_noisy('config', - "svn-remote.$repo_id.url", $url); - } - command_noisy('config', '--add', - "svn-remote.$repo_id.fetch", - "$path:".$self->refname); + $self->init_remote_config($url); } - $self->{url} = $url; $self; } @@ -2208,6 +2251,19 @@ sub gs_do_switch { $editor->{git_commit_ok}; } +sub minimize_url { + my ($self) = @_; + return $self->{url} if ($self->{url} eq $self->{repos_root}); + my $url = $self->{repos_root}; + my @components = split(m!/!, $self->{svn_path}); + my $c = ''; + do { + $url .= "/$c" if length $c; + eval { (ref $self)->new($url)->get_latest_revnum }; + } while ($@ && ($c = shift @components)); + $url; +} + sub can_do_switch { my $self = shift; unless (defined $can_do_switch) { diff --git a/t/t9100-git-svn-basic.sh b/t/t9100-git-svn-basic.sh index af617486dd..97798c4d07 100755 --- a/t/t9100-git-svn-basic.sh +++ b/t/t9100-git-svn-basic.sh @@ -220,10 +220,22 @@ test_expect_failure 'exit if remote refs are ambigious' " bar:refs/remotes/git-svn && git-svn migrate " + test_expect_failure 'exit if init-ing a would clobber a URL' " + svnadmin create ${PWD}/svnrepo2 && + svn mkdir -m 'mkdir bar' ${svnrepo}2/bar && git-repo-config --unset svn-remote.git-svn.fetch \ '^bar:refs/remotes/git-svn$' && - git-svn init $svnrepo/bar + git-svn init ${svnrepo}2/bar + " + +test_expect_success \ + 'init allows us to connect to another directory in the same repo' " + git-svn init -i bar $svnrepo/bar && + git repo-config --get svn-remote.git-svn.fetch \ + '^bar:refs/remotes/bar$' && + git repo-config --get svn-remote.git-svn.fetch \ + '^:refs/remotes/git-svn$' " test_done