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>
This commit is contained in:
Michael G. Schwern 2012-07-28 02:47:47 -07:00 committed by Eric Wong
parent 1a35da0b5d
commit 93c3fcbe4d
4 changed files with 48 additions and 5 deletions

View File

@ -201,9 +201,9 @@ sub read_all_remotes {
} elsif (m!^(.+)\.usesvmprops=\s*(.*)\s*$!) { } elsif (m!^(.+)\.usesvmprops=\s*(.*)\s*$!) {
$r->{$1}->{svm} = {}; $r->{$1}->{svm} = {};
} elsif (m!^(.+)\.url=\s*(.*)\s*$!) { } elsif (m!^(.+)\.url=\s*(.*)\s*$!) {
$r->{$1}->{url} = $2; $r->{$1}->{url} = canonicalize_url($2);
} elsif (m!^(.+)\.pushurl=\s*(.*)\s*$!) { } elsif (m!^(.+)\.pushurl=\s*(.*)\s*$!) {
$r->{$1}->{pushurl} = $2; $r->{$1}->{pushurl} = canonicalize_url($2);
} elsif (m!^(.+)\.ignore-refs=\s*(.*)\s*$!) { } elsif (m!^(.+)\.ignore-refs=\s*(.*)\s*$!) {
$r->{$1}->{ignore_refs_regex} = $2; $r->{$1}->{ignore_refs_regex} = $2;
} elsif (m!^(.+)\.(branches|tags)=$svn_refspec$!) { } elsif (m!^(.+)\.(branches|tags)=$svn_refspec$!) {

View File

@ -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 { sub _canonicalize_url_ourselves {
my ($url) = @_; my ($url) = @_;
$url =~ s#^([^:]+://[^/]*/)(.*)$#$1 . canonicalize_path($2)#e; if ($url =~ m#^([^:]+)://([^/]*)(.*)$#) {
return $url; my ($scheme, $domain, $uri) = ($1, $2, _canonicalize_url_path(canonicalize_path($3)));
$url = "$scheme://$domain$uri";
}
$url;
} }

View File

@ -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";
}

View File

@ -27,6 +27,8 @@ test_expect_success 'setup old-looking metadata' '
head=`git rev-parse --verify refs/heads/git-svn-HEAD^0` head=`git rev-parse --verify refs/heads/git-svn-HEAD^0`
test_expect_success 'git-svn-HEAD is a real HEAD' "test -n '$head'" 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' ' test_expect_success 'initialize old-style (v0) git svn layout' '
mkdir -p "$GIT_DIR"/git-svn/info "$GIT_DIR"/svn/info && mkdir -p "$GIT_DIR"/git-svn/info "$GIT_DIR"/svn/info &&
echo "$svnrepo" > "$GIT_DIR"/git-svn/info/url && 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 && ! test -d "$GIT_DIR"/git-svn &&
git rev-parse --verify refs/${remotes_git_svn}^0 && git rev-parse --verify refs/${remotes_git_svn}^0 &&
git rev-parse --verify refs/remotes/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` = \ test `git config --get svn-remote.svn.fetch` = \
":refs/${remotes_git_svn}" ":refs/${remotes_git_svn}"
' '