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>maint
							parent
							
								
									a4e57e75c9
								
							
						
					
					
						commit
						cfbe7ab333
					
				
							
								
								
									
										24
									
								
								git-svn.perl
								
								
								
								
							
							
						
						
									
										24
									
								
								git-svn.perl
								
								
								
								
							|  | @ -3223,6 +3223,25 @@ sub _auth_providers () { | ||||||
| 	] | 	] | ||||||
| } | } | ||||||
|  |  | ||||||
|  | sub escape_uri_only { | ||||||
|  | 	my ($uri) = @_; | ||||||
|  | 	my @tmp; | ||||||
|  | 	foreach (split m{/}, $uri) { | ||||||
|  | 		s/([^\w.-])/sprintf("%%%02X",ord($1))/eg; | ||||||
|  | 		push @tmp, $_; | ||||||
|  | 	} | ||||||
|  | 	join('/', @tmp); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | sub escape_url { | ||||||
|  | 	my ($url) = @_; | ||||||
|  | 	if ($url =~ m#^(https?)://([^/]+)(.*)$#) { | ||||||
|  | 		my ($scheme, $domain, $uri) = ($1, $2, escape_uri_only($3)); | ||||||
|  | 		$url = "$scheme://$domain$uri"; | ||||||
|  | 	} | ||||||
|  | 	$url; | ||||||
|  | } | ||||||
|  |  | ||||||
| sub new { | sub new { | ||||||
| 	my ($class, $url) = @_; | 	my ($class, $url) = @_; | ||||||
| 	$url =~ s!/+$!!; | 	$url =~ s!/+$!!; | ||||||
|  | @ -3255,10 +3274,11 @@ sub new { | ||||||
| 			$Git::SVN::Prompt::_no_auth_cache = 1; | 			$Git::SVN::Prompt::_no_auth_cache = 1; | ||||||
| 		} | 		} | ||||||
| 	} # no warnings 'once' | 	} # no warnings 'once' | ||||||
| 	my $self = SVN::Ra->new(url => $url, auth => $baton, | 	my $self = SVN::Ra->new(url => escape_url($url), auth => $baton, | ||||||
| 	                      config => $config, | 	                      config => $config, | ||||||
| 			      pool => SVN::Pool->new, | 			      pool => SVN::Pool->new, | ||||||
| 	                      auth_provider_callbacks => $callbacks); | 	                      auth_provider_callbacks => $callbacks); | ||||||
|  | 	$self->{url} = $url; | ||||||
| 	$self->{svn_path} = $url; | 	$self->{svn_path} = $url; | ||||||
| 	$self->{repos_root} = $self->get_repos_root; | 	$self->{repos_root} = $self->get_repos_root; | ||||||
| 	$self->{svn_path} =~ s#^\Q$self->{repos_root}\E(/|$)##; | 	$self->{svn_path} =~ s#^\Q$self->{repos_root}\E(/|$)##; | ||||||
|  | @ -3384,7 +3404,7 @@ sub gs_do_switch { | ||||||
|  |  | ||||||
| 	my $full_url = $self->{url}; | 	my $full_url = $self->{url}; | ||||||
| 	my $old_url = $full_url; | 	my $old_url = $full_url; | ||||||
| 	$full_url .= "/$path" if length $path; | 	$full_url .= '/' . escape_uri_only($path) if length $path; | ||||||
| 	my ($ra, $reparented); | 	my ($ra, $reparented); | ||||||
| 	if ($old_url ne $full_url) { | 	if ($old_url ne $full_url) { | ||||||
| 		if ($old_url !~ m#^svn(\+ssh)?://#) { | 		if ($old_url !~ m#^svn(\+ssh)?://#) { | ||||||
|  |  | ||||||
|  | @ -0,0 +1,40 @@ | ||||||
|  | #!/bin/sh | ||||||
|  | # | ||||||
|  | # Copyright (c) 2007 Eric Wong | ||||||
|  | # | ||||||
|  |  | ||||||
|  | test_description='git-svn funky branch names' | ||||||
|  | . ./lib-git-svn.sh | ||||||
|  |  | ||||||
|  | test_expect_success 'setup svnrepo' " | ||||||
|  | 	mkdir project project/trunk project/branches project/tags && | ||||||
|  | 	echo foo > project/trunk/foo && | ||||||
|  | 	svn import -m '$test_description' project \"$svnrepo/pr ject\" && | ||||||
|  | 	rm -rf project && | ||||||
|  | 	svn cp -m 'fun' \"$svnrepo/pr ject/trunk\" \ | ||||||
|  | 	                \"$svnrepo/pr ject/branches/fun plugin\" && | ||||||
|  | 	svn cp -m 'more fun!' \"$svnrepo/pr ject/branches/fun plugin\" \ | ||||||
|  | 	                      \"$svnrepo/pr ject/branches/more fun plugin!\" && | ||||||
|  | 	start_httpd | ||||||
|  | 	" | ||||||
|  |  | ||||||
|  | test_expect_success 'test clone with funky branch names' " | ||||||
|  | 	git svn clone -s \"$svnrepo/pr ject\" project && | ||||||
|  | 	cd project && | ||||||
|  | 		git rev-parse 'refs/remotes/fun%20plugin' && | ||||||
|  | 		git rev-parse 'refs/remotes/more%20fun%20plugin!' && | ||||||
|  | 	cd .. | ||||||
|  | 	" | ||||||
|  |  | ||||||
|  | test_expect_success 'test dcommit to funky branch' " | ||||||
|  | 	cd project && | ||||||
|  | 	git reset --hard 'refs/remotes/more%20fun%20plugin!' && | ||||||
|  | 	echo hello >> foo && | ||||||
|  | 	git commit -m 'hello' -- foo && | ||||||
|  | 	git svn dcommit && | ||||||
|  | 	cd .. | ||||||
|  | 	" | ||||||
|  |  | ||||||
|  | stop_httpd | ||||||
|  |  | ||||||
|  | test_done | ||||||
		Loading…
	
		Reference in New Issue
	
	 Eric Wong
						Eric Wong