Bug#692298: unblock: git/1:1.7.10.4-2
Julien Cristau wrote:
> On Sun, Nov 4, 2012 at 11:30:04 -0800, Jonathan Nieder wrote:
>> 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
[...]
> The first of those is big, and svn 1.7 is not in wheezy...
In light of [1], I'm happy to skip
b8c78e2a git svn: work around SVN 1.7 mishandling of svn:special changes
in a tpu upload. Proposed upload attached. What do you think?
Thanks,
Jonathan
[1] http://svn.apache.org/viewvc?view=revision&revision=1406870
From: Jonathan Nieder <jrnieder@gmail.com>
Date: Fri, 12 Oct 2012 13:26:39 -0700
Subject: debian: use YAML as platform-independent .git/svn/.caches format
On 32-bit arches, attempts to use "git svn fetch" on repositories
cloned using older perl currently produce
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
because the byteorder changed from 1234 to 12345678 when perl's
use64bit compile-time option was enabled.
Wait --- isn't Memoize::Storable's nstore option supposed to shield
users from such changing platform details? Unfortunately the 'nstore'
option has no effect due to a typo in its implementation (bug#677292).
Rather than coming up with a transition plan to account for git
repositories shared between machines with and without a fix to that
bug, let's move away from Memoize::Storable completely. A patch
applied upstream in 1.7.11 teaches 'git svn' to use libyaml when
available to read and write its caches under a new filename with a
simpler, platform-independent format. The Debian packaging can
complete the fix by adding a run-time dependency by git-svn on
libyaml-perl.
[jn: backport for wheezy: adjust version number and position in
debian/diff]
Analysis-by: Tim Retout <diocles@debian.org>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
---
debian/changelog | 11 +
debian/control | 4 +-
...-YAML-format-for-mergeinfo-cache-when-poss.diff | 294 +++++++++++++++++++++
3 files changed, 307 insertions(+), 2 deletions(-)
create mode 100644 debian/diff/0013-git-svn-use-YAML-format-for-mergeinfo-cache-when-poss.diff
diff --git a/debian/changelog b/debian/changelog
index 7558b3ab..575cd06a 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,14 @@
+git (1:1.7.10.4-1+wheezy1) testing; urgency=low
+
+ * debian/diff/0013-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> Sun, 18 Nov 2012 11:45:41 -0800
+
git (1:1.7.10.4-1) unstable; urgency=low
* new upstream point release (thx Jonathan Nieder).
diff --git a/debian/control b/debian/control
index e1f1a442..a8e188a2 100644
--- a/debian/control
+++ b/debian/control
@@ -5,7 +5,7 @@ Maintainer: Gerrit Pape <pape@smarden.org>
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 @@ Description: fast, scalable, distributed revision control system (cvs interopera
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)
diff --git a/debian/diff/0013-git-svn-use-YAML-format-for-mergeinfo-cache-when-poss.diff b/debian/diff/0013-git-svn-use-YAML-format-for-mergeinfo-cache-when-poss.diff
new file mode 100644
index 00000000..a0f1dfdb
--- /dev/null
+++ b/debian/diff/0013-git-svn-use-YAML-format-for-mergeinfo-cache-when-poss.diff
@@ -0,0 +1,294 @@
+From db8445cce70a6bdb014fb04624ebcce7f39ad905 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 ca038ec..77bab24 100755
+--- a/git-svn.perl
++++ b/git-svn.perl
+@@ -2031,6 +2031,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);
+
+@@ -3553,6 +3557,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.
+ {
+@@ -3565,22 +3580,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
+
--
1.8.0
Reply to: