[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#692298: unblock: git/1:1.7.10.4-2



Package: release.debian.org
User: release.debian.org@packages.debian.org
Usertags: unblock

Hi,

Please unblock git/1:1.7.10.4-2 to get fixes to

  #678137 -- incompatibility with SVN 1.7

and

  #587650 -- "Byte order is not compatible at ../../lib/Storable.pm"
             errors when accessing git-svn repositories created with
             perl/squeeze

We might send more fixes later, but these are the two I most want not
to release without.

Thanks,
Jonathan
diff -u git-1.7.10.4/debian/changelog git-1.7.10.4/debian/changelog
--- git-1.7.10.4/debian/changelog
+++ git-1.7.10.4/debian/changelog
@@ -1,3 +1,25 @@
+git (1:1.7.10.4-2) unstable; urgency=low
+
+  * debian/diff:
+    * 0013...0030: new from the upstream 'master' branch: git svn:
+      adapt to svn 1.7 changes:
+      * normalize paths and URLs passed to Subversion (thx Michael G.
+        Schwern; closes: #678137)
+      * use correct "svn cp" syntax when checking git svn's mangling
+        of @-signs in branch names (svn became stricter).
+      * commit filetype changes between a regular file and symlink as
+        replacement (deletion followed by addition) instead of
+        modification of files.  Otherwise, clients pulling the change
+        with "svn update" hit an assertion failure (svn issue 4091).
+    * 0031-git-svn-use-YAML-format-...diff: new from 1.7.11: git svn:
+      use YAML format for mergeinfo cache when possible.
+  * debian/control: git-svn: Depends: libyaml-perl for platform- and
+    version-independent .git/svn/.caches format; Build-Depends:
+    libyaml-perl for tests (thx Tim Retout for the analysis; closes:
+    #587650).
+
+ -- Jonathan Nieder <jrnieder@gmail.com>  Fri, 12 Oct 2012 13:27:36 -0700
+
 git (1:1.7.10.4-1) unstable; urgency=low
 
   * new upstream point release (thx Jonathan Nieder).
diff -u git-1.7.10.4/debian/control git-1.7.10.4/debian/control
--- git-1.7.10.4/debian/control
+++ git-1.7.10.4/debian/control
@@ -5,7 +5,7 @@
 Uploaders: Jonathan Nieder <jrnieder@gmail.com>
 Build-Depends: libz-dev,
  libcurl4-gnutls-dev | libcurl3-gnutls-dev, libexpat1-dev,
- subversion, libsvn-perl | libsvn-core-perl,
+ subversion, libsvn-perl | libsvn-core-perl, libyaml-perl,
  tcl8.5, gettext,
  cvs, cvsps, libdbd-sqlite3-perl,
  unzip, libio-pty-perl,
@@ -147,7 +147,7 @@
 
 Package: git-svn
 Architecture: all
-Depends: git (>> ${source:Upstream-Version}), git (<< ${source:Upstream-Version}-.), libsvn-perl | libsvn-core-perl, libwww-perl, libterm-readkey-perl
+Depends: git (>> ${source:Upstream-Version}), git (<< ${source:Upstream-Version}-.), libsvn-perl | libsvn-core-perl, libyaml-perl, libwww-perl, libterm-readkey-perl
 Suggests: git-doc, subversion
 Replaces: cogito (<< 0.16rc2-0)
 Description: fast, scalable, distributed revision control system (svn interoperability)
only in patch2:
unchanged:
--- git-1.7.10.4.orig/debian/diff/0028-t9118-workaround-inconsistency-between-SVN-versions.diff
+++ git-1.7.10.4/debian/diff/0028-t9118-workaround-inconsistency-between-SVN-versions.diff
@@ -0,0 +1,46 @@
+From cb36ce89042a9aa04e5f2cdbbce16810c580991e Mon Sep 17 00:00:00 2001
+From: "Michael G. Schwern" <schwern@pobox.com>
+Date: Sat, 28 Jul 2012 02:47:45 -0700
+Subject: t9118: workaround inconsistency between SVN versions
+
+SVN 1.7 will truncate "not-a%40{0}" to just "not-a".
+
+Rather than guess what SVN is going to do for each version, make the test use
+the branch name that was actually created.
+
+[ew: commit title]
+
+Signed-off-by: Eric Wong <normalperson@yhbt.net>
+Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
+---
+ t/t9118-git-svn-funky-branch-names.sh |    7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/t/t9118-git-svn-funky-branch-names.sh b/t/t9118-git-svn-funky-branch-names.sh
+index 63fc982..193d3ca 100755
+--- a/t/t9118-git-svn-funky-branch-names.sh
++++ b/t/t9118-git-svn-funky-branch-names.sh
+@@ -32,6 +32,11 @@ test_expect_success 'setup svnrepo' '
+ 	start_httpd
+ 	'
+ 
++# SVN 1.7 will truncate "not-a%40{0]" to just "not-a".
++# Look at what SVN wound up naming the branch and use that.
++# Be sure to escape the @ if it shows up.
++non_reflog=`svn_cmd ls "$svnrepo/pr ject/branches" | grep not-a | sed 's/\///' | sed 's/@/%40/'`
++
+ test_expect_success 'test clone with funky branch names' '
+ 	git svn clone -s "$svnrepo/pr ject" project &&
+ 	(
+@@ -42,7 +47,7 @@ test_expect_success 'test clone with funky branch names' '
+ 		git rev-parse "refs/remotes/%2Eleading_dot" &&
+ 		git rev-parse "refs/remotes/trailing_dot%2E" &&
+ 		git rev-parse "refs/remotes/trailing_dotlock%2Elock" &&
+-		git rev-parse "refs/remotes/not-a%40{0}reflog"
++		git rev-parse "refs/remotes/$non_reflog"
+ 	)
+ 	'
+ 
+-- 
+1.7.10.4
+
only in patch2:
unchanged:
--- git-1.7.10.4.orig/debian/diff/0029-svn-test-escape-peg-revision-separator-using-empty-pe.diff
+++ git-1.7.10.4/debian/diff/0029-svn-test-escape-peg-revision-separator-using-empty-pe.diff
@@ -0,0 +1,60 @@
+From ed94bdaf04c932d088c25742b50576d5fbadfd2e Mon Sep 17 00:00:00 2001
+From: Jonathan Nieder <jrnieder@gmail.com>
+Date: Tue, 9 Oct 2012 01:41:45 -0700
+Subject: svn test: escape peg revision separator using empty peg rev
+
+This test script uses "svn cp" to create a branch with an @-sign in
+its name:
+
+	svn cp "pr ject/trunk" "pr ject/branches/not-a@{0}reflog"
+
+That sets up for later tests that fetch the branch and check that git
+svn mangles the refname appropriately.
+
+Unfortunately, modern svn versions interpret path arguments with an
+@-sign as an example of path@revision syntax (which pegs a path to a
+particular revision) and truncate the path or error out with message
+"svn: E205000: Syntax error parsing peg revision '{0}reflog'".
+
+When using subversion 1.6.x, escaping the @ sign as %40 avoids trouble
+(see 08fd28bb, 2010-07-08).  Newer versions are stricter:
+
+	$ svn cp "$repo/pr ject/trunk" "$repo/pr ject/branches/not-a%40{reflog}"
+	svn: E205000: Syntax error parsing peg revision '%7B0%7Dreflog'
+
+The recommended method for escaping a literal @ sign in a path passed
+to subversion is to add an empty peg revision at the end of the path
+("branches/not-a@{0}reflog@").  Do that.
+
+Pre-1.6.12 versions of Subversion probably treat the trailing @ as
+another literal @-sign (svn issue 3651).  Luckily ever since
+v1.8.0-rc0~155^2~7 (t9118: workaround inconsistency between SVN
+versions, 2012-07-28) the test can survive that.
+
+Tested with Debian Subversion 1.6.12dfsg-6 and 1.7.5-1 and r1395837
+of Subversion trunk (1.8.x).
+
+Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
+Tested-by: Michael J Gruber <git@drmicha.warpmail.net>
+Signed-off-by: Eric Wong <normalperson@yhbt.net>
+Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
+---
+ t/t9118-git-svn-funky-branch-names.sh |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/t/t9118-git-svn-funky-branch-names.sh b/t/t9118-git-svn-funky-branch-names.sh
+index 193d3ca..15f93b4 100755
+--- a/t/t9118-git-svn-funky-branch-names.sh
++++ b/t/t9118-git-svn-funky-branch-names.sh
+@@ -28,7 +28,7 @@ test_expect_success 'setup svnrepo' '
+ 	svn_cmd cp -m "trailing .lock" "$svnrepo/pr ject/trunk" \
+ 			"$svnrepo/pr ject/branches/trailing_dotlock.lock" &&
+ 	svn_cmd cp -m "reflog" "$svnrepo/pr ject/trunk" \
+-			"$svnrepo/pr ject/branches/not-a%40{0}reflog" &&
++			"$svnrepo/pr ject/branches/not-a@{0}reflog@" &&
+ 	start_httpd
+ 	'
+ 
+-- 
+1.7.10.4
+
only in patch2:
unchanged:
--- git-1.7.10.4.orig/debian/diff/0025-git-svn-canonicalize-earlier.diff
+++ git-1.7.10.4/debian/diff/0025-git-svn-canonicalize-earlier.diff
@@ -0,0 +1,61 @@
+From 566a4860db8bd4334e7fe4c1ffab1530f33afa8f Mon Sep 17 00:00:00 2001
+From: "Michael G. Schwern" <schwern@pobox.com>
+Date: Sat, 28 Jul 2012 02:47:49 -0700
+Subject: git-svn: canonicalize earlier
+
+Just a few things I noticed.  Its good to canonicalize as early as
+possible.
+
+[ew: commit title]
+
+Signed-off-by: Eric Wong <normalperson@yhbt.net>
+Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
+---
+ git-svn.perl |   10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/git-svn.perl b/git-svn.perl
+index ba006fc..b25f628 100755
+--- a/git-svn.perl
++++ b/git-svn.perl
+@@ -1531,16 +1531,16 @@ sub cmd_info {
+ 	# canonicalize_path() will return "" to make libsvn 1.5.x happy,
+ 	$path = "." if $path eq "";
+ 
+-	my $full_url = $url . ($fullpath eq "" ? "" : "/$fullpath");
++	my $full_url = canonicalize_url( $url . ($fullpath eq "" ? "" : "/$fullpath") );
+ 
+ 	if ($_url) {
+-		print canonicalize_url($full_url), "\n";
++		print "$full_url\n";
+ 		return;
+ 	}
+ 
+ 	my $result = "Path: $path\n";
+ 	$result .= "Name: " . basename($path) . "\n" if $file_type ne "dir";
+-	$result .= "URL: " . canonicalize_url($full_url) . "\n";
++	$result .= "URL: $full_url\n";
+ 
+ 	eval {
+ 		my $repos_root = $gs->repos_root;
+@@ -5581,7 +5581,7 @@ ()
+ 
+ sub new {
+ 	my ($class, $url) = @_;
+-	$url =~ s!/+$!!;
++	$url = ::canonicalize_url($url);
+ 	return $RA if ($RA && $RA->url eq $url);
+ 
+ 	::_req_svn();
+@@ -5613,7 +5613,7 @@ sub new {
+ 			$Git::SVN::Prompt::_no_auth_cache = 1;
+ 		}
+ 	} # no warnings 'once'
+-	my $self = SVN::Ra->new(url => ::canonicalize_url($url), auth => $baton,
++	my $self = SVN::Ra->new(url => $url, auth => $baton,
+ 	                      config => $config,
+ 			      pool => SVN::Pool->new,
+ 	                      auth_provider_callbacks => $callbacks);
+-- 
+1.7.10.4
+
only in patch2:
unchanged:
--- git-1.7.10.4.orig/debian/diff/0022-Git-SVN-Ra-canonicalize-earlier.diff
+++ git-1.7.10.4/debian/diff/0022-Git-SVN-Ra-canonicalize-earlier.diff
@@ -0,0 +1,55 @@
+From 253d877dcbf42385af8101a941da6f202942a1f0 Mon Sep 17 00:00:00 2001
+From: "Michael G. Schwern" <schwern@pobox.com>
+Date: Sat, 28 Jul 2012 02:38:32 -0700
+Subject: Git::SVN{,::Ra}: canonicalize earlier
+
+This canonicalizes paths and urls as early as possible so we don't
+have to remember to do it at the point of use.  It will fix a swath
+of SVN 1.7 problems in one go.
+
+Its ok to double canonicalize things.
+
+SVN 1.7 still fails, still not worrying about that.
+
+[ew: commit title]
+
+Signed-off-by: Eric Wong <normalperson@yhbt.net>
+Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
+---
+ git-svn.perl |    6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/git-svn.perl b/git-svn.perl
+index b14f4ad..c491111 100755
+--- a/git-svn.perl
++++ b/git-svn.perl
+@@ -4366,7 +4366,7 @@ sub path {
+ 
+ 	if (@_) {
+ 		my $path = shift;
+-		$self->{path} = $path;
++		$self->{path} = ::canonicalize_path($path);
+ 		return;
+ 	}
+ 
+@@ -4378,7 +4378,7 @@ sub url {
+ 
+ 	if (@_) {
+ 		my $url = shift;
+-		$self->{url} = $url;
++		$self->{url} = ::canonicalize_url($url);
+ 		return;
+ 	}
+ 
+@@ -5656,7 +5656,7 @@ sub url {
+ 
+ 	if (@_) {
+ 		my $url = shift;
+-		$self->{url} = $url;
++		$self->{url} = ::canonicalize_url($url);
+ 		return;
+ 	}
+ 
+-- 
+1.7.10.4
+
only in patch2:
unchanged:
--- git-1.7.10.4.orig/debian/diff/0031-git-svn-use-YAML-format-for-mergeinfo-cache-when-poss.diff
+++ git-1.7.10.4/debian/diff/0031-git-svn-use-YAML-format-for-mergeinfo-cache-when-poss.diff
@@ -0,0 +1,294 @@
+From c9254062d2dec478ec727c4e3ef6ca62cba4f0bc Mon Sep 17 00:00:00 2001
+From: Jonathan Nieder <jrnieder@gmail.com>
+Date: Sat, 9 Jun 2012 17:35:35 -0500
+Subject: git-svn: use YAML format for mergeinfo cache when possible
+
+Since v1.7.0-rc2~11 (git-svn: persistent memoization, 2010-01-30),
+git-svn has maintained some private per-repository caches in
+.git/svn/.caches to avoid refetching and recalculating some
+mergeinfo-related information with every "git svn fetch".
+
+These caches use the 'nstore' format from the perl core module
+Storable, which can be read and written quickly and was designed for
+transfer over the wire (the 'n' stands for 'network').  This format is
+supposed to be endianness-independent and independent of
+floating-point representation.
+
+Unfortunately the format is *not* independent of the perl version ---
+new perl versions will write files that very old perl cannot read.
+Worse, the format is not independent of the size of a perl integer.
+So if you toggle perl's use64bitint compile-time option, then using
+'git svn fetch' on your old repositories produces errors like this:
+
+	Byte order is not compatible at ../../lib/Storable.pm (autosplit
+	into ../../lib/auto/Storable/_retrieve.al) line 380, at
+	/usr/share/perl/5.12/Memoize/Storable.pm line 21
+
+That is, upgrading perl to a version that uses use64bitint for the
+first time makes git-svn suddenly refuse to fetch in existing
+repositories.  Removing .git/svn/.caches lets git-svn recover.
+
+It's time to switch to a platform independent serializer backend with
+better compatibility guarantees.  This patch uses YAML::Any.
+
+Other choices were considered:
+
+ - thawing data from Data::Dumper involves "eval".  Doing that without
+   creating a security risk is fussy.
+
+ - the JSON API works on scalars in memory and doesn't provide a
+   standard way to serialize straight to disk.
+
+YAML::Any is reasonably fast and has a pleasant API.  In most
+backends, LoadFile() reads the entire file into a scalar anyway and
+converts it as a second step, but having an interface that allows the
+deserialization to happen on the fly without a temporary is still a
+comfort.
+
+YAML::Any is not a core perl module, so we take care to use it when
+and only when it is available.  Installations without that module
+should fall back to using Storable with all its quirks, keeping their
+cache files in
+
+	.git/svn/.caches/*.db
+
+Installations with YAML peacefully coexist by keeping a separate set
+of cache files in
+
+	.git/svn/.caches/*.yaml.
+
+In most cases, switching between is a one-time thing, so it doesn't
+seem worth the complication to migrate existing caches.
+
+The upshot: after this patch, as long as YAML::Any is installed you
+can move your git repository between machines with different perl
+installations and "git svn fetch" will work fine.  If you do not have
+YAML::Any, the behavior is unchanged (and in particular does not get
+any worse).
+
+[jn: update fallback NO_PERL_MAKEMAKER rules, too, thanks to Adam
+ Roben; tweak log message to take
+ https://rt.cpan.org/Public/Bug/Display.html?id=77790 into account,
+ thanks to Tim Retout]
+
+Reported-by: Sandro Weiser <sandro.weiser@informatik.tu-chemnitz.de>
+Reported-by: Bdale Garbee <bdale@gag.com>
+Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
+Signed-off-by: Eric Wong <normalperson@yhbt.net>
+Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
+---
+ git-svn.perl                 |   31 +++++++++++---
+ perl/Git/SVN/Memoize/YAML.pm |   93 ++++++++++++++++++++++++++++++++++++++++++
+ perl/Makefile                |    8 +++-
+ perl/Makefile.PL             |    1 +
+ 4 files changed, 125 insertions(+), 8 deletions(-)
+ create mode 100644 perl/Git/SVN/Memoize/YAML.pm
+
+diff --git a/git-svn.perl b/git-svn.perl
+index 40ccdd5..367f3ad 100755
+--- a/git-svn.perl
++++ b/git-svn.perl
+@@ -2142,6 +2142,10 @@ package Git::SVN;
+ use Time::Local;
+ use Memoize;  # core since 5.8.0, Jul 2002
+ use Memoize::Storable;
++my $can_use_yaml;
++BEGIN {
++	$can_use_yaml = eval { require Git::SVN::Memoize::YAML; 1};
++}
+ 
+ my ($_gc_nr, $_gc_period);
+ 
+@@ -3676,6 +3680,17 @@ sub has_no_changes {
+ 		command_oneline("rev-parse", "$commit~1^{tree}"));
+ }
+ 
++sub tie_for_persistent_memoization {
++	my $hash = shift;
++	my $path = shift;
++
++	if ($can_use_yaml) {
++		tie %$hash => 'Git::SVN::Memoize::YAML', "$path.yaml";
++	} else {
++		tie %$hash => 'Memoize::Storable', "$path.db", 'nstore';
++	}
++}
++
+ # The GIT_DIR environment variable is not always set until after the command
+ # line arguments are processed, so we can't memoize in a BEGIN block.
+ {
+@@ -3688,22 +3703,26 @@ sub has_no_changes {
+ 		my $cache_path = "$ENV{GIT_DIR}/svn/.caches/";
+ 		mkpath([$cache_path]) unless -d $cache_path;
+ 
+-		tie my %lookup_svn_merge_cache => 'Memoize::Storable',
+-		    "$cache_path/lookup_svn_merge.db", 'nstore';
++		my %lookup_svn_merge_cache;
++		my %check_cherry_pick_cache;
++		my %has_no_changes_cache;
++
++		tie_for_persistent_memoization(\%lookup_svn_merge_cache,
++		    "$cache_path/lookup_svn_merge");
+ 		memoize 'lookup_svn_merge',
+ 			SCALAR_CACHE => 'FAULT',
+ 			LIST_CACHE => ['HASH' => \%lookup_svn_merge_cache],
+ 		;
+ 
+-		tie my %check_cherry_pick_cache => 'Memoize::Storable',
+-		    "$cache_path/check_cherry_pick.db", 'nstore';
++		tie_for_persistent_memoization(\%check_cherry_pick_cache,
++		    "$cache_path/check_cherry_pick");
+ 		memoize 'check_cherry_pick',
+ 			SCALAR_CACHE => 'FAULT',
+ 			LIST_CACHE => ['HASH' => \%check_cherry_pick_cache],
+ 		;
+ 
+-		tie my %has_no_changes_cache => 'Memoize::Storable',
+-		    "$cache_path/has_no_changes.db", 'nstore';
++		tie_for_persistent_memoization(\%has_no_changes_cache,
++		    "$cache_path/has_no_changes");
+ 		memoize 'has_no_changes',
+ 			SCALAR_CACHE => ['HASH' => \%has_no_changes_cache],
+ 			LIST_CACHE => 'FAULT',
+diff --git a/perl/Git/SVN/Memoize/YAML.pm b/perl/Git/SVN/Memoize/YAML.pm
+new file mode 100644
+index 0000000..9676b8f
+--- /dev/null
++++ b/perl/Git/SVN/Memoize/YAML.pm
+@@ -0,0 +1,93 @@
++package Git::SVN::Memoize::YAML;
++use warnings;
++use strict;
++use YAML::Any ();
++
++# based on Memoize::Storable.
++
++sub TIEHASH {
++	my $package = shift;
++	my $filename = shift;
++	my $truehash = (-e $filename) ? YAML::Any::LoadFile($filename) : {};
++	my $self = {FILENAME => $filename, H => $truehash};
++	bless $self => $package;
++}
++
++sub STORE {
++	my $self = shift;
++	$self->{H}{$_[0]} = $_[1];
++}
++
++sub FETCH {
++	my $self = shift;
++	$self->{H}{$_[0]};
++}
++
++sub EXISTS {
++	my $self = shift;
++	exists $self->{H}{$_[0]};
++}
++
++sub DESTROY {
++	my $self = shift;
++	YAML::Any::DumpFile($self->{FILENAME}, $self->{H});
++}
++
++sub SCALAR {
++	my $self = shift;
++	scalar(%{$self->{H}});
++}
++
++sub FIRSTKEY {
++	'Fake hash from Git::SVN::Memoize::YAML';
++}
++
++sub NEXTKEY {
++	undef;
++}
++
++1;
++__END__
++
++=head1 NAME
++
++Git::SVN::Memoize::YAML - store Memoized data in YAML format
++
++=head1 SYNOPSIS
++
++    use Memoize;
++    use Git::SVN::Memoize::YAML;
++
++    tie my %cache => 'Git::SVN::Memoize::YAML', $filename;
++    memoize('slow_function', SCALAR_CACHE => [HASH => \%cache]);
++    slow_function(arguments);
++
++=head1 DESCRIPTION
++
++This module provides a class that can be used to tie a hash to a
++YAML file.  The file is read when the hash is initialized and
++rewritten when the hash is destroyed.
++
++The intent is to allow L<Memoize> to back its cache with a file in
++YAML format, just like L<Memoize::Storable> allows L<Memoize> to
++back its cache with a file in Storable format.  Unlike the Storable
++format, the YAML format is platform-independent and fairly stable.
++
++Carps on error.
++
++=head1 DIAGNOSTICS
++
++See L<YAML::Any>.
++
++=head1 DEPENDENCIES
++
++L<YAML::Any> from CPAN.
++
++=head1 INCOMPATIBILITIES
++
++None reported.
++
++=head1 BUGS
++
++The entire cache is read into a Perl hash when loading the file,
++so this is not very scalable.
+diff --git a/perl/Makefile b/perl/Makefile
+index 3e21766..fec6546 100644
+--- a/perl/Makefile
++++ b/perl/Makefile
+@@ -24,17 +24,21 @@ ifdef NO_PERL_MAKEMAKER
+ instdir_SQ = $(subst ','\'',$(prefix)/lib)
+ $(makfile): ../GIT-CFLAGS Makefile
+ 	echo all: private-Error.pm Git.pm Git/I18N.pm > $@
+-	echo '	mkdir -p blib/lib/Git' >> $@
++	echo '	mkdir -p blib/lib/Git/SVN/Memoize' >> $@
+ 	echo '	$(RM) blib/lib/Git.pm; cp Git.pm blib/lib/' >> $@
+ 	echo '	$(RM) blib/lib/Git/I18N.pm; cp Git/I18N.pm blib/lib/Git/' >> $@
++	echo '	$(RM) blib/lib/Git/SVN/Memoize/YAML.pm' >> $@
++	echo '	cp Git/SVN/Memoize/YAML.pm blib/lib/Git/SVN/Memoize/' >> $@
+ 	echo '	$(RM) blib/lib/Error.pm' >> $@
+ 	'$(PERL_PATH_SQ)' -MError -e 'exit($$Error::VERSION < 0.15009)' || \
+ 	echo '	cp private-Error.pm blib/lib/Error.pm' >> $@
+ 	echo install: >> $@
+ 	echo '	mkdir -p "$$(DESTDIR)$(instdir_SQ)"' >> $@
+-	echo '	mkdir -p "$$(DESTDIR)$(instdir_SQ)/Git"' >> $@
++	echo '	mkdir -p "$$(DESTDIR)$(instdir_SQ)/Git/SVN/Memoize"' >> $@
+ 	echo '	$(RM) "$$(DESTDIR)$(instdir_SQ)/Git.pm"; cp Git.pm "$$(DESTDIR)$(instdir_SQ)"' >> $@
+ 	echo '	$(RM) "$$(DESTDIR)$(instdir_SQ)/Git/I18N.pm"; cp Git/I18N.pm "$$(DESTDIR)$(instdir_SQ)/Git"' >> $@
++	echo '	$(RM) "$$(DESTDIR)$(instdir_SQ)/Git/SVN/Memoize/YAML.pm"' >> $@
++	echo '	cp Git/SVN/Memoize/YAML.pm "$$(DESTDIR)$(instdir_SQ)/Git/SVN/Memoize"' >> $@
+ 	echo '	$(RM) "$$(DESTDIR)$(instdir_SQ)/Error.pm"' >> $@
+ 	'$(PERL_PATH_SQ)' -MError -e 'exit($$Error::VERSION < 0.15009)' || \
+ 	echo '	cp private-Error.pm "$$(DESTDIR)$(instdir_SQ)/Error.pm"' >> $@
+diff --git a/perl/Makefile.PL b/perl/Makefile.PL
+index 456d45b..321dfe1 100644
+--- a/perl/Makefile.PL
++++ b/perl/Makefile.PL
+@@ -27,6 +27,7 @@ MAKE_FRAG
+ my %pm = (
+ 	'Git.pm' => '$(INST_LIBDIR)/Git.pm',
+ 	'Git/I18N.pm' => '$(INST_LIBDIR)/Git/I18N.pm',
++	'Git/SVN/Memoize/YAML.pm' => '$(INST_LIBDIR)/Git/SVN/Memoize/YAML.pm',
+ );
+ 
+ # We come with our own bundled Error.pm. It's not in the set of default
+-- 
+1.7.10.4
+
only in patch2:
unchanged:
--- git-1.7.10.4.orig/debian/diff/0026-git-svn-introduce-add_path_to_url-function.diff
+++ git-1.7.10.4/debian/diff/0026-git-svn-introduce-add_path_to_url-function.diff
@@ -0,0 +1,196 @@
+From d8ff9224c955f1db9fdcab5df45da54cc4b3f79b Mon Sep 17 00:00:00 2001
+From: "Michael G. Schwern" <schwern@pobox.com>
+Date: Sat, 28 Jul 2012 02:47:50 -0700
+Subject: git-svn: introduce add_path_to_url function
+
+Remove the ad-hoc versions.
+
+This is mostly to normalize the process and ensure the URLs produced
+don't have double slashes or anything.
+
+Also provides a place to fix the corner case where a file path
+contains a percent sign.
+
+[ew: commit title]
+
+Signed-off-by: Eric Wong <normalperson@yhbt.net>
+Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
+---
+ git-svn.perl |   66 ++++++++++++++++++++++++++++++++++++++--------------------
+ 1 file changed, 43 insertions(+), 23 deletions(-)
+
+diff --git a/git-svn.perl b/git-svn.perl
+index b25f628..d00234d 100755
+--- a/git-svn.perl
++++ b/git-svn.perl
+@@ -1358,6 +1358,31 @@ sub join_paths {
+ }
+ 
+ 
++=head3 add_path_to_url
++
++    my $new_url = add_path_to_url($url, $path);
++
++Appends $path onto the $url.  If $path is empty, $url is returned unchanged.
++
++=cut
++
++sub add_path_to_url {
++	my($url, $path) = @_;
++
++	return $url if !defined $path or !length $path;
++
++	# Strip trailing and leading slashes so we don't
++	# wind up with http://x.com///path
++	$url  =~ s{/+$}{};
++	$path =~ s{^/+}{};
++
++	# If a path has a % in it, URI escape it so it's not
++	# mistaken for a URI escape later.
++	$path =~ s{%}{%25}g;
++
++	return join '/', $url, $path;
++}
++
+ # get_svnprops(PATH)
+ # ------------------
+ # Helper for cmd_propget and cmd_proplist below.
+@@ -1531,7 +1556,7 @@ sub cmd_info {
+ 	# canonicalize_path() will return "" to make libsvn 1.5.x happy,
+ 	$path = "." if $path eq "";
+ 
+-	my $full_url = canonicalize_url( $url . ($fullpath eq "" ? "" : "/$fullpath") );
++	my $full_url = canonicalize_url( add_path_to_url( $url, $fullpath ) );
+ 
+ 	if ($_url) {
+ 		print "$full_url\n";
+@@ -2639,8 +2664,7 @@ sub _set_svm_vars {
+ 		# username is of no interest
+ 		$src =~ s{(^[a-z\+]*://)[^/@]*@}{$1};
+ 
+-		my $replace = $ra->url;
+-		$replace .= "/$path" if length $path;
++		my $replace = ::add_path_to_url($ra->url, $path);
+ 
+ 		my $section = "svn-remote.$self->{repo_id}";
+ 		tmp_config("$section.svm-source", $src);
+@@ -2657,7 +2681,7 @@ sub _set_svm_vars {
+ 	my $path = $self->path;
+ 	my %tried;
+ 	while (length $path) {
+-		my $try = $self->url . "/$path";
++		my $try = ::add_path_to_url($self->url, $path);
+ 		unless ($tried{$try}) {
+ 			return $ra if $self->read_svm_props($ra, $path, $r);
+ 			$tried{$try} = 1;
+@@ -2666,7 +2690,7 @@ sub _set_svm_vars {
+ 	}
+ 	die "Path: '$path' should be ''\n" if $path ne '';
+ 	return $ra if $self->read_svm_props($ra, $path, $r);
+-	$tried{$self->url."/$path"} = 1;
++	$tried{ ::add_path_to_url($self->url, $path) } = 1;
+ 
+ 	if ($ra->{repos_root} eq $self->url) {
+ 		die @err, (map { "  $_\n" } keys %tried), "\n";
+@@ -2678,7 +2702,7 @@ sub _set_svm_vars {
+ 	$path = $ra->{svn_path};
+ 	$ra = Git::SVN::Ra->new($ra->{repos_root});
+ 	while (length $path) {
+-		my $try = $ra->url ."/$path";
++		my $try = ::add_path_to_url($ra->url, $path);
+ 		unless ($tried{$try}) {
+ 			$ok = $self->read_svm_props($ra, $path, $r);
+ 			last if $ok;
+@@ -2688,7 +2712,7 @@ sub _set_svm_vars {
+ 	}
+ 	die "Path: '$path' should be ''\n" if $path ne '';
+ 	$ok ||= $self->read_svm_props($ra, $path, $r);
+-	$tried{$ra->url ."/$path"} = 1;
++	$tried{ ::add_path_to_url($ra->url, $path) } = 1;
+ 	if (!$ok) {
+ 		die @err, (map { "  $_\n" } keys %tried), "\n";
+ 	}
+@@ -3008,20 +3032,19 @@ sub rewrite_uuid {
+ 
+ sub metadata_url {
+ 	my ($self) = @_;
+-	($self->rewrite_root || $self->url) .
+-	   (length $self->path ? '/' . $self->path : '');
++	my $url = $self->rewrite_root || $self->url;
++	return ::add_path_to_url( $url, $self->path );
+ }
+ 
+ sub full_url {
+ 	my ($self) = @_;
+-	$self->url . (length $self->path ? '/' . $self->path : '');
++	return ::add_path_to_url( $self->url, $self->path );
+ }
+ 
+ sub full_pushurl {
+ 	my ($self) = @_;
+ 	if ($self->{pushurl}) {
+-		return $self->{pushurl} . (length $self->path ? '/' .
+-		       $self->path : '');
++		return ::add_path_to_url( $self->{pushurl}, $self->path );
+ 	} else {
+ 		return $self->full_url;
+ 	}
+@@ -3189,7 +3212,7 @@ sub find_parent_branch {
+ 	my $r = $i->{copyfrom_rev};
+ 	my $repos_root = $self->ra->{repos_root};
+ 	my $url = $self->ra->url;
+-	my $new_url = $url . $branch_from;
++	my $new_url = ::add_path_to_url( $url, $branch_from );
+ 	print STDERR  "Found possible branch point: ",
+ 	              "$new_url => ", $self->full_url, ", $r\n"
+ 	              unless $::_q > 1;
+@@ -3518,12 +3541,11 @@ sub find_extra_svk_parents {
+ 	for my $ticket ( @tickets ) {
+ 		my ($uuid, $path, $rev) = split /:/, $ticket;
+ 		if ( $uuid eq $self->ra_uuid ) {
+-			my $url = $self->url;
+-			my $repos_root = $url;
++			my $repos_root = $self->url;
+ 			my $branch_from = $path;
+ 			$branch_from =~ s{^/}{};
+-			my $gs = $self->other_gs($repos_root."/".$branch_from,
+-			                         $url,
++			my $gs = $self->other_gs(::add_path_to_url( $repos_root, $branch_from ),
++			                         $repos_root,
+ 			                         $branch_from,
+ 			                         $rev,
+ 			                         $self->{ref_id});
+@@ -3931,8 +3953,7 @@ sub make_log_entry {
+ 		$email ||= "$author\@$uuid";
+ 		$commit_email ||= "$author\@$uuid";
+ 	} elsif ($self->use_svnsync_props) {
+-		my $full_url = $self->svnsync->{url};
+-		$full_url .= "/".$self->path if length $self->path;
++		my $full_url = ::add_path_to_url( $self->svnsync->{url}, $self->path );
+ 		remove_username($full_url);
+ 		my $uuid = $self->svnsync->{uuid};
+ 		$log_entry{metadata} = "$full_url\@$rev $uuid";
+@@ -5798,9 +5819,8 @@ sub gs_do_switch {
+ 	my $path = $gs->path;
+ 	my $pool = SVN::Pool->new;
+ 
+-	my $full_url = $self->url;
+-	my $old_url = $full_url;
+-	$full_url .= '/' . $path if length $path;
++	my $old_url = $self->url;
++	my $full_url = ::add_path_to_url( $self->url, $path );
+ 	my ($ra, $reparented);
+ 
+ 	if ($old_url =~ m#^svn(\+ssh)?://# ||
+@@ -6066,7 +6086,7 @@ sub minimize_url {
+ 	my @components = split(m!/!, $self->{svn_path});
+ 	my $c = '';
+ 	do {
+-		$url .= "/$c" if length $c;
++		$url = ::add_path_to_url($url, $c);
+ 		eval {
+ 			my $ra = (ref $self)->new($url);
+ 			my $latest = $ra->get_latest_revnum;
+-- 
+1.7.10.4
+
only in patch2:
unchanged:
--- git-1.7.10.4.orig/debian/diff/0020-git-svn-add-join_paths-to-safely-concatenate-paths.diff
+++ git-1.7.10.4/debian/diff/0020-git-svn-add-join_paths-to-safely-concatenate-paths.diff
@@ -0,0 +1,98 @@
+From f39fef0a43e4c755837593229a39828e45611e77 Mon Sep 17 00:00:00 2001
+From: "Michael G. Schwern" <schwern@pobox.com>
+Date: Sat, 28 Jul 2012 02:38:29 -0700
+Subject: git-svn: add join_paths() to safely concatenate paths
+
+Otherwise you might wind up with things like...
+
+    my $path1 = undef;
+    my $path2 = 'foo';
+    my $path = $path1 . '/' . $path2;
+
+creating '/foo'.  Or this...
+
+    my $path1 = 'foo/';
+    my $path2 = 'bar';
+    my $path = $path1 . '/' . $path2;
+
+creating 'foo//bar'.
+
+Could have used File::Spec, but I'm shying away from it due to SVN
+1.7's pickiness about paths.  Felt it would be better to have our own
+we can control completely.
+
+[ew: commit title]
+[jn: drop unused unit test]
+
+Signed-off-by: Eric Wong <normalperson@yhbt.net>
+Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
+---
+ git-svn.perl |   38 ++++++++++++++++++++++++++++++++++----
+ 1 file changed, 34 insertions(+), 4 deletions(-)
+
+diff --git a/git-svn.perl b/git-svn.perl
+index 045105b..e7d0fb8 100755
+--- a/git-svn.perl
++++ b/git-svn.perl
+@@ -1285,6 +1285,38 @@ sub _canonicalize_url_ourselves {
+ 	return $url;
+ }
+ 
++=head3 join_paths
++
++    my $new_path = join_paths(@paths);
++
++Appends @paths together into a single path.  Any empty paths are ignored.
++
++=cut
++
++sub join_paths {
++	my @paths = @_;
++
++	@paths = grep { defined $_ && length $_ } @paths;
++
++	return '' unless @paths;
++	return $paths[0] if @paths == 1;
++
++	my $new_path = shift @paths;
++	$new_path =~ s{/+$}{};
++
++	my $last_path = pop @paths;
++	$last_path =~ s{^/+}{};
++
++	for my $path (@paths) {
++		$path =~ s{^/+}{};
++		$path =~ s{/+$}{};
++		$new_path .= "/$path";
++	}
++
++	return $new_path .= "/$last_path";
++}
++
++
+ # get_svnprops(PATH)
+ # ------------------
+ # Helper for cmd_propget and cmd_proplist below.
+@@ -1298,7 +1330,7 @@ sub get_svnprops {
+ 	$path = $cmd_dir_prefix . $path;
+ 	fatal("No such file or directory: $path") unless -e $path;
+ 	my $is_dir = -d $path ? 1 : 0;
+-	$path = $gs->{path} . '/' . $path;
++	$path = join_paths($gs->{path}, $path);
+ 
+ 	# canonicalize the path (otherwise libsvn will abort or fail to
+ 	# find the file)
+@@ -2342,9 +2374,7 @@ sub init_remote_config {
+ 			}
+ 			my $old_path = $self->path;
+ 			$url =~ s!^\Q$min_url\E(/|$)!!;
+-			if (length $old_path) {
+-				$url .= "/$old_path";
+-			}
++			$url = ::join_paths($url, $old_path);
+ 			$self->path($url);
+ 			$url = $min_url;
+ 		}
+-- 
+1.7.10.4
+
only in patch2:
unchanged:
--- git-1.7.10.4.orig/debian/diff/0021-git-svn-path-canonicalization-uses-SVN-API.diff
+++ git-1.7.10.4/debian/diff/0021-git-svn-path-canonicalization-uses-SVN-API.diff
@@ -0,0 +1,64 @@
+From e0fdd786a0fa23df21fdaa7847e56ea2e374c4e4 Mon Sep 17 00:00:00 2001
+From: "Michael G. Schwern" <schwern@pobox.com>
+Date: Sat, 28 Jul 2012 02:38:31 -0700
+Subject: git-svn: path canonicalization uses SVN API
+
+All tests pass with SVN 1.6.  SVN 1.7 remains broken, not worrying
+about it yet.
+
+SVN changed its path canonicalization API between 1.6 and 1.7.
+http://svnbook.red-bean.com/en/1.6/svn.developer.usingapi.html#svn.developer.usingapi.urlpath
+http://svnbook.red-bean.com/en/1.7/svn.developer.usingapi.html#svn.developer.usingapi.urlpath
+
+The SVN API does not accept foo/.. but it also doesn't canonicalize
+it.  We have to do it ourselves.
+
+[ew: commit title, fall back if SVN <= 1.6 fails to canonicalize]
+[jn: load SVN::Base on demand]
+
+Signed-off-by: Eric Wong <normalperson@yhbt.net>
+Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
+---
+ git-svn.perl |   26 ++++++++++++++++++++++++++
+ 1 file changed, 26 insertions(+)
+
+diff --git a/git-svn.perl b/git-svn.perl
+index e7d0fb8..b14f4ad 100755
+--- a/git-svn.perl
++++ b/git-svn.perl
+@@ -1245,6 +1245,32 @@ sub _collapse_dotdot {
+ 
+ 
+ sub canonicalize_path {
++	my $path = shift;
++	my $rv;
++
++	::_req_svn();
++
++	# The 1.7 way to do it
++	if ( defined &SVN::_Core::svn_dirent_canonicalize ) {
++		$path = _collapse_dotdot($path);
++		$rv = SVN::_Core::svn_dirent_canonicalize($path);
++	}
++	# The 1.6 way to do it
++	# This can return undef on subversion-perl-1.4.2-2.el5 (CentOS 5.2)
++	elsif ( defined &SVN::_Core::svn_path_canonicalize ) {
++		$path = _collapse_dotdot($path);
++		$rv = SVN::_Core::svn_path_canonicalize($path);
++	}
++
++	return $rv if defined $rv;
++
++	# No SVN API canonicalization is available, or the SVN API
++	# didn't return a successful result, do it ourselves
++	return _canonicalize_path_ourselves($path);
++}
++
++
++sub _canonicalize_path_ourselves {
+ 	my ($path) = @_;
+ 	my $dot_slash_added = 0;
+ 	if (substr($path, 0, 1) ne "/") {
+-- 
+1.7.10.4
+
only in patch2:
unchanged:
--- git-1.7.10.4.orig/debian/diff/0024-git-svn-replace-URL-escapes-with-canonicalization.diff
+++ git-1.7.10.4/debian/diff/0024-git-svn-replace-URL-escapes-with-canonicalization.diff
@@ -0,0 +1,148 @@
+From ec8f9d9592654b4486e6b14a457e45640d697857 Mon Sep 17 00:00:00 2001
+From: "Michael G. Schwern" <schwern@pobox.com>
+Date: Sat, 28 Jul 2012 02:47:48 -0700
+Subject: git-svn: replace URL escapes with canonicalization
+
+The old hand-rolled URL escape functions were inferior to
+canonicalization functions.
+
+Continuing to move towards getting everything canonicalizing the same way.
+
+* Git::SVN->init_remote_config and Git::SVN::Ra->minimize_url both
+  have to canonicalize the same way else init_remote_config
+  will incorrectly think they're different URLs causing
+  t9107-git-svn-migrate.sh to fail.
+
+[ew: commit title]
+
+Signed-off-by: Eric Wong <normalperson@yhbt.net>
+Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
+---
+ git-svn.perl |   53 +++++++++--------------------------------------------
+ 1 file changed, 9 insertions(+), 44 deletions(-)
+
+diff --git a/git-svn.perl b/git-svn.perl
+index a47ec74..ba006fc 100755
+--- a/git-svn.perl
++++ b/git-svn.perl
+@@ -1507,24 +1507,6 @@ sub cmd_commit_diff {
+ 	}
+ }
+ 
+-sub escape_uri_only {
+-	my ($uri) = @_;
+-	my @tmp;
+-	foreach (split m{/}, $uri) {
+-		s/([^~\w.%+-]|%(?![a-fA-F0-9]{2}))/sprintf("%%%02X",ord($1))/eg;
+-		push @tmp, $_;
+-	}
+-	join('/', @tmp);
+-}
+-
+-sub escape_url {
+-	my ($url) = @_;
+-	if ($url =~ m#^([^:]+)://([^/]*)(.*)$#) {
+-		my ($scheme, $domain, $uri) = ($1, $2, escape_uri_only($3));
+-		$url = "$scheme://$domain$uri";
+-	}
+-	$url;
+-}
+ 
+ sub cmd_info {
+ 	my $path = canonicalize_path(defined($_[0]) ? $_[0] : ".");
+@@ -1552,18 +1534,18 @@ sub cmd_info {
+ 	my $full_url = $url . ($fullpath eq "" ? "" : "/$fullpath");
+ 
+ 	if ($_url) {
+-		print escape_url($full_url), "\n";
++		print canonicalize_url($full_url), "\n";
+ 		return;
+ 	}
+ 
+ 	my $result = "Path: $path\n";
+ 	$result .= "Name: " . basename($path) . "\n" if $file_type ne "dir";
+-	$result .= "URL: " . escape_url($full_url) . "\n";
++	$result .= "URL: " . canonicalize_url($full_url) . "\n";
+ 
+ 	eval {
+ 		my $repos_root = $gs->repos_root;
+ 		Git::SVN::remove_username($repos_root);
+-		$result .= "Repository Root: " . escape_url($repos_root) . "\n";
++		$result .= "Repository Root: " . canonicalize_url($repos_root) . "\n";
+ 	};
+ 	if ($@) {
+ 		$result .= "Repository Root: (offline)\n";
+@@ -2389,7 +2371,7 @@ sub find_existing_remote {
+ 
+ sub init_remote_config {
+ 	my ($self, $url, $no_write) = @_;
+-	$url =~ s!/+$!!; # strip trailing slash
++	$url = ::canonicalize_url($url);
+ 	my $r = read_all_remotes();
+ 	my $existing = find_existing_remote($url, $r);
+ 	if ($existing) {
+@@ -5596,24 +5578,6 @@ ()
+ 	]
+ }
+ 
+-sub escape_uri_only {
+-	my ($uri) = @_;
+-	my @tmp;
+-	foreach (split m{/}, $uri) {
+-		s/([^~\w.%+-]|%(?![a-fA-F0-9]{2}))/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 {
+ 	my ($class, $url) = @_;
+@@ -5649,7 +5613,7 @@ sub new {
+ 			$Git::SVN::Prompt::_no_auth_cache = 1;
+ 		}
+ 	} # no warnings 'once'
+-	my $self = SVN::Ra->new(url => escape_url($url), auth => $baton,
++	my $self = SVN::Ra->new(url => ::canonicalize_url($url), auth => $baton,
+ 	                      config => $config,
+ 			      pool => SVN::Pool->new,
+ 	                      auth_provider_callbacks => $callbacks);
+@@ -5841,7 +5805,7 @@ sub gs_do_switch {
+ 
+ 	if ($old_url =~ m#^svn(\+ssh)?://# ||
+ 	    ($full_url =~ m#^https?://# &&
+-	     escape_url($full_url) ne $full_url)) {
++	     ::canonicalize_url($full_url) ne $full_url)) {
+ 		$_[0] = undef;
+ 		$self = undef;
+ 		$RA = undef;
+@@ -5854,7 +5818,7 @@ sub gs_do_switch {
+ 	}
+ 
+ 	$ra ||= $self;
+-	$url_b = escape_url($url_b);
++	$url_b = ::canonicalize_url($url_b);
+ 	my $reporter = $ra->do_switch($rev_b, '', 1, $url_b, $editor, $pool);
+ 	my @lock = $SVN::Core::VERSION ge '1.2.0' ? (undef) : ();
+ 	$reporter->set_path('', $rev_a, 0, @lock, $pool);
+@@ -6109,7 +6073,8 @@ sub minimize_url {
+ 			$ra->get_log("", $latest, 0, 1, 0, 1, sub {});
+ 		};
+ 	} while ($@ && ($c = shift @components));
+-	$url;
++
++	return ::canonicalize_url($url);
+ }
+ 
+ sub can_do_switch {
+-- 
+1.7.10.4
+
only in patch2:
unchanged:
--- git-1.7.10.4.orig/debian/diff/0015-Git-SVN-Ra-use-accessor-for-URLs.diff
+++ git-1.7.10.4/debian/diff/0015-Git-SVN-Ra-use-accessor-for-URLs.diff
@@ -0,0 +1,139 @@
+From 03af2344304c67f1eef59f343f3cff9ec324eb34 Mon Sep 17 00:00:00 2001
+From: "Michael G. Schwern" <schwern@pobox.com>
+Date: Fri, 27 Jul 2012 13:00:50 -0700
+Subject: Git::SVN::Ra: use accessor for URLs
+
+Later it can canonicalize automatically.
+
+A later change will make other things use the accessor.
+
+No functional change.
+
+[ew: commit title, reformatted accessor to match existing style]
+
+Signed-off-by: Eric Wong <normalperson@yhbt.net>
+Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
+---
+ git-svn.perl |   38 +++++++++++++++++++++++++++-----------
+ 1 file changed, 27 insertions(+), 11 deletions(-)
+
+diff --git a/git-svn.perl b/git-svn.perl
+index 235b087..d1294fc 100755
+--- a/git-svn.perl
++++ b/git-svn.perl
+@@ -5515,7 +5515,7 @@ sub escape_url {
+ sub new {
+ 	my ($class, $url) = @_;
+ 	$url =~ s!/+$!!;
+-	return $RA if ($RA && $RA->{url} eq $url);
++	return $RA if ($RA && $RA->url eq $url);
+ 
+ 	::_req_svn();
+ 
+@@ -5550,13 +5550,29 @@ sub new {
+ 	                      config => $config,
+ 			      pool => SVN::Pool->new,
+ 	                      auth_provider_callbacks => $callbacks);
+-	$self->{url} = $url;
++	$RA = bless $self, $class;
++
++	# Make sure its canonicalized
++	$self->url($url);
+ 	$self->{svn_path} = $url;
+ 	$self->{repos_root} = $self->get_repos_root;
+ 	$self->{svn_path} =~ s#^\Q$self->{repos_root}\E(/|$)##;
+ 	$self->{cache} = { check_path => { r => 0, data => {} },
+ 	                   get_dir => { r => 0, data => {} } };
+-	$RA = bless $self, $class;
++
++	return $RA;
++}
++
++sub url {
++	my $self = shift;
++
++	if (@_) {
++		my $url = shift;
++		$self->{url} = $url;
++		return;
++	}
++
++	return $self->{url};
+ }
+ 
+ sub check_path {
+@@ -5715,7 +5731,7 @@ sub gs_do_switch {
+ 	my $path = $gs->{path};
+ 	my $pool = SVN::Pool->new;
+ 
+-	my $full_url = $self->{url};
++	my $full_url = $self->url;
+ 	my $old_url = $full_url;
+ 	$full_url .= '/' . $path if length $path;
+ 	my ($ra, $reparented);
+@@ -5730,7 +5746,7 @@ sub gs_do_switch {
+ 		$ra_invalid = 1;
+ 	} elsif ($old_url ne $full_url) {
+ 		SVN::_Ra::svn_ra_reparent($self->{session}, $full_url, $pool);
+-		$self->{url} = $full_url;
++		$self->url($full_url);
+ 		$reparented = 1;
+ 	}
+ 
+@@ -5743,7 +5759,7 @@ sub gs_do_switch {
+ 
+ 	if ($reparented) {
+ 		SVN::_Ra::svn_ra_reparent($self->{session}, $old_url, $pool);
+-		$self->{url} = $old_url;
++		$self->url($old_url);
+ 	}
+ 
+ 	$pool->clear;
+@@ -5792,7 +5808,7 @@ sub gs_fetch_loop_common {
+ 	my $inc = $_log_window_size;
+ 	my ($min, $max) = ($base, $head < $base + $inc ? $head : $base + $inc);
+ 	my $longest_path = longest_common_path($gsv, $globs);
+-	my $ra_url = $self->{url};
++	my $ra_url = $self->url;
+ 	my $find_trailing_edge;
+ 	while (1) {
+ 		my %revs;
+@@ -5938,7 +5954,7 @@ sub match_globs {
+ 				 ($self->check_path($p, $r) !=
+ 				  $SVN::Node::dir));
+ 			next unless $p =~ /$g->{path}->{regex}/;
+-			$exists->{$p} = Git::SVN->init($self->{url}, $p, undef,
++			$exists->{$p} = Git::SVN->init($self->url, $p, undef,
+ 					 $g->{ref}->full_path($de), 1);
+ 		}
+ 	}
+@@ -5962,7 +5978,7 @@ sub match_globs {
+ 			next if ($self->check_path($pathname, $r) !=
+ 			         $SVN::Node::dir);
+ 			$exists->{$pathname} = Git::SVN->init(
+-			                      $self->{url}, $pathname, undef,
++			                      $self->url, $pathname, undef,
+ 			                      $g->{ref}->full_path($p), 1);
+ 		}
+ 		my $c = '';
+@@ -5978,7 +5994,7 @@ sub match_globs {
+ 
+ sub minimize_url {
+ 	my ($self) = @_;
+-	return $self->{url} if ($self->{url} eq $self->{repos_root});
++	return $self->url if ($self->url eq $self->{repos_root});
+ 	my $url = $self->{repos_root};
+ 	my @components = split(m!/!, $self->{svn_path});
+ 	my $c = '';
+@@ -5998,7 +6014,7 @@ sub can_do_switch {
+ 	unless (defined $can_do_switch) {
+ 		my $pool = SVN::Pool->new;
+ 		my $rep = eval {
+-			$self->do_switch(1, '', 0, $self->{url},
++			$self->do_switch(1, '', 0, $self->url,
+ 			                 SVN::Delta::Editor->new, $pool);
+ 		};
+ 		if ($@) {
+-- 
+1.7.10.4
+
only in patch2:
unchanged:
--- git-1.7.10.4.orig/debian/diff/0023-git-svn-attempt-to-mimic-SVN-1.7-URL-canonicalization.diff
+++ git-1.7.10.4/debian/diff/0023-git-svn-attempt-to-mimic-SVN-1.7-URL-canonicalization.diff
@@ -0,0 +1,98 @@
+From 80702a1f9be362436715ad9c3fa01ef74ddfd6e4 Mon Sep 17 00:00:00 2001
+From: "Michael G. Schwern" <schwern@pobox.com>
+Date: Sat, 28 Jul 2012 02:47:47 -0700
+Subject: 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]
+[jn: drop unused unit test]
+
+Signed-off-by: Eric Wong <normalperson@yhbt.net>
+Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
+---
+ git-svn.perl               |   23 +++++++++++++++++++----
+ t/t9107-git-svn-migrate.sh |    4 +++-
+ 2 files changed, 22 insertions(+), 5 deletions(-)
+
+diff --git a/git-svn.perl b/git-svn.perl
+index c491111..a47ec74 100755
+--- a/git-svn.perl
++++ b/git-svn.perl
+@@ -1305,10 +1305,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;
+ }
+ 
+ =head3 join_paths
+@@ -2281,9 +2296,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$!) {
+diff --git a/t/t9107-git-svn-migrate.sh b/t/t9107-git-svn-migrate.sh
+index 289fc31..e7b103d 100755
+--- a/t/t9107-git-svn-migrate.sh
++++ b/t/t9107-git-svn-migrate.sh
+@@ -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}"
+ 	'
+-- 
+1.7.10.4
+
only in patch2:
unchanged:
--- git-1.7.10.4.orig/debian/diff/0017-use-Git-SVN-RA-url-accessor-globally.diff
+++ git-1.7.10.4/debian/diff/0017-use-Git-SVN-RA-url-accessor-globally.diff
@@ -0,0 +1,114 @@
+From ea2bfa9264e973954a40d79631e6a586f621b92a Mon Sep 17 00:00:00 2001
+From: "Michael G. Schwern" <schwern@pobox.com>
+Date: Fri, 27 Jul 2012 13:00:52 -0700
+Subject: use Git::SVN{,::RA}->url accessor globally
+
+Note: The structure returned from Git::SVN->read_all_remotes() does not
+appear to contain objects, so I'm leaving them alone.
+
+That's everything converted over to the url and path accessors.
+
+No functional change.
+
+[ew: commit title]
+
+Signed-off-by: Eric Wong <normalperson@yhbt.net>
+Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
+---
+ git-svn.perl |   28 +++++++++++++++-------------
+ 1 file changed, 15 insertions(+), 13 deletions(-)
+
+diff --git a/git-svn.perl b/git-svn.perl
+index 68b3c28..18f963d 100755
+--- a/git-svn.perl
++++ b/git-svn.perl
+@@ -1371,7 +1371,7 @@ sub cmd_commit_diff {
+ 			fatal("Needed URL or usable git-svn --id in ",
+ 			      "the command-line\n", $usage);
+ 		}
+-		$url = $gs->{url};
++		$url = $gs->url;
+ 		$svn_path = $gs->path;
+ 	}
+ 	unless (defined $_revision) {
+@@ -1639,15 +1639,16 @@ sub complete_url_ls_init {
+ 			      "and a separate URL is not specified");
+ 		}
+ 	}
+-	my $url = $ra->{url};
++	my $url = $ra->url;
+ 	my $gs = Git::SVN->init($url, undef, undef, undef, 1);
+ 	my $k = "svn-remote.$gs->{repo_id}.url";
+ 	my $orig_url = eval { command_oneline(qw/config --get/, $k) };
+-	if ($orig_url && ($orig_url ne $gs->{url})) {
++	if ($orig_url && ($orig_url ne $gs->url)) {
+ 		die "$k already set: $orig_url\n",
+-		    "wanted to set to: $gs->{url}\n";
++		    "wanted to set to: $gs->url\n";
+ 	}
+-	command_oneline('config', $k, $gs->{url}) unless $orig_url;
++	command_oneline('config', $k, $gs->url) unless $orig_url;
++
+ 	my $remote_path = $gs->path . "/$repo_path";
+ 	$remote_path =~ s{%([0-9A-F]{2})}{chr hex($1)}ieg;
+ 	$remote_path =~ s#/+#/#g;
+@@ -2557,7 +2558,7 @@ sub _set_svm_vars {
+ 		# username is of no interest
+ 		$src =~ s{(^[a-z\+]*://)[^/@]*@}{$1};
+ 
+-		my $replace = $ra->{url};
++		my $replace = $ra->url;
+ 		$replace .= "/$path" if length $path;
+ 
+ 		my $section = "svn-remote.$self->{repo_id}";
+@@ -2596,16 +2597,17 @@ sub _set_svm_vars {
+ 	$path = $ra->{svn_path};
+ 	$ra = Git::SVN::Ra->new($ra->{repos_root});
+ 	while (length $path) {
+-		unless ($tried{"$ra->{url}/$path"}) {
++		my $try = $ra->url ."/$path";
++		unless ($tried{$try}) {
+ 			$ok = $self->read_svm_props($ra, $path, $r);
+ 			last if $ok;
+-			$tried{"$ra->{url}/$path"} = 1;
++			$tried{$try} = 1;
+ 		}
+ 		$path =~ s#/?[^/]+$##;
+ 	}
+ 	die "Path: '$path' should be ''\n" if $path ne '';
+ 	$ok ||= $self->read_svm_props($ra, $path, $r);
+-	$tried{"$ra->{url}/$path"} = 1;
++	$tried{$ra->url ."/$path"} = 1;
+ 	if (!$ok) {
+ 		die @err, (map { "  $_\n" } keys %tried), "\n";
+ 	}
+@@ -3105,7 +3107,7 @@ sub find_parent_branch {
+ 	}
+ 	my $r = $i->{copyfrom_rev};
+ 	my $repos_root = $self->ra->{repos_root};
+-	my $url = $self->ra->{url};
++	my $url = $self->ra->url;
+ 	my $new_url = $url . $branch_from;
+ 	print STDERR  "Found possible branch point: ",
+ 	              "$new_url => ", $self->full_url, ", $r\n"
+@@ -6616,14 +6618,14 @@ sub minimize_connections {
+ 		my $ra = Git::SVN::Ra->new($url);
+ 
+ 		# skip existing cases where we already connect to the root
+-		if (($ra->{url} eq $ra->{repos_root}) ||
++		if (($ra->url eq $ra->{repos_root}) ||
+ 		    ($ra->{repos_root} eq $repo_id)) {
+-			$root_repos->{$ra->{url}} = $repo_id;
++			$root_repos->{$ra->url} = $repo_id;
+ 			next;
+ 		}
+ 
+ 		my $root_ra = Git::SVN::Ra->new($ra->{repos_root});
+-		my $root_path = $ra->{url};
++		my $root_path = $ra->url;
+ 		$root_path =~ s#^\Q$ra->{repos_root}\E(/|$)##;
+ 		foreach my $path (keys %$fetch) {
+ 			my $ref_id = $fetch->{$path};
+-- 
+1.7.10.4
+
only in patch2:
unchanged:
--- git-1.7.10.4.orig/debian/diff/0014-Git-SVN-use-accessor-for-URLs-internally.diff
+++ git-1.7.10.4/debian/diff/0014-Git-SVN-use-accessor-for-URLs-internally.diff
@@ -0,0 +1,151 @@
+From a72c94bfa8a7118094a77024853ab24014f9664a Mon Sep 17 00:00:00 2001
+From: "Michael G. Schwern" <schwern@pobox.com>
+Date: Fri, 27 Jul 2012 13:00:49 -0700
+Subject: Git::SVN: use accessor for URLs internally
+
+So later it can do automatic canonicalization.
+
+A later patch will make other things use the accessor.
+
+No functional change here.
+
+[ew: commit title]
+
+Signed-off-by: Eric Wong <normalperson@yhbt.net>
+Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
+---
+ git-svn.perl |   42 ++++++++++++++++++++++++++++--------------
+ 1 file changed, 28 insertions(+), 14 deletions(-)
+
+diff --git a/git-svn.perl b/git-svn.perl
+index 99bbac3..235b087 100755
+--- a/git-svn.perl
++++ b/git-svn.perl
+@@ -2346,7 +2346,7 @@ sub init_remote_config {
+ 			      "svn-remote.$self->{repo_id}.fetch",
+ 			      $self->path.":".$self->refname);
+ 	}
+-	$self->{url} = $url;
++	$self->url($url);
+ }
+ 
+ sub find_by_url { # repos_root and, path are optional
+@@ -2448,9 +2448,10 @@ sub new {
+ 		$path =~ s{/\z}{};
+ 		$self->path($path);
+ 	}
+-	$self->{url} = command_oneline('config', '--get',
+-	                               "svn-remote.$repo_id.url") or
++	my $url = command_oneline('config', '--get',
++	                          "svn-remote.$repo_id.url") or
+                   die "Failed to read \"svn-remote.$repo_id.url\" in config\n";
++	$self->url($url);
+ 	$self->{pushurl} = eval { command_oneline('config', '--get',
+ 	                          "svn-remote.$repo_id.pushurl") };
+ 	$self->rebuild;
+@@ -2572,17 +2573,18 @@ sub _set_svm_vars {
+ 	my $path = $self->path;
+ 	my %tried;
+ 	while (length $path) {
+-		unless ($tried{"$self->{url}/$path"}) {
++		my $try = $self->url . "/$path";
++		unless ($tried{$try}) {
+ 			return $ra if $self->read_svm_props($ra, $path, $r);
+-			$tried{"$self->{url}/$path"} = 1;
++			$tried{$try} = 1;
+ 		}
+ 		$path =~ s#/?[^/]+$##;
+ 	}
+ 	die "Path: '$path' should be ''\n" if $path ne '';
+ 	return $ra if $self->read_svm_props($ra, $path, $r);
+-	$tried{"$self->{url}/$path"} = 1;
++	$tried{$self->url."/$path"} = 1;
+ 
+-	if ($ra->{repos_root} eq $self->{url}) {
++	if ($ra->{repos_root} eq $self->url) {
+ 		die @err, (map { "  $_\n" } keys %tried), "\n";
+ 	}
+ 
+@@ -2605,7 +2607,7 @@ sub _set_svm_vars {
+ 	if (!$ok) {
+ 		die @err, (map { "  $_\n" } keys %tried), "\n";
+ 	}
+-	Git::SVN::Ra->new($self->{url});
++	Git::SVN::Ra->new($self->url);
+ }
+ 
+ sub svnsync {
+@@ -2672,7 +2674,7 @@ sub ra_uuid {
+ 		if (!$@ && $uuid && $uuid =~ /^([a-f\d\-]{30,})$/i) {
+ 			$self->{ra_uuid} = $uuid;
+ 		} else {
+-			die "ra_uuid called without URL\n" unless $self->{url};
++			die "ra_uuid called without URL\n" unless $self->url;
+ 			$self->{ra_uuid} = $self->ra->get_uuid;
+ 			tmp_config('--add', $key, $self->{ra_uuid});
+ 		}
+@@ -2696,7 +2698,7 @@ sub repos_root {
+ 
+ sub ra {
+ 	my ($self) = shift;
+-	my $ra = Git::SVN::Ra->new($self->{url});
++	my $ra = Git::SVN::Ra->new($self->url);
+ 	$self->_set_repos_root($ra->{repos_root});
+ 	if ($self->use_svm_props && !$self->{svm}) {
+ 		if ($self->no_metadata) {
+@@ -2921,13 +2923,13 @@ sub rewrite_uuid {
+ 
+ sub metadata_url {
+ 	my ($self) = @_;
+-	($self->rewrite_root || $self->{url}) .
++	($self->rewrite_root || $self->url) .
+ 	   (length $self->path ? '/' . $self->path : '');
+ }
+ 
+ sub full_url {
+ 	my ($self) = @_;
+-	$self->{url} . (length $self->path ? '/' . $self->path : '');
++	$self->url . (length $self->path ? '/' . $self->path : '');
+ }
+ 
+ sub full_pushurl {
+@@ -3431,7 +3433,7 @@ sub find_extra_svk_parents {
+ 	for my $ticket ( @tickets ) {
+ 		my ($uuid, $path, $rev) = split /:/, $ticket;
+ 		if ( $uuid eq $self->ra_uuid ) {
+-			my $url = $self->{url};
++			my $url = $self->url;
+ 			my $repos_root = $url;
+ 			my $branch_from = $path;
+ 			$branch_from =~ s{^/}{};
+@@ -3662,7 +3664,7 @@ sub find_extra_svn_parents {
+ 	# are now marked as merge, we can add the tip as a parent.
+ 	my @merges = split "\n", $mergeinfo;
+ 	my @merge_tips;
+-	my $url = $self->{url};
++	my $url = $self->url;
+ 	my $uuid = $self->ra_uuid;
+ 	my %ranges;
+ 	for my $merge ( @merges ) {
+@@ -4283,6 +4285,18 @@ sub path {
+ 	return $self->{path};
+ }
+ 
++sub url {
++	my $self = shift;
++
++	if (@_) {
++		my $url = shift;
++		$self->{url} = $url;
++		return;
++	}
++
++	return $self->{url};
++}
++
+ # for read-only access of old .rev_db formats
+ sub unlink_rev_db_symlink {
+ 	my ($self) = @_;
+-- 
+1.7.10.4
+
only in patch2:
unchanged:
--- git-1.7.10.4.orig/debian/diff/0030-git-svn-work-around-SVN-1.7-mishandling-of-svn-specia.diff
+++ git-1.7.10.4/debian/diff/0030-git-svn-work-around-SVN-1.7-mishandling-of-svn-specia.diff
@@ -0,0 +1,78 @@
+From 36f97461bb3b18f7b33fa0f82452dba2989085b1 Mon Sep 17 00:00:00 2001
+From: Jonathan Nieder <jrnieder@gmail.com>
+Date: Tue, 9 Oct 2012 03:12:39 -0700
+Subject: git svn: work around SVN 1.7 mishandling of svn:special changes
+
+Subversion represents symlinks as ordinary files with content starting
+with "link " and the svn:special property set to "*".  Thus a file can
+switch between being a symlink and a non-symlink simply by toggling
+its svn:special property, and new checkouts will automatically write a
+file of the appropriate type.  Likewise, in subversion 1.6 and older,
+running "svn update" would notice changes in filetype and update the
+working copy appropriately.
+
+Starting in subversion 1.7 (issue 4091), changes to the svn:special
+property trip an assertion instead:
+
+	$ svn up svn-tree
+	Updating 'svn-tree':
+	svn: E235000: In file 'subversion/libsvn_wc/update_editor.c' \
+	line 1583: assertion failed (action == svn_wc_conflict_action_edit \
+	|| action == svn_wc_conflict_action_delete || action == \
+	svn_wc_conflict_action_replace)
+
+Revisions prepared with ordinary svn commands ("svn add" and not "svn
+propset") don't trip this because they represent these filetype
+changes using a replace operation, which is approximately equivalent
+to removal followed by adding a new file and works fine.  Follow suit.
+
+Noticed using t9100.  After this change, git-svn's file-to-symlink
+changes are sent in a format that modern "svn update" can handle and
+tests t9100.11-13 pass again.
+
+Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
+Signed-off-by: Eric Wong <normalperson@yhbt.net>
+Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
+---
+ git-svn.perl |   25 ++++++++++++++++++++++++-
+ 1 file changed, 24 insertions(+), 1 deletion(-)
+
+diff --git a/git-svn.perl b/git-svn.perl
+index 9d57aa0..40ccdd5 100755
+--- a/git-svn.perl
++++ b/git-svn.perl
+@@ -5439,7 +5439,30 @@ sub M {
+ 	$self->close_file($fbat,undef,$self->{pool});
+ }
+ 
+-sub T { shift->M(@_) }
++sub T {
++	my ($self, $m, $deletions) = @_;
++
++	# Work around subversion issue 4091: toggling the "is a
++	# symlink" property requires removing and re-adding a
++	# file or else "svn up" on affected clients trips an
++	# assertion and aborts.
++	if (($m->{mode_b} =~ /^120/ && $m->{mode_a} !~ /^120/) ||
++	    ($m->{mode_b} !~ /^120/ && $m->{mode_a} =~ /^120/)) {
++		$self->D({
++			mode_a => $m->{mode_a}, mode_b => '000000',
++			sha1_a => $m->{sha1_a}, sha1_b => '0' x 40,
++			chg => 'D', file_b => $m->{file_b}
++		});
++		$self->A({
++			mode_a => '000000', mode_b => $m->{mode_b},
++			sha1_a => '0' x 40, sha1_b => $m->{sha1_b},
++			chg => 'A', file_b => $m->{file_b}
++		});
++		return;
++	}
++
++	$self->M($m, $deletions);
++}
+ 
+ sub change_file_prop {
+ 	my ($self, $fbat, $pname, $pval) = @_;
+-- 
+1.7.10.4
+
only in patch2:
unchanged:
--- git-1.7.10.4.orig/debian/diff/0018-git-svn-use-SVN-1.7-to-canonicalize-when-possible.diff
+++ git-1.7.10.4/debian/diff/0018-git-svn-use-SVN-1.7-to-canonicalize-when-possible.diff
@@ -0,0 +1,51 @@
+From c0a72bbb2a7e4fd244cfcb268c55f9af8ee63274 Mon Sep 17 00:00:00 2001
+From: "Michael G. Schwern" <schwern@pobox.com>
+Date: Sat, 28 Jul 2012 02:38:27 -0700
+Subject: git-svn: use SVN 1.7 to canonicalize when possible
+
+No change on SVN 1.6.  The tests all pass with SVN 1.6 if
+canonicalize_url() does nothing, so tests passing doesn't have
+much meaning.
+
+The tests are so messed up right now with SVN 1.7 it isn't really
+useful to check.  They will be useful later.
+
+[ew: commit title]
+[jn: load SVN::Base on demand]
+
+Signed-off-by: Eric Wong <normalperson@yhbt.net>
+Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
+---
+ git-svn.perl |   16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+diff --git a/git-svn.perl b/git-svn.perl
+index 18f963d..02249b6 100755
+--- a/git-svn.perl
++++ b/git-svn.perl
+@@ -1252,6 +1252,22 @@ sub canonicalize_path {
+ }
+ 
+ sub canonicalize_url {
++	my $url = shift;
++
++	::_req_svn();
++
++	# The 1.7 way to do it
++	if ( defined &SVN::_Core::svn_uri_canonicalize ) {
++		return SVN::_Core::svn_uri_canonicalize($url);
++	}
++	# There wasn't a 1.6 way to do it, so we do it ourself.
++	else {
++		return _canonicalize_url_ourselves($url);
++	}
++}
++
++
++sub _canonicalize_url_ourselves {
+ 	my ($url) = @_;
+ 	$url =~ s#^([^:]+://[^/]*/)(.*)$#$1 . canonicalize_path($2)#e;
+ 	return $url;
+-- 
+1.7.10.4
+
only in patch2:
unchanged:
--- git-1.7.10.4.orig/debian/diff/0027-git-svn-canonicalize-newly-minted-URLs.diff
+++ git-1.7.10.4/debian/diff/0027-git-svn-canonicalize-newly-minted-URLs.diff
@@ -0,0 +1,125 @@
+From f2550fc85e6fec6edb9740018ae913defb6beb49 Mon Sep 17 00:00:00 2001
+From: "Michael G. Schwern" <schwern@pobox.com>
+Date: Sat, 28 Jul 2012 02:47:51 -0700
+Subject: git-svn: canonicalize newly-minted URLs
+
+Go through all the spots that use the new add_path_to_url() to
+make a new URL and canonicalize them.
+
+* copyfrom_path has to be canonicalized else find_parent_branch
+  will get confused
+
+* due to the `canonicalize_url($full_url) ne $full_url)` line of
+  logic in gs_do_switch(), $full_url is left alone until after.
+
+At this point SVN 1.7 passes except for 3 tests in
+t9100-git-svn-basic.sh that look like an SVN bug to do with
+symlinks.
+
+[ew: commit title]
+
+Signed-off-by: Eric Wong <normalperson@yhbt.net>
+Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
+---
+ git-svn.perl |   27 +++++++++++++++++++++------
+ 1 file changed, 21 insertions(+), 6 deletions(-)
+
+diff --git a/git-svn.perl b/git-svn.perl
+index d00234d..9d57aa0 100755
+--- a/git-svn.perl
++++ b/git-svn.perl
+@@ -2461,6 +2461,8 @@ sub init_remote_config {
+ sub find_by_url { # repos_root and, path are optional
+ 	my ($class, $full_url, $repos_root, $path) = @_;
+ 
++	$full_url = ::canonicalize_url($full_url);
++
+ 	return undef unless defined $full_url;
+ 	remove_username($full_url);
+ 	remove_username($repos_root) if defined $repos_root;
+@@ -2499,6 +2501,11 @@ sub find_by_url { # repos_root and, path are optional
+ 			}
+ 			$p =~ s#^\Q$z\E(?:/|$)#$prefix# or next;
+ 		}
++
++		# remote fetch paths are not URI escaped.  Decode ours
++		# so they match
++		$p = uri_decode($p);
++
+ 		foreach my $f (keys %$fetch) {
+ 			next if $f ne $p;
+ 			return Git::SVN->new($fetch->{$f}, $repo_id, $f);
+@@ -3033,18 +3040,18 @@ sub rewrite_uuid {
+ sub metadata_url {
+ 	my ($self) = @_;
+ 	my $url = $self->rewrite_root || $self->url;
+-	return ::add_path_to_url( $url, $self->path );
++	return ::canonicalize_url( ::add_path_to_url( $url, $self->path ) );
+ }
+ 
+ sub full_url {
+ 	my ($self) = @_;
+-	return ::add_path_to_url( $self->url, $self->path );
++	return ::canonicalize_url( ::add_path_to_url( $self->url, $self->path ) );
+ }
+ 
+ sub full_pushurl {
+ 	my ($self) = @_;
+ 	if ($self->{pushurl}) {
+-		return ::add_path_to_url( $self->{pushurl}, $self->path );
++		return ::canonicalize_url( ::add_path_to_url( $self->{pushurl}, $self->path ) );
+ 	} else {
+ 		return $self->full_url;
+ 	}
+@@ -3212,7 +3219,7 @@ sub find_parent_branch {
+ 	my $r = $i->{copyfrom_rev};
+ 	my $repos_root = $self->ra->{repos_root};
+ 	my $url = $self->ra->url;
+-	my $new_url = ::add_path_to_url( $url, $branch_from );
++	my $new_url = ::canonicalize_url( ::add_path_to_url( $url, $branch_from ) );
+ 	print STDERR  "Found possible branch point: ",
+ 	              "$new_url => ", $self->full_url, ", $r\n"
+ 	              unless $::_q > 1;
+@@ -3953,7 +3960,9 @@ sub make_log_entry {
+ 		$email ||= "$author\@$uuid";
+ 		$commit_email ||= "$author\@$uuid";
+ 	} elsif ($self->use_svnsync_props) {
+-		my $full_url = ::add_path_to_url( $self->svnsync->{url}, $self->path );
++		my $full_url = ::canonicalize_url(
++			::add_path_to_url( $self->svnsync->{url}, $self->path )
++		);
+ 		remove_username($full_url);
+ 		my $uuid = $self->svnsync->{uuid};
+ 		$log_entry{metadata} = "$full_url\@$rev $uuid";
+@@ -5634,6 +5643,7 @@ sub new {
+ 			$Git::SVN::Prompt::_no_auth_cache = 1;
+ 		}
+ 	} # no warnings 'once'
++
+ 	my $self = SVN::Ra->new(url => $url, auth => $baton,
+ 	                      config => $config,
+ 			      pool => SVN::Pool->new,
+@@ -5730,6 +5740,7 @@ sub get_log {
+ 				qw/copyfrom_path copyfrom_rev action/;
+ 			if ($s{'copyfrom_path'}) {
+ 				$s{'copyfrom_path'} =~ s/$prefix_regex//;
++				$s{'copyfrom_path'} = ::canonicalize_path($s{'copyfrom_path'});
+ 			}
+ 			$_[0]{$p} = \%s;
+ 		}
+@@ -5832,7 +5843,11 @@ sub gs_do_switch {
+ 		$ra = Git::SVN::Ra->new($full_url);
+ 		$ra_invalid = 1;
+ 	} elsif ($old_url ne $full_url) {
+-		SVN::_Ra::svn_ra_reparent($self->{session}, $full_url, $pool);
++		SVN::_Ra::svn_ra_reparent(
++			$self->{session},
++			::canonicalize_url($full_url),
++			$pool
++		);
+ 		$self->url($full_url);
+ 		$reparented = 1;
+ 	}
+-- 
+1.7.10.4
+
only in patch2:
unchanged:
--- git-1.7.10.4.orig/debian/diff/0019-git-svn-factor-out-_collapse_dotdot-function.diff
+++ git-1.7.10.4/debian/diff/0019-git-svn-factor-out-_collapse_dotdot-function.diff
@@ -0,0 +1,57 @@
+From 7f944a129dfd3662bdbfaa09c9ff8f7ba177cf45 Mon Sep 17 00:00:00 2001
+From: "Michael G. Schwern" <schwern@pobox.com>
+Date: Sat, 28 Jul 2012 02:38:28 -0700
+Subject: git-svn: factor out _collapse_dotdot function
+
+The SVN API functions will not accept ../foo but their canonicalization
+functions will not collapse it.  So we'll have to do it ourselves.
+
+_collapse_dotdot() works better than the existing regex did.
+
+This will be used shortly when canonicalize_path() starts using the
+SVN API.
+
+[ew: commit title]
+[jn: drop unused unit test]
+
+Signed-off-by: Eric Wong <normalperson@yhbt.net>
+Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
+---
+ git-svn.perl |   14 +++++++++++++-
+ 1 file changed, 13 insertions(+), 1 deletion(-)
+
+diff --git a/git-svn.perl b/git-svn.perl
+index 02249b6..045105b 100755
+--- a/git-svn.perl
++++ b/git-svn.perl
+@@ -1232,6 +1232,18 @@ sub cmd_mkdirs {
+ 	$gs->mkemptydirs($_revision);
+ }
+ 
++# Turn foo/../bar into bar
++sub _collapse_dotdot {
++	my $path = shift;
++
++	1 while $path =~ s{/[^/]+/+\.\.}{};
++	1 while $path =~ s{[^/]+/+\.\./}{};
++	1 while $path =~ s{[^/]+/+\.\.}{};
++
++	return $path;
++}
++
++
+ sub canonicalize_path {
+ 	my ($path) = @_;
+ 	my $dot_slash_added = 0;
+@@ -1243,7 +1255,7 @@ sub canonicalize_path {
+ 	# good reason), so let's do this manually.
+ 	$path =~ s#/+#/#g;
+ 	$path =~ s#/\.(?:/|$)#/#g;
+-	$path =~ s#/[^/]+/\.\.##g;
++	$path = _collapse_dotdot($path);
+ 	$path =~ s#/$##g;
+ 	$path =~ s#^\./## if $dot_slash_added;
+ 	$path =~ s#^/##;
+-- 
+1.7.10.4
+
only in patch2:
unchanged:
--- git-1.7.10.4.orig/debian/diff/0016-use-Git-SVN-path-accessor-globally.diff
+++ git-1.7.10.4/debian/diff/0016-use-Git-SVN-path-accessor-globally.diff
@@ -0,0 +1,130 @@
+From 46fc943fe2d122080c1a0222fe8b97500a781c49 Mon Sep 17 00:00:00 2001
+From: "Michael G. Schwern" <schwern@pobox.com>
+Date: Fri, 27 Jul 2012 13:00:51 -0700
+Subject: use Git::SVN->path accessor globally
+
+No functional change.
+
+[ew: commit title]
+
+Signed-off-by: Eric Wong <normalperson@yhbt.net>
+Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
+---
+ git-svn.perl |   24 +++++++++++++-----------
+ 1 file changed, 13 insertions(+), 11 deletions(-)
+
+diff --git a/git-svn.perl b/git-svn.perl
+index d1294fc..68b3c28 100755
+--- a/git-svn.perl
++++ b/git-svn.perl
+@@ -1171,7 +1171,7 @@ sub cmd_show_ignore {
+ 	my ($url, $rev, $uuid, $gs) = working_head_info('HEAD');
+ 	$gs ||= Git::SVN->new;
+ 	my $r = (defined $_revision ? $_revision : $gs->ra->get_latest_revnum);
+-	$gs->prop_walk($gs->{path}, $r, sub {
++	$gs->prop_walk($gs->path, $r, sub {
+ 		my ($gs, $path, $props) = @_;
+ 		print STDOUT "\n# $path\n";
+ 		my $s = $props->{'svn:ignore'} or return;
+@@ -1187,7 +1187,7 @@ sub cmd_show_externals {
+ 	my ($url, $rev, $uuid, $gs) = working_head_info('HEAD');
+ 	$gs ||= Git::SVN->new;
+ 	my $r = (defined $_revision ? $_revision : $gs->ra->get_latest_revnum);
+-	$gs->prop_walk($gs->{path}, $r, sub {
++	$gs->prop_walk($gs->path, $r, sub {
+ 		my ($gs, $path, $props) = @_;
+ 		print STDOUT "\n# $path\n";
+ 		my $s = $props->{'svn:externals'} or return;
+@@ -1202,7 +1202,7 @@ sub cmd_create_ignore {
+ 	my ($url, $rev, $uuid, $gs) = working_head_info('HEAD');
+ 	$gs ||= Git::SVN->new;
+ 	my $r = (defined $_revision ? $_revision : $gs->ra->get_latest_revnum);
+-	$gs->prop_walk($gs->{path}, $r, sub {
++	$gs->prop_walk($gs->path, $r, sub {
+ 		my ($gs, $path, $props) = @_;
+ 		# $path is of the form /path/to/dir/
+ 		$path = '.' . $path;
+@@ -1372,7 +1372,7 @@ sub cmd_commit_diff {
+ 			      "the command-line\n", $usage);
+ 		}
+ 		$url = $gs->{url};
+-		$svn_path = $gs->{path};
++		$svn_path = $gs->path;
+ 	}
+ 	unless (defined $_revision) {
+ 		fatal("-r|--revision is a required argument\n", $usage);
+@@ -1610,6 +1610,8 @@ sub post_fetch_checkout {
+ sub complete_svn_url {
+ 	my ($url, $path) = @_;
+ 	$path =~ s#/+$##;
++
++	# If the path is not a URL...
+ 	if ($path !~ m#^[a-z\+]+://#) {
+ 		if (!defined $url || $url !~ m#^[a-z\+]+://#) {
+ 			fatal("E: '$path' is not a complete URL ",
+@@ -1646,7 +1648,7 @@ sub complete_url_ls_init {
+ 		    "wanted to set to: $gs->{url}\n";
+ 	}
+ 	command_oneline('config', $k, $gs->{url}) unless $orig_url;
+-	my $remote_path = "$gs->{path}/$repo_path";
++	my $remote_path = $gs->path . "/$repo_path";
+ 	$remote_path =~ s{%([0-9A-F]{2})}{chr hex($1)}ieg;
+ 	$remote_path =~ s#/+#/#g;
+ 	$remote_path =~ s#^/##g;
+@@ -3118,7 +3120,7 @@ sub find_parent_branch {
+ 			($base, $head) = parse_revision_argument(0, $r);
+ 		} else {
+ 			if ($r0 < $r) {
+-				$gs->ra->get_log([$gs->{path}], $r0 + 1, $r, 1,
++				$gs->ra->get_log([$gs->path], $r0 + 1, $r, 1,
+ 					0, 1, sub { $base = $_[1] - 1 });
+ 			}
+ 		}
+@@ -3140,7 +3142,7 @@ sub find_parent_branch {
+ 			# at the moment), so we can't rely on it
+ 			$self->{last_rev} = $r0;
+ 			$self->{last_commit} = $parent;
+-			$ed = SVN::Git::Fetcher->new($self, $gs->{path});
++			$ed = SVN::Git::Fetcher->new($self, $gs->path);
+ 			$gs->ra->gs_do_switch($r0, $rev, $gs,
+ 					      $self->full_url, $ed)
+ 			  or die "SVN connection failed somewhere...\n";
+@@ -4559,7 +4561,7 @@ sub _mark_empty_symlinks {
+ 	chomp(my $empty_blob = `git hash-object -t blob --stdin < /dev/null`);
+ 	my ($ls, $ctx) = command_output_pipe(qw/ls-tree -r -z/, $cmt);
+ 	local $/ = "\0";
+-	my $pfx = defined($switch_path) ? $switch_path : $git_svn->{path};
++	my $pfx = defined($switch_path) ? $switch_path : $git_svn->path;
+ 	$pfx .= '/' if length($pfx);
+ 	while (<$ls>) {
+ 		chomp;
+@@ -5692,7 +5694,7 @@ sub get_commit_editor {
+ sub gs_do_update {
+ 	my ($self, $rev_a, $rev_b, $gs, $editor) = @_;
+ 	my $new = ($rev_a == $rev_b);
+-	my $path = $gs->{path};
++	my $path = $gs->path;
+ 
+ 	if ($new && -e $gs->{index}) {
+ 		unlink $gs->{index} or die
+@@ -5728,7 +5730,7 @@ sub gs_do_update {
+ # svn_ra_reparent didn't work before 1.4)
+ sub gs_do_switch {
+ 	my ($self, $rev_a, $rev_b, $gs, $url_b, $editor) = @_;
+-	my $path = $gs->{path};
++	my $path = $gs->path;
+ 	my $pool = SVN::Pool->new;
+ 
+ 	my $full_url = $self->url;
+@@ -5772,7 +5774,7 @@ sub longest_common_path {
+ 	my $common_max = scalar @$gsv;
+ 
+ 	foreach my $gs (@$gsv) {
+-		my @tmp = split m#/#, $gs->{path};
++		my @tmp = split m#/#, $gs->path;
+ 		my $p = '';
+ 		foreach (@tmp) {
+ 			$p .= length($p) ? "/$_" : $_;
+-- 
+1.7.10.4
+
only in patch2:
unchanged:
--- git-1.7.10.4.orig/debian/diff/0013-Git-SVN-use-accessors-internally-for-path.diff
+++ git-1.7.10.4/debian/diff/0013-Git-SVN-use-accessors-internally-for-path.diff
@@ -0,0 +1,239 @@
+From 70160850b246250da4f856f11a37cb2a6ed04d32 Mon Sep 17 00:00:00 2001
+From: "Michael G. Schwern" <schwern@pobox.com>
+Date: Fri, 27 Jul 2012 13:00:48 -0700
+Subject: Git::SVN: use accessors internally for path
+
+Then later it can be canonicalized automatically rather than everywhere
+its used.
+
+Later patch will make other things use it.
+
+[ew: commit title, reformatted accessor to match existing style]
+[jn: backport by patching git-svn.perl instead of perl/Git/SVN.pm]
+
+Signed-off-by: Eric Wong <normalperson@yhbt.net>
+Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
+---
+ git-svn.perl |   86 +++++++++++++++++++++++++++++++++++++---------------------
+ 1 file changed, 55 insertions(+), 31 deletions(-)
+
+diff --git a/git-svn.perl b/git-svn.perl
+index ca038ec..99bbac3 100755
+--- a/git-svn.perl
++++ b/git-svn.perl
+@@ -2309,12 +2309,12 @@ sub init_remote_config {
+ 				print STDERR "Using higher level of URL: ",
+ 					     "$url => $min_url\n";
+ 			}
+-			my $old_path = $self->{path};
+-			$self->{path} = $url;
+-			$self->{path} =~ s!^\Q$min_url\E(/|$)!!;
++			my $old_path = $self->path;
++			$url =~ s!^\Q$min_url\E(/|$)!!;
+ 			if (length $old_path) {
+-				$self->{path} .= "/$old_path";
++				$url .= "/$old_path";
+ 			}
++			$self->path($url);
+ 			$url = $min_url;
+ 		}
+ 	}
+@@ -2338,11 +2338,13 @@ sub init_remote_config {
+ 	unless ($no_write) {
+ 		command_noisy('config',
+ 			      "svn-remote.$self->{repo_id}.url", $url);
+-		$self->{path} =~ s{^/}{};
+-		$self->{path} =~ s{%([0-9A-F]{2})}{chr hex($1)}ieg;
++		my $path = $self->path;
++		$path =~ s{^/}{};
++		$path =~ s{%([0-9A-F]{2})}{chr hex($1)}ieg;
++		$self->path($path);
+ 		command_noisy('config', '--add',
+ 			      "svn-remote.$self->{repo_id}.fetch",
+-			      "$self->{path}:".$self->refname);
++			      $self->path.":".$self->refname);
+ 	}
+ 	$self->{url} = $url;
+ }
+@@ -2430,17 +2432,22 @@ sub new {
+ 		}
+ 	}
+ 	my $self = _new($class, $repo_id, $ref_id, $path);
+-	if (!defined $self->{path} || !length $self->{path}) {
++	if (!defined $self->path || !length $self->path) {
+ 		my $fetch = command_oneline('config', '--get',
+ 		                            "svn-remote.$repo_id.fetch",
+ 		                            ":$ref_id\$") or
+ 		     die "Failed to read \"svn-remote.$repo_id.fetch\" ",
+ 		         "\":$ref_id\$\" in config\n";
+-		($self->{path}, undef) = split(/\s*:\s*/, $fetch);
++		my($path) = split(/\s*:\s*/, $fetch);
++		$self->path($path);
++	}
++	{
++		my $path = $self->path;
++		$path =~ s{/+}{/}g;
++		$path =~ s{\A/}{};
++		$path =~ s{/\z}{};
++		$self->path($path);
+ 	}
+-	$self->{path} =~ s{/+}{/}g;
+-	$self->{path} =~ s{\A/}{};
+-	$self->{path} =~ s{/\z}{};
+ 	$self->{url} = command_oneline('config', '--get',
+ 	                               "svn-remote.$repo_id.url") or
+                   die "Failed to read \"svn-remote.$repo_id.url\" in config\n";
+@@ -2562,7 +2569,7 @@ sub _set_svm_vars {
+ 	}
+ 
+ 	my $r = $ra->get_latest_revnum;
+-	my $path = $self->{path};
++	my $path = $self->path;
+ 	my %tried;
+ 	while (length $path) {
+ 		unless ($tried{"$self->{url}/$path"}) {
+@@ -2723,7 +2730,7 @@ sub prop_walk {
+ 	$path =~ s#^/*#/#g;
+ 	my $p = $path;
+ 	# Strip the irrelevant part of the path.
+-	$p =~ s#^/+\Q$self->{path}\E(/|$)#/#;
++	$p =~ s#^/+\Q@{[$self->path]}\E(/|$)#/#;
+ 	# Ensure the path is terminated by a `/'.
+ 	$p =~ s#/*$#/#;
+ 
+@@ -2744,7 +2751,7 @@ sub prop_walk {
+ 
+ 	foreach (sort keys %$dirent) {
+ 		next if $dirent->{$_}->{kind} != $SVN::Node::dir;
+-		$self->prop_walk($self->{path} . $p . $_, $rev, $sub);
++		$self->prop_walk($self->path . $p . $_, $rev, $sub);
+ 	}
+ }
+ 
+@@ -2915,19 +2922,19 @@ sub rewrite_uuid {
+ sub metadata_url {
+ 	my ($self) = @_;
+ 	($self->rewrite_root || $self->{url}) .
+-	   (length $self->{path} ? '/' . $self->{path} : '');
++	   (length $self->path ? '/' . $self->path : '');
+ }
+ 
+ sub full_url {
+ 	my ($self) = @_;
+-	$self->{url} . (length $self->{path} ? '/' . $self->{path} : '');
++	$self->{url} . (length $self->path ? '/' . $self->path : '');
+ }
+ 
+ sub full_pushurl {
+ 	my ($self) = @_;
+ 	if ($self->{pushurl}) {
+-		return $self->{pushurl} . (length $self->{path} ? '/' .
+-		       $self->{path} : '');
++		return $self->{pushurl} . (length $self->path ? '/' .
++		       $self->path : '');
+ 	} else {
+ 		return $self->full_url;
+ 	}
+@@ -3043,20 +3050,20 @@ sub do_git_commit {
+ 
+ sub match_paths {
+ 	my ($self, $paths, $r) = @_;
+-	return 1 if $self->{path} eq '';
+-	if (my $path = $paths->{"/$self->{path}"}) {
++	return 1 if $self->path eq '';
++	if (my $path = $paths->{"/".$self->path}) {
+ 		return ($path->{action} eq 'D') ? 0 : 1;
+ 	}
+-	$self->{path_regex} ||= qr/^\/\Q$self->{path}\E\//;
++	$self->{path_regex} ||= qr{^/\Q@{[$self->path]}\E/};
+ 	if (grep /$self->{path_regex}/, keys %$paths) {
+ 		return 1;
+ 	}
+ 	my $c = '';
+-	foreach (split m#/#, $self->{path}) {
++	foreach (split m#/#, $self->path) {
+ 		$c .= "/$_";
+ 		next unless ($paths->{$c} &&
+ 		             ($paths->{$c}->{action} =~ /^[AR]$/));
+-		if ($self->ra->check_path($self->{path}, $r) ==
++		if ($self->ra->check_path($self->path, $r) ==
+ 		    $SVN::Node::dir) {
+ 			return 1;
+ 		}
+@@ -3070,14 +3077,14 @@ sub find_parent_branch {
+ 	unless (defined $paths) {
+ 		my $err_handler = $SVN::Error::handler;
+ 		$SVN::Error::handler = \&Git::SVN::Ra::skip_unknown_revs;
+-		$self->ra->get_log([$self->{path}], $rev, $rev, 0, 1, 1,
++		$self->ra->get_log([$self->path], $rev, $rev, 0, 1, 1,
+ 				   sub { $paths = $_[0] });
+ 		$SVN::Error::handler = $err_handler;
+ 	}
+ 	return undef unless defined $paths;
+ 
+ 	# look for a parent from another branch:
+-	my @b_path_components = split m#/#, $self->{path};
++	my @b_path_components = split m#/#, $self->path;
+ 	my @a_path_components;
+ 	my $i;
+ 	while (@b_path_components) {
+@@ -3230,7 +3237,7 @@ sub mkemptydirs {
+ 		close $fh;
+ 	}
+ 
+-	my $strip = qr/\A\Q$self->{path}\E(?:\/|$)/;
++	my $strip = qr/\A\Q@{[$self->path]}\E(?:\/|$)/;
+ 	foreach my $d (sort keys %empty_dirs) {
+ 		$d = uri_decode($d);
+ 		$d =~ s/$strip//;
+@@ -3838,7 +3845,7 @@ sub make_log_entry {
+ 		$commit_email ||= "$author\@$uuid";
+ 	} elsif ($self->use_svnsync_props) {
+ 		my $full_url = $self->svnsync->{url};
+-		$full_url .= "/$self->{path}" if length $self->{path};
++		$full_url .= "/".$self->path if length $self->path;
+ 		remove_username($full_url);
+ 		my $uuid = $self->svnsync->{uuid};
+ 		$log_entry{metadata} = "$full_url\@$rev $uuid";
+@@ -3885,7 +3892,7 @@ sub set_tree {
+ 	                tree_b => $tree,
+ 	                editor_cb => sub {
+ 			       $self->set_tree_cb($log_entry, $tree, @_) },
+-	                svn_path => $self->{path} );
++	                svn_path => $self->path );
+ 	if (!SVN::Git::Editor->new(\%ed_opts)->apply_diff) {
+ 		print "No changes\nr$self->{last_rev} = $tree\n";
+ 	}
+@@ -4253,10 +4260,27 @@ sub _new {
+ 
+ 	$_[3] = $path = '' unless (defined $path);
+ 	mkpath([$dir]);
+-	bless {
++	my $obj = bless {
+ 		ref_id => $ref_id, dir => $dir, index => "$dir/index",
+-	        path => $path, config => "$ENV{GIT_DIR}/svn/config",
++	        config => "$ENV{GIT_DIR}/svn/config",
+ 	        map_root => "$dir/.rev_map", repo_id => $repo_id }, $class;
++
++	# Ensure it gets canonicalized
++	$obj->path($path);
++
++	return $obj;
++}
++
++sub path {
++	my $self = shift;
++
++	if (@_) {
++		my $path = shift;
++		$self->{path} = $path;
++		return;
++	}
++
++	return $self->{path};
+ }
+ 
+ # for read-only access of old .rev_db formats
+-- 
+1.7.10.4
+

Reply to: