Skip to content

Commit 93c3fcb

Browse files
schwernEric Wong
authored andcommitted
git-svn: attempt to mimic SVN 1.7 URL canonicalization
Previously, our URL canonicalization didn't do much of anything. Now it actually escapes and collapses slashes. This is mostly a cut & paste of escape_url from git-svn. This is closer to how SVN 1.7's canonicalization behaves. Doing it with 1.6 lets us chase down some problems caused by more effective canonicalization without having to deal with all the other 1.7 issues on top of that. * Remote URLs have to be canonicalized otherwise Git::SVN->find_existing_remote will think they're different. * The SVN remote is now written to the git config canonicalized. That should be ok. Adjust a test to account for that. [ew: commit title] Signed-off-by: Eric Wong <normalperson@yhbt.net>
1 parent 1a35da0 commit 93c3fcb

File tree

4 files changed

+48
-5
lines changed

4 files changed

+48
-5
lines changed

perl/Git/SVN.pm

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,9 +201,9 @@ sub read_all_remotes {
201201
} elsif (m!^(.+)\.usesvmprops=\s*(.*)\s*$!) {
202202
$r->{$1}->{svm} = {};
203203
} elsif (m!^(.+)\.url=\s*(.*)\s*$!) {
204-
$r->{$1}->{url} = $2;
204+
$r->{$1}->{url} = canonicalize_url($2);
205205
} elsif (m!^(.+)\.pushurl=\s*(.*)\s*$!) {
206-
$r->{$1}->{pushurl} = $2;
206+
$r->{$1}->{pushurl} = canonicalize_url($2);
207207
} elsif (m!^(.+)\.ignore-refs=\s*(.*)\s*$!) {
208208
$r->{$1}->{ignore_refs_regex} = $2;
209209
} elsif (m!^(.+)\.(branches|tags)=$svn_refspec$!) {

perl/Git/SVN/Utils.pm

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,10 +150,25 @@ sub canonicalize_url {
150150
}
151151

152152

153+
sub _canonicalize_url_path {
154+
my ($uri_path) = @_;
155+
156+
my @parts;
157+
foreach my $part (split m{/+}, $uri_path) {
158+
$part =~ s/([^~\w.%+-]|%(?![a-fA-F0-9]{2}))/sprintf("%%%02X",ord($1))/eg;
159+
push @parts, $part;
160+
}
161+
162+
return join('/', @parts);
163+
}
164+
153165
sub _canonicalize_url_ourselves {
154166
my ($url) = @_;
155-
$url =~ s#^([^:]+://[^/]*/)(.*)$#$1 . canonicalize_path($2)#e;
156-
return $url;
167+
if ($url =~ m#^([^:]+)://([^/]*)(.*)$#) {
168+
my ($scheme, $domain, $uri) = ($1, $2, _canonicalize_url_path(canonicalize_path($3)));
169+
$url = "$scheme://$domain$uri";
170+
}
171+
$url;
157172
}
158173

159174

t/Git-SVN/Utils/canonicalize_url.t

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#!/usr/bin/env perl
2+
3+
# Test our own home rolled URL canonicalizer. Test the private one
4+
# directly because we can't predict what the SVN API is doing to do.
5+
6+
use strict;
7+
use warnings;
8+
9+
use Test::More 'no_plan';
10+
11+
use Git::SVN::Utils;
12+
my $canonicalize_url = \&Git::SVN::Utils::_canonicalize_url_ourselves;
13+
14+
my %tests = (
15+
"http://x.com" => "http://x.com",
16+
"http://x.com/" => "http://x.com",
17+
"http://x.com/foo/bar" => "http://x.com/foo/bar",
18+
"http://x.com//foo//bar//" => "http://x.com/foo/bar",
19+
"http://x.com/ /%/" => "http://x.com/%20%20/%25",
20+
);
21+
22+
for my $arg (keys %tests) {
23+
my $want = $tests{$arg};
24+
25+
is $canonicalize_url->($arg), $want, "canonicalize_url('$arg') => $want";
26+
}

t/t9107-git-svn-migrate.sh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ test_expect_success 'setup old-looking metadata' '
2727
head=`git rev-parse --verify refs/heads/git-svn-HEAD^0`
2828
test_expect_success 'git-svn-HEAD is a real HEAD' "test -n '$head'"
2929

30+
svnrepo_escaped=`echo $svnrepo | sed 's/ /%20/'`
31+
3032
test_expect_success 'initialize old-style (v0) git svn layout' '
3133
mkdir -p "$GIT_DIR"/git-svn/info "$GIT_DIR"/svn/info &&
3234
echo "$svnrepo" > "$GIT_DIR"/git-svn/info/url &&
@@ -35,7 +37,7 @@ test_expect_success 'initialize old-style (v0) git svn layout' '
3537
! test -d "$GIT_DIR"/git-svn &&
3638
git rev-parse --verify refs/${remotes_git_svn}^0 &&
3739
git rev-parse --verify refs/remotes/svn^0 &&
38-
test "$(git config --get svn-remote.svn.url)" = "$svnrepo" &&
40+
test "$(git config --get svn-remote.svn.url)" = "$svnrepo_escaped" &&
3941
test `git config --get svn-remote.svn.fetch` = \
4042
":refs/${remotes_git_svn}"
4143
'

0 commit comments

Comments
 (0)