Browse Source

git-svn: add join_paths() to safely concatenate paths

Otherwise you might wind up with things like...

    my $path1 = undef;
    my $path2 = 'foo';
    my $path = $path1 . '/' . $path2;

creating '/foo'.  Or this...

    my $path1 = 'foo/';
    my $path2 = 'bar';
    my $path = $path1 . '/' . $path2;

creating 'foo//bar'.

Could have used File::Spec, but I'm shying away from it due to SVN
1.7's pickiness about paths.  Felt it would be better to have our own
we can control completely.

[ew: commit title]

Signed-off-by: Eric Wong <normalperson@yhbt.net>
maint
Michael G. Schwern 12 years ago committed by Eric Wong
parent
commit
ca475a61f8
  1. 3
      git-svn.perl
  2. 10
      perl/Git/SVN.pm
  3. 32
      perl/Git/SVN/Utils.pm
  4. 32
      t/Git-SVN/Utils/join_paths.t

3
git-svn.perl

@ -34,6 +34,7 @@ use Git::SVN::Utils qw( @@ -34,6 +34,7 @@ use Git::SVN::Utils qw(
can_compress
canonicalize_path
canonicalize_url
join_paths
);

use Git qw(
@ -1275,7 +1276,7 @@ sub get_svnprops { @@ -1275,7 +1276,7 @@ sub get_svnprops {
$path = $cmd_dir_prefix . $path;
fatal("No such file or directory: $path") unless -e $path;
my $is_dir = -d $path ? 1 : 0;
$path = $gs->{path} . '/' . $path;
$path = join_paths($gs->{path}, $path);

# canonicalize the path (otherwise libsvn will abort or fail to
# find the file)

10
perl/Git/SVN.pm

@ -23,7 +23,11 @@ use Git qw( @@ -23,7 +23,11 @@ use Git qw(
command_output_pipe
command_close_pipe
);
use Git::SVN::Utils qw(fatal can_compress);
use Git::SVN::Utils qw(
fatal
can_compress
join_paths
);

my $can_use_yaml;
BEGIN {
@ -316,9 +320,7 @@ sub init_remote_config { @@ -316,9 +320,7 @@ sub init_remote_config {
}
my $old_path = $self->path;
$url =~ s!^\Q$min_url\E(/|$)!!;
if (length $old_path) {
$url .= "/$old_path";
}
$url = join_paths($url, $old_path);
$self->path($url);
$url = $min_url;
}

32
perl/Git/SVN/Utils.pm

@ -12,6 +12,7 @@ our @EXPORT_OK = qw( @@ -12,6 +12,7 @@ our @EXPORT_OK = qw(
can_compress
canonicalize_path
canonicalize_url
join_paths
);


@ -134,4 +135,35 @@ sub _canonicalize_url_ourselves { @@ -134,4 +135,35 @@ sub _canonicalize_url_ourselves {
}


=head3 join_paths

my $new_path = join_paths(@paths);

Appends @paths together into a single path. Any empty paths are ignored.

=cut

sub join_paths {
my @paths = @_;

@paths = grep { defined $_ && length $_ } @paths;

return '' unless @paths;
return $paths[0] if @paths == 1;

my $new_path = shift @paths;
$new_path =~ s{/+$}{};

my $last_path = pop @paths;
$last_path =~ s{^/+}{};

for my $path (@paths) {
$path =~ s{^/+}{};
$path =~ s{/+$}{};
$new_path .= "/$path";
}

return $new_path .= "/$last_path";
}

1;

32
t/Git-SVN/Utils/join_paths.t

@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
#!/usr/bin/env perl

use strict;
use warnings;

use Test::More 'no_plan';

use Git::SVN::Utils qw(
join_paths
);

# A reference cannot be a hash key, so we use an array.
my @tests = (
[] => '',
["/x.com", "bar"] => '/x.com/bar',
["x.com", ""] => 'x.com',
["/x.com/foo/", undef, "bar"] => '/x.com/foo/bar',
["x.com/foo/", "/bar/baz/"] => 'x.com/foo/bar/baz/',
["foo", "bar"] => 'foo/bar',
["/foo/bar", "baz", "/biff"] => '/foo/bar/baz/biff',
["", undef, "."] => '.',
[] => '',

);

while(@tests) {
my($have, $want) = splice @tests, 0, 2;

my $args = join ", ", map { qq['$_'] } map { defined($_) ? $_ : 'undef' } @$have;
my $name = "join_paths($args) eq '$want'";
is join_paths(@$have), $want, $name;
}
Loading…
Cancel
Save