git-svn: support for funky branch and project names over HTTP(S)
SVN requires that paths be URI-escaped for HTTP(S) repositories. file:// and svn:// repositories do not need these rules. Additionally, accessing individual paths inside repositories (check_path() and get_log() do NOT require escapes to function and in fact it breaks things). Noticed-by: Michael J. Cohen <mjc@cruiseplanners.com> Signed-off-by: Eric Wong <normalperson@yhbt.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Eric Wong committed
Nov 11, 2007 at 23:37 UTC
f5530b8833bcaa423cd53d133d3de3fa0173fbf3
2 files changed
+62
-2
git-svn.perl
+22
-2
@@ -3068,6 +3068,25 @@ BEGIN {
3068
}
3069
}
3070
3071
+sub escape_uri_only {
3072
+ my ($uri) = @_;
3073
+ my @tmp;
3074
+ foreach (split m{/}, $uri) {
3075
+ s/([^\w.-])/sprintf("%%%02X",ord($1))/eg;
3076
+ push @tmp, $_;
3077
+ }
3078
+ join('/', @tmp);
3079
+}
3080
+
3081
+sub escape_url {
3082
+ my ($url) = @_;
3083
+ if ($url =~ m#^(https?)://([^/]+)(.*)$#) {
3084
+ my ($scheme, $domain, $uri) = ($1, $2, escape_uri_only($3));
3085
+ $url = "$scheme://$domain$uri";
3086
+ }
3087
+ $url;
3088
+}
3089
+
3090
sub new {
3091
my ($class, $url) = @_;
3092
$url =~ s!/+$!!;
@@ -3092,10 +3111,11 @@ sub new {
3111
]);
3112
my $config = SVN::Core::config_get_config($config_dir);
3113
$RA = undef;
3095
- my $self = SVN::Ra->new(url => $url, auth => $baton,
3114
+ my $self = SVN::Ra->new(url => escape_url($url), auth => $baton,
3115
config => $config,
3116
pool => SVN::Pool->new,
3117
auth_provider_callbacks => $callbacks);
3118
+ $self->{url} = $url;
3119
$self->{svn_path} = $url;
3120
$self->{repos_root} = $self->get_repos_root;
3121
$self->{svn_path} =~ s#^\Q$self->{repos_root}\E(/|$)##;
@@ -3203,7 +3223,7 @@ sub gs_do_switch {
3223
3224
my $full_url = $self->{url};
3225
my $old_url = $full_url;
3206
- $full_url .= "/$path" if length $path;
3226
+ $full_url .= '/' . escape_uri_only($path) if length $path;
3227
my ($ra, $reparented);
3228
if ($old_url ne $full_url) {
3229
if ($old_url !~ m#^svn(\+ssh)?://#) {
t/t9118-git-svn-funky-branch-names.sh
new
+40
@@ -0,0 +1,40 @@
1
+#!/bin/sh
2
+#
3
+# Copyright (c) 2007 Eric Wong
4
+#
5
+
6
+test_description='git-svn funky branch names'
7
+. ./lib-git-svn.sh
8
+
9
+test_expect_success 'setup svnrepo' "
10
+ mkdir project project/trunk project/branches project/tags &&
11
+ echo foo > project/trunk/foo &&
12
+ svn import -m '$test_description' project \"$svnrepo/pr ject\" &&
13
+ rm -rf project &&
14
+ svn cp -m 'fun' \"$svnrepo/pr ject/trunk\" \
15
+ \"$svnrepo/pr ject/branches/fun plugin\" &&
16
+ svn cp -m 'more fun!' \"$svnrepo/pr ject/branches/fun plugin\" \
17
+ \"$svnrepo/pr ject/branches/more fun plugin!\" &&
18
+ start_httpd
19
+ "
20
+
21
+test_expect_success 'test clone with funky branch names' "
22
+ git svn clone -s \"$svnrepo/pr ject\" project &&
23
+ cd project &&
24
+ git rev-parse 'refs/remotes/fun%20plugin' &&
25
+ git rev-parse 'refs/remotes/more%20fun%20plugin!' &&
26
+ cd ..
27
+ "
28
+
29
+test_expect_success 'test dcommit to funky branch' "
30
+ cd project &&
31
+ git reset --hard 'refs/remotes/more%20fun%20plugin!' &&
32
+ echo hello >> foo &&
33
+ git commit -m 'hello' -- foo &&
34
+ git svn dcommit &&
35
+ cd ..
36
+ "
37
+
38
+stop_httpd
39
+
40
+test_done