git-svn: Always duplicate paths returned from get_log
This makes get_log more safe to use because callers cannot run into path clobbering any more. The additional overhead will not affect performance since the critical calls from the fetch loop need the path duplication anyway and the rest of the call sites is not performance critical. Signed-off-by: Mattias Nissler <mattias.nissler@gmx.de> Acked-by: Eric Wong <normalperson@yhbt.net>
Mattias Nissler committed
Jul 7, 2009 at 01:39 UTC
3c49a03524b686c7b575e0a667736217e5445447
1 file changed
+23
-22
git-svn.perl
+23
-22
@@ -2538,9 +2538,8 @@ sub find_parent_branch {
2538
unless (defined $paths) {
2539
my $err_handler = $SVN::Error::handler;
2540
$SVN::Error::handler = \&Git::SVN::Ra::skip_unknown_revs;
2541
- $self->ra->get_log([$self->{path}], $rev, $rev, 0, 1, 1, sub {
2542
- $paths =
2543
- Git::SVN::Ra::dup_changed_paths($_[0]) });
2541
+ $self->ra->get_log([$self->{path}], $rev, $rev, 0, 1, 1,
2542
+ sub { $paths = $_[0] });
2543
$SVN::Error::handler = $err_handler;
2544
}
2545
return undef unless defined $paths;
@@ -4431,6 +4430,26 @@ sub get_log {
4430
my ($self, @args) = @_;
4431
my $pool = SVN::Pool->new;
4432
4433
+ # svn_log_changed_path_t objects passed to get_log are likely to be
4434
+ # overwritten even if only the refs are copied to an external variable,
4435
+ # so we should dup the structures in their entirety. Using an
4436
+ # externally passed pool (instead of our temporary and quickly cleared
4437
+ # pool in Git::SVN::Ra) does not help matters at all...
4438
+ my $receiver = pop @args;
4439
+ push(@args, sub {
4440
+ my ($paths) = $_[0];
4441
+ return &$receiver(@_) unless $paths;
4442
+ $_[0] = ();
4443
+ foreach my $p (keys %$paths) {
4444
+ my $i = $paths->{$p};
4445
+ my %s = map { $_ => $i->$_ }
4446
+ qw/copyfrom_path copyfrom_rev action/;
4447
+ $_[0]{$p} = \%s;
4448
+ }
4449
+ &$receiver(@_);
4450
+ });
4451
+
4452
+
4453
# the limit parameter was not supported in SVN 1.1.x, so we
4454
# drop it. Therefore, the receiver callback passed to it
4455
# is made aware of this limitation by being wrapped if
@@ -4600,7 +4619,7 @@ sub gs_fetch_loop_common {
4619
};
4620
sub _cb {
4621
my ($paths, $r, $author, $date, $log) = @_;
4603
- [ dup_changed_paths($paths),
4622
+ [ $paths,
4623
{ author => $author, date => $date, log => $log } ];
4624
}
4625
$self->get_log([$longest_path], $min, $max, 0, 1, 1,
@@ -4823,24 +4842,6 @@ sub skip_unknown_revs {
4842
die "Error from SVN, ($errno): ", $err->expanded_message,"\n";
4843
}
4844
4826
-# svn_log_changed_path_t objects passed to get_log are likely to be
4827
-# overwritten even if only the refs are copied to an external variable,
4828
-# so we should dup the structures in their entirety. Using an externally
4829
-# passed pool (instead of our temporary and quickly cleared pool in
4830
-# Git::SVN::Ra) does not help matters at all...
4831
-sub dup_changed_paths {
4832
- my ($paths) = @_;
4833
- return undef unless $paths;
4834
- my %ret;
4835
- foreach my $p (keys %$paths) {
4836
- my $i = $paths->{$p};
4837
- my %s = map { $_ => $i->$_ }
4838
- qw/copyfrom_path copyfrom_rev action/;
4839
- $ret{$p} = \%s;
4840
- }
4841
- \%ret;
4842
-}
4843
-
4845
package Git::SVN::Log;
4846
use strict;
4847
use warnings;