git svn: info: correctly handle absolute path args

Calling "git svn info $(pwd)" would hit:
  "Reading from filehandle failed at ..."
errors due to improper prefixing and canonicalization.

Strip the toplevel path from absolute filesystem paths to ensure
downstream canonicalization routines are only exposed to paths
tracked in git (or SVN).

v2:
  Thanks to Andrej Manduch for originally noticing the issue
  and fixing my original version of this to handle
  more corner cases such as "/path/to/top/../top" and
  "/path/to/top/../top/file" as shown in the new test cases.

v3:
  Fix pathname portability problems pointed out by Johannes Sixt
  with a hint from brian m. carlson.

Cc: Johannes Sixt <j6t@kdbg.org>
Cc: "brian m. carlson" <sandals@crustytoothpaste.net>
Signed-off-by: Andrej Manduch <amanduch@gmail.com>
Signed-off-by: Eric Wong <normalperson@yhbt.net>
This commit is contained in:
Eric Wong 2014-08-03 01:44:08 +00:00
parent 785a1c8258
commit 4950eed520
2 changed files with 63 additions and 6 deletions

View File

@ -1477,10 +1477,37 @@ sub cmd_commit_diff {
}
}
sub cmd_info {
my $path = canonicalize_path(defined($_[0]) ? $_[0] : ".");
my $fullpath = canonicalize_path($cmd_dir_prefix . $path);
my $path_arg = defined($_[0]) ? $_[0] : '.';
my $path = $path_arg;
if (File::Spec->file_name_is_absolute($path)) {
$path = canonicalize_path($path);
my $toplevel = eval {
my @cmd = qw/rev-parse --show-toplevel/;
command_oneline(\@cmd, STDERR => 0);
};
# remove $toplevel from the absolute path:
my ($vol, $dirs, $file) = File::Spec->splitpath($path);
my (undef, $tdirs, $tfile) = File::Spec->splitpath($toplevel);
my @dirs = File::Spec->splitdir($dirs);
my @tdirs = File::Spec->splitdir($tdirs);
pop @dirs if $dirs[-1] eq '';
pop @tdirs if $tdirs[-1] eq '';
push @dirs, $file;
push @tdirs, $tfile;
while (@tdirs && @dirs && $tdirs[0] eq $dirs[0]) {
shift @dirs;
shift @tdirs;
}
$dirs = File::Spec->catdir(@dirs);
$path = File::Spec->catpath($vol, $dirs);
$path = canonicalize_path($path);
} else {
$path = canonicalize_path($cmd_dir_prefix . $path);
}
if (exists $_[1]) {
die "Too many arguments specified\n";
}
@ -1501,14 +1528,14 @@ sub cmd_info {
# canonicalize_path() will return "" to make libsvn 1.5.x happy,
$path = "." if $path eq "";
my $full_url = canonicalize_url( add_path_to_url( $url, $fullpath ) );
my $full_url = canonicalize_url( add_path_to_url( $url, $path ) );
if ($_url) {
print "$full_url\n";
return;
}
my $result = "Path: $path\n";
my $result = "Path: $path_arg\n";
$result .= "Name: " . basename($path) . "\n" if $file_type ne "dir";
$result .= "URL: $full_url\n";
@ -1539,7 +1566,7 @@ sub cmd_info {
}
my ($lc_author, $lc_rev, $lc_date_utc);
my @args = Git::SVN::Log::git_svn_log_cmd($rev, $rev, "--", $fullpath);
my @args = Git::SVN::Log::git_svn_log_cmd($rev, $rev, "--", $path);
my $log = command_output_pipe(@args);
my $esc_color = qr/(?:\033\[(?:(?:\d+;)*\d*)?m)*/;
while (<$log>) {

View File

@ -74,6 +74,36 @@ test_expect_success 'info .' "
test_cmp_info expected.info-dot actual.info-dot
"
test_expect_success 'info $(pwd)' '
(cd svnwc; svn info "$(pwd)") >expected.info-pwd &&
(cd gitwc; git svn info "$(pwd)") >actual.info-pwd &&
grep -v ^Path: <expected.info-pwd >expected.info-np &&
grep -v ^Path: <actual.info-pwd >actual.info-np &&
test_cmp_info expected.info-np actual.info-np &&
test "$(sed -ne \"/^Path:/ s!/svnwc!!\" <expected.info-pwd)" = \
"$(sed -ne \"/^Path:/ s!/gitwc!!\" <actual.info-pwd)"
'
test_expect_success 'info $(pwd)/../___wc' '
(cd svnwc; svn info "$(pwd)/../svnwc") >expected.info-pwd &&
(cd gitwc; git svn info "$(pwd)/../gitwc") >actual.info-pwd &&
grep -v ^Path: <expected.info-pwd >expected.info-np &&
grep -v ^Path: <actual.info-pwd >actual.info-np &&
test_cmp_info expected.info-np actual.info-np &&
test "$(sed -ne \"/^Path:/ s!/svnwc!!\" <expected.info-pwd)" = \
"$(sed -ne \"/^Path:/ s!/gitwc!!\" <actual.info-pwd)"
'
test_expect_success 'info $(pwd)/../___wc//file' '
(cd svnwc; svn info "$(pwd)/../svnwc//file") >expected.info-pwd &&
(cd gitwc; git svn info "$(pwd)/../gitwc//file") >actual.info-pwd &&
grep -v ^Path: <expected.info-pwd >expected.info-np &&
grep -v ^Path: <actual.info-pwd >actual.info-np &&
test_cmp_info expected.info-np actual.info-np &&
test "$(sed -ne \"/^Path:/ s!/svnwc!!\" <expected.info-pwd)" = \
"$(sed -ne \"/^Path:/ s!/gitwc!!\" <actual.info-pwd)"
'
test_expect_success 'info --url .' '
test "$(cd gitwc; git svn info --url .)" = "$quoted_svnrepo"
'