aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--perl/Git/SVN.pm4
-rw-r--r--perl/Git/SVN/Utils.pm19
-rw-r--r--t/Git-SVN/Utils/canonicalize_url.t26
-rwxr-xr-xt/t9107-git-svn-migrate.sh4
4 files changed, 48 insertions, 5 deletions
diff --git a/perl/Git/SVN.pm b/perl/Git/SVN.pm
index dacac7fb4..a2e7144b4 100644
--- a/perl/Git/SVN.pm
+++ b/perl/Git/SVN.pm
@@ -201,9 +201,9 @@ sub read_all_remotes {
} elsif (m!^(.+)\.usesvmprops=\s*(.*)\s*$!) {
$r->{$1}->{svm} = {};
} elsif (m!^(.+)\.url=\s*(.*)\s*$!) {
- $r->{$1}->{url} = $2;
+ $r->{$1}->{url} = canonicalize_url($2);
} elsif (m!^(.+)\.pushurl=\s*(.*)\s*$!) {
- $r->{$1}->{pushurl} = $2;
+ $r->{$1}->{pushurl} = canonicalize_url($2);
} elsif (m!^(.+)\.ignore-refs=\s*(.*)\s*$!) {
$r->{$1}->{ignore_refs_regex} = $2;
} elsif (m!^(.+)\.(branches|tags)=$svn_refspec$!) {
diff --git a/perl/Git/SVN/Utils.pm b/perl/Git/SVN/Utils.pm
index f0b1b53a3..ab7add5e8 100644
--- a/perl/Git/SVN/Utils.pm
+++ b/perl/Git/SVN/Utils.pm
@@ -150,10 +150,25 @@ sub canonicalize_url {
}
+sub _canonicalize_url_path {
+ my ($uri_path) = @_;
+
+ my @parts;
+ foreach my $part (split m{/+}, $uri_path) {
+ $part =~ s/([^~\w.%+-]|%(?![a-fA-F0-9]{2}))/sprintf("%%%02X",ord($1))/eg;
+ push @parts, $part;
+ }
+
+ return join('/', @parts);
+}
+
sub _canonicalize_url_ourselves {
my ($url) = @_;
- $url =~ s#^([^:]+://[^/]*/)(.*)$#$1 . canonicalize_path($2)#e;
- return $url;
+ if ($url =~ m#^([^:]+)://([^/]*)(.*)$#) {
+ my ($scheme, $domain, $uri) = ($1, $2, _canonicalize_url_path(canonicalize_path($3)));
+ $url = "$scheme://$domain$uri";
+ }
+ $url;
}
diff --git a/t/Git-SVN/Utils/canonicalize_url.t b/t/Git-SVN/Utils/canonicalize_url.t
new file mode 100644
index 000000000..05795ab63
--- /dev/null
+++ b/t/Git-SVN/Utils/canonicalize_url.t
@@ -0,0 +1,26 @@
+#!/usr/bin/env perl
+
+# Test our own home rolled URL canonicalizer. Test the private one
+# directly because we can't predict what the SVN API is doing to do.
+
+use strict;
+use warnings;
+
+use Test::More 'no_plan';
+
+use Git::SVN::Utils;
+my $canonicalize_url = \&Git::SVN::Utils::_canonicalize_url_ourselves;
+
+my %tests = (
+ "http://x.com" => "http://x.com",
+ "http://x.com/" => "http://x.com",
+ "http://x.com/foo/bar" => "http://x.com/foo/bar",
+ "http://x.com//foo//bar//" => "http://x.com/foo/bar",
+ "http://x.com/ /%/" => "http://x.com/%20%20/%25",
+);
+
+for my $arg (keys %tests) {
+ my $want = $tests{$arg};
+
+ is $canonicalize_url->($arg), $want, "canonicalize_url('$arg') => $want";
+}
diff --git a/t/t9107-git-svn-migrate.sh b/t/t9107-git-svn-migrate.sh
index cfb4453ca..ee73013ee 100755
--- a/t/t9107-git-svn-migrate.sh
+++ b/t/t9107-git-svn-migrate.sh
@@ -27,6 +27,8 @@ test_expect_success 'setup old-looking metadata' '
head=`git rev-parse --verify refs/heads/git-svn-HEAD^0`
test_expect_success 'git-svn-HEAD is a real HEAD' "test -n '$head'"
+svnrepo_escaped=`echo $svnrepo | sed 's/ /%20/'`
+
test_expect_success 'initialize old-style (v0) git svn layout' '
mkdir -p "$GIT_DIR"/git-svn/info "$GIT_DIR"/svn/info &&
echo "$svnrepo" > "$GIT_DIR"/git-svn/info/url &&
@@ -35,7 +37,7 @@ test_expect_success 'initialize old-style (v0) git svn layout' '
! test -d "$GIT_DIR"/git-svn &&
git rev-parse --verify refs/${remotes_git_svn}^0 &&
git rev-parse --verify refs/remotes/svn^0 &&
- test "$(git config --get svn-remote.svn.url)" = "$svnrepo" &&
+ test "$(git config --get svn-remote.svn.url)" = "$svnrepo_escaped" &&
test `git config --get svn-remote.svn.fetch` = \
":refs/${remotes_git_svn}"
'