]> Pileus Git - ~andy/git/commitdiff
git-svn: attempt to mimic SVN 1.7 URL canonicalization
authorMichael G. Schwern <schwern@pobox.com>
Sat, 28 Jul 2012 09:47:47 +0000 (02:47 -0700)
committerEric Wong <normalperson@yhbt.net>
Thu, 2 Aug 2012 21:46:00 +0000 (21:46 +0000)
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>
perl/Git/SVN.pm
perl/Git/SVN/Utils.pm
t/Git-SVN/Utils/canonicalize_url.t [new file with mode: 0644]
t/t9107-git-svn-migrate.sh

index dacac7fb463c4d5fb9a835f798f6dac01042ef18..a2e7144b4ccc1d772c13102f7727f740a3c69e85 100644 (file)
@@ -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$!) {
index f0b1b53a3ff98d044db98fd3939cab6862e234c1..ab7add5e8b319ef8d9941956ed46d5bd68839905 100644 (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 {
        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 (file)
index 0000000..05795ab
--- /dev/null
@@ -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";
+}
index cfb4453ca5e34658486fd3deafc208d669ea07d3..ee73013eed0b1c6410319aa3d7e4e57ea242a594 100755 (executable)
@@ -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}"
        '