diff options
-rwxr-xr-x | git-svn.perl | 116 |
1 files changed, 83 insertions, 33 deletions
diff --git a/git-svn.perl b/git-svn.perl index b7e46e5b0..d55691216 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -367,8 +367,7 @@ sub cmd_multi_init { sub cmd_multi_fetch { my $remotes = Git::SVN::read_all_remotes(); foreach my $repo_id (sort keys %$remotes) { - if ($remotes->{$repo_id}->{url} && - $remotes->{$repo_id}->{fetch}) { + if ($remotes->{$repo_id}->{url}) { Git::SVN::fetch_all($repo_id, $remotes); } } @@ -483,6 +482,17 @@ sub complete_url_ls_init { $gs = Git::SVN->init($url, $path, undef, $ref, 1); } if ($gs) { + my $k = "svn-remote.$gs->{repo_id}.url"; + my $orig_url = eval { + command_oneline(qw/config --get/, $k) + }; + if ($orig_url && ($orig_url ne $gs->{url})) { + die "$k already set: $orig_url\n", + "wanted to set to: $gs->{url}\n"; + } + unless ($orig_url) { + command_oneline('config', $k, $gs->{url}); + } $remote_id = $gs->{repo_id}; last; } @@ -751,13 +761,15 @@ sub fetch_all { } } - foreach my $p (sort keys %$fetch) { - my $gs = Git::SVN->new($fetch->{$p}, $repo_id, $p); - my $lr = $gs->rev_db_max; - if (defined $lr) { - $base = $lr if ($lr < $base); + if ($fetch) { + foreach my $p (sort keys %$fetch) { + my $gs = Git::SVN->new($fetch->{$p}, $repo_id, $p); + my $lr = $gs->rev_db_max; + if (defined $lr) { + $base = $lr if ($lr < $base); + } + push @gs, $gs; } - push @gs, $gs; } $ra->gs_fetch_loop_common($base, $head, \@gs, \@globs); } @@ -974,35 +986,69 @@ sub svm { sub _set_svm_vars { my ($self, $ra) = @_; + return $ra if $self->svm; + + my @err = ( "useSvmProps set, but failed to read SVM properties\n", + "(svm:source, svm:mirror, svm:mirror) ", + "from the following URLs:\n" ); + sub read_svm_props { + my ($self, $props) = @_; + my $src = $props->{'svm:source'}; + my $mirror = $props->{'svm:mirror'}; + my $uuid = $props->{'svm:uuid'}; + return undef if (!$src || !$mirror || !$uuid); - return $ra if ($self->svm); - - # nope, make sure we're connected to the repository root: - if ($ra->{repos_root} ne $self->{url}) { - $ra = Git::SVN::Ra->new($ra->{repos_root}); - } - my $r = $ra->get_latest_revnum; - my ($props) = ($ra->get_dir('', $r))[2]; - if (my $src = $props->{'svm:source'}) { - my $section = "svn-remote.$self->{repo_id}"; + chomp($src, $mirror, $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{!$}{}; + $src =~ s{/?!$}{$mirror}; + $src =~ s{/+$}{}; # no trailing slashes please $src =~ s{(^[a-z\+]*://)[^/@]*@}{$1}; - tmp_config('--add', "$section.svm-source", $src); - my $uuid = $props->{'svm:uuid'}; - $uuid =~ m{^[0-9a-f\-]{30,}$} - or die "doesn't look right - svm:uuid is '$uuid'\n"; + 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; } - if ($ra->{repos_root} ne $self->{url}) { - $ra = Git::SVN::Ra->new($self->{url}); + + my $r = $ra->get_latest_revnum; + my $path = $self->{path}; + my @tried_a = ($path); + while (length $path) { + if ($self->read_svm_props(($ra->get_dir($path, $r))[2])) { + return $ra; + } + $path =~ s#/?[^/]+$## && push @tried_a, $path; } - $ra; + if ($self->read_svm_props(($ra->get_dir('', $r))[2])) { + return $ra; + } + + if ($ra->{repos_root} eq $self->{url}) { + die @err, map { " $self->{url}/$_\n" } @tried_a, "\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; + } + $ok = $self->read_svm_props(($ra->get_dir('', $r))[2]) unless $ok; + if (!$ok) { + die @err, map { " $self->{url}/$_\n" } @tried_a, "\n", + map { " $ra->{url}/$_\n" } @tried_b, "\n" + } + Git::SVN::Ra->new($self->{url}); } # this allows us to memoize our SVN::Ra UUID locally and avoid a @@ -1228,11 +1274,9 @@ sub do_git_commit { croak "$log_entry->{revision} = $c already exists! ", "Why are we refetching it?\n"; } - my $author = $log_entry->{author}; - my ($name, $email) = (defined $::users{$author} ? @{$::users{$author}} - : ($author, "$author\@".$self->ra->get_uuid)); - $ENV{GIT_AUTHOR_NAME} = $ENV{GIT_COMMITTER_NAME} = $name; - $ENV{GIT_AUTHOR_EMAIL} = $ENV{GIT_COMMITTER_EMAIL} = $email; + $ENV{GIT_AUTHOR_NAME} = $ENV{GIT_COMMITTER_NAME} = $log_entry->{name}; + $ENV{GIT_AUTHOR_EMAIL} = $ENV{GIT_COMMITTER_EMAIL} = + $log_entry->{email}; $ENV{GIT_AUTHOR_DATE} = $ENV{GIT_COMMITTER_DATE} = $log_entry->{date}; my $tree = $log_entry->{tree}; @@ -1522,8 +1566,10 @@ sub make_log_entry { close $un or croak $!; $log_entry{date} = parse_svn_date($log_entry{date}); - $log_entry{author} = check_author($log_entry{author}); $log_entry{log} .= "\n"; + my $author = $log_entry{author} = check_author($log_entry{author}); + my ($name, $email) = defined $::users{$author} ? @{$::users{$author}} + : ($author, undef); if (defined $headrev && $self->use_svm_props) { my ($uuid, $r) = $headrev =~ m{^([a-f\d\-]{30,}):(\d+)$}; if ($uuid ne $self->{svm}->{uuid}) { @@ -1535,10 +1581,14 @@ sub make_log_entry { $full_url .= "/$self->{path}" if length $self->{path}; $log_entry{metadata} = "$full_url\@$r $uuid"; $log_entry{svm_revision} = $r; + $email ||= "$author\@$uuid" } else { $log_entry{metadata} = $self->full_url . "\@$rev " . $self->ra->get_uuid; + $email ||= "$author\@" . $self->ra->get_uuid; } + $log_entry{name} = $name; + $log_entry{email} = $email; \%log_entry; } |