git-svn: 'init' attempts to connect to the repository root if possible

This allows connections to be used more efficiently and not require
users to run 'git-svn migrate --minimize' for new repositories.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
This commit is contained in:
Eric Wong 2007-01-23 16:29:23 -08:00
parent 9bf046372b
commit e6434f8760
2 changed files with 93 additions and 25 deletions

View File

@ -748,35 +748,78 @@ sub sanitize_remote_name {
$name;
}
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
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:
my $orig_url = eval {
$orig_url = eval {
command_oneline('config', '--get',
"svn-remote.$repo_id.url")
"svn-remote.$self->{repo_id}.url")
};
if ($orig_url && ($orig_url ne $url)) {
die "svn-remote.$repo_id.url already set: ",
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";
}
if (!$orig_url) {
command_noisy('config',
"svn-remote.$repo_id.url", $url);
}
"svn-remote.$self->{repo_id}.url", $url);
command_noisy('config', '--add',
"svn-remote.$repo_id.fetch",
"$path:".$self->refname);
}
"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) {
$self->init_remote_config($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) {

View File

@ -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