{"thread":{"id":"31202","subject":"[PATCH] git svn: reset invalidates the memoized mergeinfo caches","startedAt":"2012-08-07T20:02:07Z","lastAt":"2012-08-10T21:30:28Z","messageCount":9,"participants":["Peter Baumann","Eric Wong","Steven Walter","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"196619","messageId":"20120807200207.GA10899@m62s10.vlinux.de","threadId":"31202","inReplyTo":null,"subject":"[PATCH] git svn: reset invalidates the memoized mergeinfo caches","fromName":"Peter Baumann","fromEmail":"waste.manager@gmx.de","sentAt":"2012-08-07T20:02:07Z","receivedAt":"2012-08-07T20:02:07Z","isPatch":true,"sender":{"key":"waste.manager@gmx.de","avatar":null},"body":"Since v1.7.0-rc2~11 (git-svn: persistent memoization, 2010-01-30),\ngit-svn has maintained some private per-repository caches in\n.git/svn/.caches to avoid refetching and recalculating some\nmergeinfo-related information with every 'git svn fetch'.\n\nThis memoization can cause problems, e.g consider the following case:\n\nSVN repo:\n\n  ... - a - b - c - m  <- trunk\n          \\        /\n            d  -  e    <- branch1\n\nThe Git import of the above repo is at commit 'a' and doesn't know about\nthe branch1. In case of an 'git svn rebase', only the trunk of the\nSVN repo is imported. During the creation of the git commit 'm', git svn\nuses the svn:mergeinfo property and tries to find the corresponding git\ncommit 'e' to create 'm' with 'c' and 'e' as parents. But git svn rebase\nonly imports the current branch so commit 'e' is not imported.\nTherefore git svn fails to create commit 'm' as a merge commit, because one\nof its parents is not known to git. The imported history looks like this:\n\n  ... - a - b - c - m  <- trunk\n\nA later 'git svn fetch' to import all branches can't rewrite the commit 'm'\nto add 'e' as a parent and to make it a real git merge commit, because it\nwas already imported.\n\nThat's why the imported history misses the merge and looks like this:\n\n  ... - a - b - c - m  <- trunk\n          \\\n            d  -  e    <- branch1\n\nRight now the only known workaround for importing 'm' as a merge is to\nforce reimporting 'm' again from SVN, e.g. via\n\n  $ git svn reset --revision $(git find-rev $c)\n  $ git svn fetch\n\nSadly, this is where the behavior has regressed: git svn reset doesn't\ninvalidate the old mergeinfo cache, which is no longer valid for the\nreimport, which leads to 'm' beeing imprted with only 'c' as parent.\n\nAs solution to this problem, this commit invalidates the mergeinfo cache\nto force correct recalculation of the parents.\n\nDuring development of this patch, several ways for invalidating the cache\nwhere considered. One of them is to use Memoize::flush_cache, which will\ncall the CLEAR method on the underlying Memoize persistency implementation.\nSadly, neither Memoize::Storable nor the newer Memoize::YAML module\nintroduced in 68f532f4ba888 could optionally be used implement the\nCLEAR method, so this is not an option.\n\nReseting the internal hash used to store the memoized values has the same\nproblem, because it calls the non-existing CLEAR method of the\nunderlying persistency layer, too.\n\nConsidering this and taking into account the different implementations\nof the memoization modules, where Memoize::Storable is not in our control,\nimplementing the missing CLEAR method is not an option, at least not if\nMemoize::Storable is still used.\n\nTherefore the easiest solution to clear the cache is to delete the files\non disk in 'git svn reset'. Normally, deleting the files behind the back\nof the memoization module would be problematic, because the in-memory\nrepresentation would still exist and contain wrong data. Fortunately, the\nmemoization is active in memory only for a small portion of the code.\nInvalidating the cache by deleting the files on disk if it isn't active\nshould be safe.\n\nSigned-off-by: Peter Baumann <waste.manager@gmx.de>\n---\n perl/Git/SVN.pm                        | 25 ++++++++++-\n t/t9163-git-svn-reset-clears-caches.sh | 79 ++++++++++++++++++++++++++++++++++\n 2 files changed, 102 insertions(+), 2 deletions(-)\n create mode 100755 t/t9163-git-svn-reset-clears-caches.sh\n\ndiff --git a/perl/Git/SVN.pm b/perl/Git/SVN.pm\nindex 0889145..430b366 100644\n--- a/perl/Git/SVN.pm\n+++ b/perl/Git/SVN.pm\n@@ -1634,6 +1634,22 @@ sub tie_for_persistent_memoization {\n \t\tMemoize::unmemoize 'has_no_changes';\n \t}\n \n+\tsub clear_memoized_mergeinfo_caches {\n+\t\tdie \"Only call this method in non-memoized context\" if ($memoized);\n+\n+\t\tmy $cache_path = \"$ENV{GIT_DIR}/svn/.caches/\";\n+\t\treturn unless -d $cache_path;\n+\n+\t\tfor my $cache_file ((\"$cache_path/lookup_svn_merge\",\n+\t\t\t\t     \"$cache_path/check_cherry_pick\",\n+\t\t\t\t     \"$cache_path/has_no_changes\")) {\n+\t\t\tfor my $suffix (qw(yaml db)) {\n+\t\t\t\tunlink(\"$cache_file.$suffix\");\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\n \tMemoize::memoize 'Git::SVN::repos_root';\n }\n \n@@ -2126,8 +2142,13 @@ sub rev_map_set {\n \n \tsysopen(my $fh, $db_lock, O_RDWR | O_CREAT)\n \t     or croak \"Couldn't open $db_lock: $!\\n\";\n-\t$update_ref eq 'reset' ? _rev_map_reset($fh, $rev, $commit) :\n-\t\t\t\t _rev_map_set($fh, $rev, $commit);\n+\tif ($update_ref eq 'reset') {\n+\t\t_rev_map_reset($fh, $rev, $commit);\n+\t\tclear_memoized_mergeinfo_caches();\n+\t} else {\n+\t\t_rev_map_set($fh, $rev, $commit);\n+\t}\n+\n \tif ($sync) {\n \t\t$fh->flush or die \"Couldn't flush $db_lock: $!\\n\";\n \t\t$fh->sync or die \"Couldn't sync $db_lock: $!\\n\";\ndiff --git a/t/t9163-git-svn-reset-clears-caches.sh b/t/t9163-git-svn-reset-clears-caches.sh\nnew file mode 100755\nindex 0000000..d604dfd\n--- /dev/null\n+++ b/t/t9163-git-svn-reset-clears-caches.sh\n@@ -0,0 +1,79 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2012 Peter Baumann\n+#\n+\n+test_description='git svn reset clears memoized caches'\n+. ./lib-git-svn.sh\n+\n+svn_ver=\"$(svn --version --quiet)\"\n+case $svn_ver in\n+0.* | 1.[0-4].*)\n+\tskip_all=\"skipping git-svn test - SVN too old ($svn_ver)\"\n+\ttest_done\n+\t;;\n+esac\n+\n+# ... a  -  b - m   <- trunk\n+#      \\       /\n+#       ... c       <- branch1\n+#\n+# ... = SVN Commits not interesting for this test, e.g. commits creating\n+#       the SVN repo layout\n+#\n+test_expect_success 'initialize source svn repo' '\n+\tsvn_cmd mkdir -m \"create trunk\" \"$svnrepo\"/trunk &&\n+\tsvn_cmd mkdir -m \"create branches\" \"$svnrepo/branches\" &&\n+\tsvn_cmd co \"$svnrepo\"/trunk \"$SVN_TREE\" &&\n+\t(\n+\t\tcd \"$SVN_TREE\" &&\n+\t\ttouch foo &&\n+\t\tsvn add foo &&\n+\t\tsvn commit -m \"a\" &&\n+\t\tsvn cp -m branch \"$svnrepo\"/trunk \"$svnrepo\"/branches/branch1 &&\n+\t\tsvn switch \"$svnrepo\"/branches/branch1 &&\n+\t\ttouch bar &&\n+\t\tsvn add bar &&\n+\t\tsvn commit -m b &&\n+\t\tsvn switch \"$svnrepo\"/trunk &&\n+\t\ttouch baz &&\n+\t\tsvn add baz &&\n+\t\tsvn commit -m c &&\n+\t\tsvn up &&\n+\t\tsvn merge \"$svnrepo\"/branches/branch1 &&\n+\t\tsvn commit -m \"m\"\n+\t) &&\n+\trm -rf \"$SVN_TREE\"\n+'\n+\n+test_expect_success 'fetch to merge-base (a)' '\n+\tgit svn init -s \"$svnrepo\" &&\n+\tgit svn fetch --revision BASE:3\n+'\n+\n+# git svn rebase looses the merge commit\n+#\n+# ... a  -  b - m  <- trunk\n+#      \\\n+#       ... c\n+#\n+test_expect_success 'rebase looses SVN merge (m)' '\n+\tgit svn rebase &&\n+\tgit svn fetch &&\n+\ttest 1 = $(git cat-file -p master|grep parent|wc -l)\n+'\n+\n+# git svn fetch creates correct history with merge commit\n+#\n+# ... a  -  b - m  <- trunk\n+#      \\       /\n+#       ... c      <- branch1\n+#\n+test_expect_success 'reset and fetch gets the SVN merge (m) correctly' '\n+\tgit svn reset -r 3 &&\n+\tgit reset --hard trunk && \n+\tgit svn fetch &&\n+\ttest 2 = $(git cat-file -p trunk|grep parent|wc -l)\n+'\n+\n+test_done\n-- \n1.7.12.rc0.10.g476109f\n"},{"id":"196621","messageId":"20120807204510.GA10453@dcvr.yhbt.net","threadId":"31202","inReplyTo":"20120807200207.GA10899@m62s10.vlinux.de","subject":"Re: [PATCH] git svn: reset invalidates the memoized mergeinfo caches","fromName":"Eric Wong","fromEmail":"normalperson@yhbt.net","sentAt":"2012-08-07T20:45:10Z","receivedAt":"2012-08-07T20:45:10Z","isPatch":true,"sender":{"key":"e@80x24.org","avatar":null},"body":"Peter Baumann <waste.manager@gmx.de> wrote:\n> Therefore the easiest solution to clear the cache is to delete the files\n> on disk in 'git svn reset'. Normally, deleting the files behind the back\n> of the memoization module would be problematic, because the in-memory\n> representation would still exist and contain wrong data. Fortunately, the\n> memoization is active in memory only for a small portion of the code.\n> Invalidating the cache by deleting the files on disk if it isn't active\n> should be safe.\n\nThanks for the patch and explanation.  A few comments below:\n\n> +\tsub clear_memoized_mergeinfo_caches {\n> +\t\tdie \"Only call this method in non-memoized context\" if ($memoized);\n> +\n> +\t\tmy $cache_path = \"$ENV{GIT_DIR}/svn/.caches/\";\n> +\t\treturn unless -d $cache_path;\n> +\n> +\t\tfor my $cache_file ((\"$cache_path/lookup_svn_merge\",\n> +\t\t\t\t     \"$cache_path/check_cherry_pick\",\n> +\t\t\t\t     \"$cache_path/has_no_changes\")) {\n> +\t\t\tfor my $suffix (qw(yaml db)) {\n> +\t\t\t\tunlink(\"$cache_file.$suffix\");\n\nNeed to check for unlink() errors (and ignore ENOENT).\n\n> @@ -2126,8 +2142,13 @@ sub rev_map_set {\n>  \n>  \tsysopen(my $fh, $db_lock, O_RDWR | O_CREAT)\n>  \t     or croak \"Couldn't open $db_lock: $!\\n\";\n> -\t$update_ref eq 'reset' ? _rev_map_reset($fh, $rev, $commit) :\n> -\t\t\t\t _rev_map_set($fh, $rev, $commit);\n> +\tif ($update_ref eq 'reset') {\n> +\t\t_rev_map_reset($fh, $rev, $commit);\n> +\t\tclear_memoized_mergeinfo_caches();\n\nBetter to clear_memoized_mergeinfo_caches() before _rev_map_reset()\nin case unlink() (or anything else) fails when clearing the cache.\n\n> +test_expect_success 'initialize source svn repo' '\n> +\tsvn_cmd mkdir -m \"create trunk\" \"$svnrepo\"/trunk &&\n> +\tsvn_cmd mkdir -m \"create branches\" \"$svnrepo/branches\" &&\n> +\tsvn_cmd co \"$svnrepo\"/trunk \"$SVN_TREE\" &&\n> +\t(\n> +\t\tcd \"$SVN_TREE\" &&\n> +\t\ttouch foo &&\n> +\t\tsvn add foo &&\n\nsvn_cmd here, too.\n\n> +\t\tsvn commit -m \"a\" &&\n> +\t\tsvn cp -m branch \"$svnrepo\"/trunk \"$svnrepo\"/branches/branch1 &&\n> +\t\tsvn switch \"$svnrepo\"/branches/branch1 &&\n> +\t\ttouch bar &&\n> +\t\tsvn add bar &&\n> +\t\tsvn commit -m b &&\n> +\t\tsvn switch \"$svnrepo\"/trunk &&\n> +\t\ttouch baz &&\n> +\t\tsvn add baz &&\n> +\t\tsvn commit -m c &&\n> +\t\tsvn up &&\n> +\t\tsvn merge \"$svnrepo\"/branches/branch1 &&\n> +\t\tsvn commit -m \"m\"\n> +\t) &&\n"},{"id":"196640","messageId":"20120808054129.GB10899@m62s10.vlinux.de","threadId":"31202","inReplyTo":"20120807204510.GA10453@dcvr.yhbt.net","subject":"Re: [PATCH] git svn: reset invalidates the memoized mergeinfo caches","fromName":"Peter Baumann","fromEmail":"waste.manager@gmx.de","sentAt":"2012-08-08T05:41:29Z","receivedAt":"2012-08-08T05:41:29Z","isPatch":true,"sender":{"key":"waste.manager@gmx.de","avatar":null},"body":"On Tue, Aug 07, 2012 at 08:45:10PM +0000, Eric Wong wrote:\n> Peter Baumann <waste.manager@gmx.de> wrote:\n> > Therefore the easiest solution to clear the cache is to delete the files\n> > on disk in 'git svn reset'. Normally, deleting the files behind the back\n> > of the memoization module would be problematic, because the in-memory\n> > representation would still exist and contain wrong data. Fortunately, the\n> > memoization is active in memory only for a small portion of the code.\n> > Invalidating the cache by deleting the files on disk if it isn't active\n> > should be safe.\n> \n> Thanks for the patch and explanation.  A few comments below:\n> \n> > +\tsub clear_memoized_mergeinfo_caches {\n> > +\t\tdie \"Only call this method in non-memoized context\" if ($memoized);\n> > +\n> > +\t\tmy $cache_path = \"$ENV{GIT_DIR}/svn/.caches/\";\n> > +\t\treturn unless -d $cache_path;\n> > +\n> > +\t\tfor my $cache_file ((\"$cache_path/lookup_svn_merge\",\n> > +\t\t\t\t     \"$cache_path/check_cherry_pick\",\n> > +\t\t\t\t     \"$cache_path/has_no_changes\")) {\n> > +\t\t\tfor my $suffix (qw(yaml db)) {\n> > +\t\t\t\tunlink(\"$cache_file.$suffix\");\n> \n> Need to check for unlink() errors (and ignore ENOENT).\n\n\nI'm not sure what you mean here: Aren't we screwed either way if unlinking\nthe file failed? There is nothhing we can do about it if e.g. the user doesn't\nhave the permissions to delete the file, besides terminating, e.g.\n\n\tfor my $cache_file ((\"$cache_path/lookup_svn_merge\",\n\t\t\t     \"$cache_path/check_cherry_pick\",\n\t\t\t     \"$cache_path/has_no_changes\")) {\n\t\tfor my $suffix (qw(yaml db)) {\n\t\t\tnext unless (-e \"$cache_file.$suffix\");\n\t\t\tunlink(\"$cache_file.$suffix\") or \n\t\t\t\tdie \"Failed to delete $cache_file.$suffix\";\n\t\t}\n\t}\n\n> \n> > @@ -2126,8 +2142,13 @@ sub rev_map_set {\n> >  \n> >  \tsysopen(my $fh, $db_lock, O_RDWR | O_CREAT)\n> >  \t     or croak \"Couldn't open $db_lock: $!\\n\";\n> > -\t$update_ref eq 'reset' ? _rev_map_reset($fh, $rev, $commit) :\n> > -\t\t\t\t _rev_map_set($fh, $rev, $commit);\n> > +\tif ($update_ref eq 'reset') {\n> > +\t\t_rev_map_reset($fh, $rev, $commit);\n> > +\t\tclear_memoized_mergeinfo_caches();\n> \n> Better to clear_memoized_mergeinfo_caches() before _rev_map_reset()\n> in case unlink() (or anything else) fails when clearing the cache.\n\nWill do.\n\n> \n> > +test_expect_success 'initialize source svn repo' '\n> > +\tsvn_cmd mkdir -m \"create trunk\" \"$svnrepo\"/trunk &&\n> > +\tsvn_cmd mkdir -m \"create branches\" \"$svnrepo/branches\" &&\n> > +\tsvn_cmd co \"$svnrepo\"/trunk \"$SVN_TREE\" &&\n> > +\t(\n> > +\t\tcd \"$SVN_TREE\" &&\n> > +\t\ttouch foo &&\n> > +\t\tsvn add foo &&\n> \n> svn_cmd here, too.\n\nWill do.\n> \n> > +\t\tsvn commit -m \"a\" &&\n> > +\t\tsvn cp -m branch \"$svnrepo\"/trunk \"$svnrepo\"/branches/branch1 &&\n> > +\t\tsvn switch \"$svnrepo\"/branches/branch1 &&\n> > +\t\ttouch bar &&\n> > +\t\tsvn add bar &&\n> > +\t\tsvn commit -m b &&\n> > +\t\tsvn switch \"$svnrepo\"/trunk &&\n> > +\t\ttouch baz &&\n> > +\t\tsvn add baz &&\n> > +\t\tsvn commit -m c &&\n> > +\t\tsvn up &&\n> > +\t\tsvn merge \"$svnrepo\"/branches/branch1 &&\n> > +\t\tsvn commit -m \"m\"\n> > +\t) &&\n> --\n> To unsubscribe from this list: send the line \"unsubscribe git\" in\n> the body of a message to majordomo@vger.kernel.org\n> More majordomo info at  http://vger.kernel.org/majordomo-info.html\n> \n"},{"id":"196717","messageId":"20120808225258.GA24956@dcvr.yhbt.net","threadId":"31202","inReplyTo":"20120808054129.GB10899@m62s10.vlinux.de","subject":"Re: [PATCH] git svn: reset invalidates the memoized mergeinfo caches","fromName":"Eric Wong","fromEmail":"normalperson@yhbt.net","sentAt":"2012-08-08T22:52:58Z","receivedAt":"2012-08-08T22:52:58Z","isPatch":true,"sender":{"key":"e@80x24.org","avatar":null},"body":"Peter Baumann <waste.manager@gmx.de> wrote:\n> On Tue, Aug 07, 2012 at 08:45:10PM +0000, Eric Wong wrote:\n> > Peter Baumann <waste.manager@gmx.de> wrote:\n> > > +\t\t\tfor my $suffix (qw(yaml db)) {\n> > > +\t\t\t\tunlink(\"$cache_file.$suffix\");\n> > \n> > Need to check for unlink() errors (and ignore ENOENT).\n> \n> I'm not sure what you mean here: Aren't we screwed either way if unlinking\n> the file failed? There is nothhing we can do about it if e.g. the user doesn't\n> have the permissions to delete the file, besides terminating, e.g.\n> \n> \tfor my $cache_file ((\"$cache_path/lookup_svn_merge\",\n> \t\t\t     \"$cache_path/check_cherry_pick\",\n> \t\t\t     \"$cache_path/has_no_changes\")) {\n> \t\tfor my $suffix (qw(yaml db)) {\n> \t\t\tnext unless (-e \"$cache_file.$suffix\");\n> \t\t\tunlink(\"$cache_file.$suffix\") or \n> \t\t\t\tdie \"Failed to delete $cache_file.$suffix\";\n> \t\t}\n\nYes we're screwed, but silent failure is the worst way to fail,\nespecially if it can lead us back to the problems your patch is meant to\naddress.\n\nPerhaps something like this (with $! to show the error):\n\n\t\t\tmy $file = \"$cache_file.$suffix\";\n\t\t\tnext unless -e $file;\n\t\t\tunlink($file) or die \"unlink($file) failed: $!\\n\";\n"},{"id":"196725","messageId":"20120809064253.GC10899@m62s10.vlinux.de","threadId":"31202","inReplyTo":"20120808225258.GA24956@dcvr.yhbt.net","subject":"[PATCH v2] git svn: reset invalidates the memoized mergeinfo caches","fromName":"Peter Baumann","fromEmail":"waste.manager@gmx.de","sentAt":"2012-08-09T06:42:53Z","receivedAt":"2012-08-09T06:42:53Z","isPatch":true,"sender":{"key":"waste.manager@gmx.de","avatar":null},"body":"On Wed, Aug 08, 2012 at 10:52:58PM +0000, Eric Wong wrote:\n> Peter Baumann <waste.manager@gmx.de> wrote:\n> > On Tue, Aug 07, 2012 at 08:45:10PM +0000, Eric Wong wrote:\n> > > Peter Baumann <waste.manager@gmx.de> wrote:\n> > > > +\t\t\tfor my $suffix (qw(yaml db)) {\n> > > > +\t\t\t\tunlink(\"$cache_file.$suffix\");\n> > > \n> > > Need to check for unlink() errors (and ignore ENOENT).\n> > \n> > I'm not sure what you mean here: Aren't we screwed either way if unlinking\n> > the file failed? There is nothhing we can do about it if e.g. the user doesn't\n> > have the permissions to delete the file, besides terminating, e.g.\n> > \n> > \tfor my $cache_file ((\"$cache_path/lookup_svn_merge\",\n> > \t\t\t     \"$cache_path/check_cherry_pick\",\n> > \t\t\t     \"$cache_path/has_no_changes\")) {\n> > \t\tfor my $suffix (qw(yaml db)) {\n> > \t\t\tnext unless (-e \"$cache_file.$suffix\");\n> > \t\t\tunlink(\"$cache_file.$suffix\") or \n> > \t\t\t\tdie \"Failed to delete $cache_file.$suffix\";\n> > \t\t}\n> \n> Yes we're screwed, but silent failure is the worst way to fail,\n> especially if it can lead us back to the problems your patch is meant to\n> address.\n> \n> Perhaps something like this (with $! to show the error):\n> \n> \t\t\tmy $file = \"$cache_file.$suffix\";\n> \t\t\tnext unless -e $file;\n> \t\t\tunlink($file) or die \"unlink($file) failed: $!\\n\";\n\nFirst, let me thank you for your review and your detailed explanation.\nI really appreciate it.\n\nI changed svn to svn_cmd in the test (and also some minor changes to\nthe comments and removing trailing whitespace) and switched the order of\nclear_memoized_mergeinfo_caches and _rev_map_reset as you asked for, so \nhopefully this is ready to go in.\n\n-- 8< --\nFrom: Peter Baumann <waste.manager@gmx.de>\nSubject: [PATCH] git svn: reset invalidates the memoized mergeinfo caches\n\nSince v1.7.0-rc2~11 (git-svn: persistent memoization, 2010-01-30),\ngit-svn has maintained some private per-repository caches in\n.git/svn/.caches to avoid refetching and recalculating some\nmergeinfo-related information with every 'git svn fetch'.\n\nThis memoization can cause problems, e.g consider the following case:\n\nSVN repo:\n\n  ... - a - b - c - m  <- trunk\n          \\        /\n            d  -  e    <- branch1\n\nThe Git import of the above repo is at commit 'a' and doesn't know about\nthe branch1. In case of an 'git svn rebase', only the trunk of the\nSVN repo is imported. During the creation of the git commit 'm', git svn\nuses the svn:mergeinfo property and tries to find the corresponding git\ncommit 'e' to create 'm' with 'c' and 'e' as parents. But git svn rebase\nonly imports the current branch so commit 'e' is not imported.\nTherefore git svn fails to create commit 'm' as a merge commit, because one\nof its parents is not known to git. The imported history looks like this:\n\n  ... - a - b - c - m  <- trunk\n\nA later 'git svn fetch' to import all branches can't rewrite the commit 'm'\nto add 'e' as a parent and to make it a real git merge commit, because it\nwas already imported.\n\nThat's why the imported history misses the merge and looks like this:\n\n  ... - a - b - c - m  <- trunk\n          \\\n            d  -  e    <- branch1\n\nRight now the only known workaround for importing 'm' as a merge is to\nforce reimporting 'm' again from SVN, e.g. via\n\n  $ git svn reset --revision $(git find-rev $c)\n  $ git svn fetch\n\nSadly, this is where the behavior has regressed: git svn reset doesn't\ninvalidate the old mergeinfo cache, which is no longer valid for the\nreimport, which leads to 'm' beeing imprted with only 'c' as parent.\n\nAs solution to this problem, this commit invalidates the mergeinfo cache\nto force correct recalculation of the parents.\n\nDuring development of this patch, several ways for invalidating the cache\nwhere considered. One of them is to use Memoize::flush_cache, which will\ncall the CLEAR method on the underlying Memoize persistency implementation.\nSadly, neither Memoize::Storable nor the newer Memoize::YAML module\nintroduced in 68f532f4ba888 could optionally be used implement the\nCLEAR method, so this is not an option.\n\nReseting the internal hash used to store the memoized values has the same\nproblem, because it calls the non-existing CLEAR method of the\nunderlying persistency layer, too.\n\nConsidering this and taking into account the different implementations\nof the memoization modules, where Memoize::Storable is not in our control,\nimplementing the missing CLEAR method is not an option, at least not if\nMemoize::Storable is still used.\n\nTherefore the easiest solution to clear the cache is to delete the files\non disk in 'git svn reset'. Normally, deleting the files behind the back\nof the memoization module would be problematic, because the in-memory\nrepresentation would still exist and contain wrong data. Fortunately, the\nmemoization is active in memory only for a small portion of the code.\nInvalidating the cache by deleting the files on disk if it isn't active\nshould be safe.\n\nSigned-off-by: Peter Baumann <waste.manager@gmx.de>\n---\n perl/Git/SVN.pm                        | 27 +++++++++++-\n t/t9163-git-svn-reset-clears-caches.sh | 78 ++++++++++++++++++++++++++++++++++\n 2 files changed, 103 insertions(+), 2 deletions(-)\n create mode 100755 t/t9163-git-svn-reset-clears-caches.sh\n\ndiff --git a/perl/Git/SVN.pm b/perl/Git/SVN.pm\nindex 0889145..acb2539 100644\n--- a/perl/Git/SVN.pm\n+++ b/perl/Git/SVN.pm\n@@ -1634,6 +1634,24 @@ sub tie_for_persistent_memoization {\n \t\tMemoize::unmemoize 'has_no_changes';\n \t}\n \n+\tsub clear_memoized_mergeinfo_caches {\n+\t\tdie \"Only call this method in non-memoized context\" if ($memoized);\n+\n+\t\tmy $cache_path = \"$ENV{GIT_DIR}/svn/.caches/\";\n+\t\treturn unless -d $cache_path;\n+\n+\t\tfor my $cache_file ((\"$cache_path/lookup_svn_merge\",\n+\t\t\t\t     \"$cache_path/check_cherry_pick\",\n+\t\t\t\t     \"$cache_path/has_no_changes\")) {\n+\t\t\tfor my $suffix (qw(yaml db)) {\n+\t\t\t\tmy $file = \"$cache_file.$suffix\";\n+\t\t\t\tnext unless -e $file;\n+\t\t\t\tunlink($file) or die \"unlink($file) failed: $!\\n\";\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\n \tMemoize::memoize 'Git::SVN::repos_root';\n }\n \n@@ -2126,8 +2144,13 @@ sub rev_map_set {\n \n \tsysopen(my $fh, $db_lock, O_RDWR | O_CREAT)\n \t     or croak \"Couldn't open $db_lock: $!\\n\";\n-\t$update_ref eq 'reset' ? _rev_map_reset($fh, $rev, $commit) :\n-\t\t\t\t _rev_map_set($fh, $rev, $commit);\n+\tif ($update_ref eq 'reset') {\n+\t\tclear_memoized_mergeinfo_caches();\n+\t\t_rev_map_reset($fh, $rev, $commit);\n+\t} else {\n+\t\t_rev_map_set($fh, $rev, $commit);\n+\t}\n+\n \tif ($sync) {\n \t\t$fh->flush or die \"Couldn't flush $db_lock: $!\\n\";\n \t\t$fh->sync or die \"Couldn't sync $db_lock: $!\\n\";\ndiff --git a/t/t9163-git-svn-reset-clears-caches.sh b/t/t9163-git-svn-reset-clears-caches.sh\nnew file mode 100755\nindex 0000000..cd4c662\n--- /dev/null\n+++ b/t/t9163-git-svn-reset-clears-caches.sh\n@@ -0,0 +1,78 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2012 Peter Baumann\n+#\n+\n+test_description='git svn reset clears memoized caches'\n+. ./lib-git-svn.sh\n+\n+svn_ver=\"$(svn --version --quiet)\"\n+case $svn_ver in\n+0.* | 1.[0-4].*)\n+\tskip_all=\"skipping git-svn test - SVN too old ($svn_ver)\"\n+\ttest_done\n+\t;;\n+esac\n+\n+# ... a  -  b - m   <- trunk\n+#      \\       /\n+#       ... c       <- branch1\n+#\n+# SVN Commits not interesting for this test are abbreviated with \"...\"\n+#\n+test_expect_success 'initialize source svn repo' '\n+\tsvn_cmd mkdir -m \"create trunk\" \"$svnrepo\"/trunk &&\n+\tsvn_cmd mkdir -m \"create branches\" \"$svnrepo/branches\" &&\n+\tsvn_cmd co \"$svnrepo\"/trunk \"$SVN_TREE\" &&\n+\t(\n+\t\tcd \"$SVN_TREE\" &&\n+\t\ttouch foo &&\n+\t\tsvn_cmd add foo &&\n+\t\tsvn_cmd commit -m \"a\" &&\n+\t\tsvn_cmd cp -m branch \"$svnrepo\"/trunk \"$svnrepo\"/branches/branch1 &&\n+\t\tsvn_cmd switch \"$svnrepo\"/branches/branch1 &&\n+\t\ttouch bar &&\n+\t\tsvn_cmd add bar &&\n+\t\tsvn_cmd commit -m b &&\n+\t\tsvn_cmd switch \"$svnrepo\"/trunk &&\n+\t\ttouch baz &&\n+\t\tsvn_cmd add baz &&\n+\t\tsvn_cmd commit -m c &&\n+\t\tsvn_cmd up &&\n+\t\tsvn_cmd merge \"$svnrepo\"/branches/branch1 &&\n+\t\tsvn_cmd commit -m \"m\"\n+\t) &&\n+\trm -rf \"$SVN_TREE\"\n+'\n+\n+test_expect_success 'fetch to merge-base (a)' '\n+\tgit svn init -s \"$svnrepo\" &&\n+\tgit svn fetch --revision BASE:3\n+'\n+\n+# git svn rebase looses the merge commit\n+#\n+# ... a  -  b - m  <- trunk\n+#      \\\n+#       ... c\n+#\n+test_expect_success 'rebase looses SVN merge (m)' '\n+\tgit svn rebase &&\n+\tgit svn fetch &&\n+\ttest 1 = $(git cat-file -p master|grep parent|wc -l)\n+'\n+\n+# git svn fetch creates correct history with merge commit\n+#\n+# ... a  -  b - m  <- trunk\n+#      \\       /\n+#       ... c      <- branch1\n+#\n+test_expect_success 'reset and fetch gets the SVN merge (m) correctly' '\n+\tgit svn reset -r 3 &&\n+\tgit reset --hard trunk &&\n+\tgit svn fetch &&\n+\ttest 2 = $(git cat-file -p trunk|grep parent|wc -l)\n+'\n+\n+test_done\n-- \n1.7.12.rc0.10.g476109f\n"},{"id":"196745","messageId":"CAK8d-aK_R0X36o_CyNgE=1PSX2AOd79bJNhbHzgL0vO7yj224g@mail.gmail.com","threadId":"31202","inReplyTo":"20120809064253.GC10899@m62s10.vlinux.de","subject":"Re: [PATCH v2] git svn: reset invalidates the memoized mergeinfo caches","fromName":"Steven Walter","fromEmail":"stevenrwalter@gmail.com","sentAt":"2012-08-09T17:35:25Z","receivedAt":"2012-08-09T17:35:25Z","isPatch":true,"sender":{"key":"stevenrwalter@gmail.com","avatar":"https://avatars.githubusercontent.com/u/79127?v=4"},"body":"Signed-off-by: Steven Walter <stevenrwalter@gmail.com>\n\nOn Thu, Aug 9, 2012 at 2:42 AM, Peter Baumann <waste.manager@gmx.de> wrote:\n> On Wed, Aug 08, 2012 at 10:52:58PM +0000, Eric Wong wrote:\n>> Peter Baumann <waste.manager@gmx.de> wrote:\n>> > On Tue, Aug 07, 2012 at 08:45:10PM +0000, Eric Wong wrote:\n>> > > Peter Baumann <waste.manager@gmx.de> wrote:\n>> > > > +                       for my $suffix (qw(yaml db)) {\n>> > > > +                               unlink(\"$cache_file.$suffix\");\n>> > >\n>> > > Need to check for unlink() errors (and ignore ENOENT).\n>> >\n>> > I'm not sure what you mean here: Aren't we screwed either way if unlinking\n>> > the file failed? There is nothhing we can do about it if e.g. the user doesn't\n>> > have the permissions to delete the file, besides terminating, e.g.\n>> >\n>> >     for my $cache_file ((\"$cache_path/lookup_svn_merge\",\n>> >                          \"$cache_path/check_cherry_pick\",\n>> >                          \"$cache_path/has_no_changes\")) {\n>> >             for my $suffix (qw(yaml db)) {\n>> >                     next unless (-e \"$cache_file.$suffix\");\n>> >                     unlink(\"$cache_file.$suffix\") or\n>> >                             die \"Failed to delete $cache_file.$suffix\";\n>> >             }\n>>\n>> Yes we're screwed, but silent failure is the worst way to fail,\n>> especially if it can lead us back to the problems your patch is meant to\n>> address.\n>>\n>> Perhaps something like this (with $! to show the error):\n>>\n>>                       my $file = \"$cache_file.$suffix\";\n>>                       next unless -e $file;\n>>                       unlink($file) or die \"unlink($file) failed: $!\\n\";\n>\n> First, let me thank you for your review and your detailed explanation.\n> I really appreciate it.\n>\n> I changed svn to svn_cmd in the test (and also some minor changes to\n> the comments and removing trailing whitespace) and switched the order of\n> clear_memoized_mergeinfo_caches and _rev_map_reset as you asked for, so\n> hopefully this is ready to go in.\n>\n> -- 8< --\n> From: Peter Baumann <waste.manager@gmx.de>\n> Subject: [PATCH] git svn: reset invalidates the memoized mergeinfo caches\n>\n> Since v1.7.0-rc2~11 (git-svn: persistent memoization, 2010-01-30),\n> git-svn has maintained some private per-repository caches in\n> .git/svn/.caches to avoid refetching and recalculating some\n> mergeinfo-related information with every 'git svn fetch'.\n>\n> This memoization can cause problems, e.g consider the following case:\n>\n> SVN repo:\n>\n>   ... - a - b - c - m  <- trunk\n>           \\        /\n>             d  -  e    <- branch1\n>\n> The Git import of the above repo is at commit 'a' and doesn't know about\n> the branch1. In case of an 'git svn rebase', only the trunk of the\n> SVN repo is imported. During the creation of the git commit 'm', git svn\n> uses the svn:mergeinfo property and tries to find the corresponding git\n> commit 'e' to create 'm' with 'c' and 'e' as parents. But git svn rebase\n> only imports the current branch so commit 'e' is not imported.\n> Therefore git svn fails to create commit 'm' as a merge commit, because one\n> of its parents is not known to git. The imported history looks like this:\n>\n>   ... - a - b - c - m  <- trunk\n>\n> A later 'git svn fetch' to import all branches can't rewrite the commit 'm'\n> to add 'e' as a parent and to make it a real git merge commit, because it\n> was already imported.\n>\n> That's why the imported history misses the merge and looks like this:\n>\n>   ... - a - b - c - m  <- trunk\n>           \\\n>             d  -  e    <- branch1\n>\n> Right now the only known workaround for importing 'm' as a merge is to\n> force reimporting 'm' again from SVN, e.g. via\n>\n>   $ git svn reset --revision $(git find-rev $c)\n>   $ git svn fetch\n>\n> Sadly, this is where the behavior has regressed: git svn reset doesn't\n> invalidate the old mergeinfo cache, which is no longer valid for the\n> reimport, which leads to 'm' beeing imprted with only 'c' as parent.\n>\n> As solution to this problem, this commit invalidates the mergeinfo cache\n> to force correct recalculation of the parents.\n>\n> During development of this patch, several ways for invalidating the cache\n> where considered. One of them is to use Memoize::flush_cache, which will\n> call the CLEAR method on the underlying Memoize persistency implementation.\n> Sadly, neither Memoize::Storable nor the newer Memoize::YAML module\n> introduced in 68f532f4ba888 could optionally be used implement the\n> CLEAR method, so this is not an option.\n>\n> Reseting the internal hash used to store the memoized values has the same\n> problem, because it calls the non-existing CLEAR method of the\n> underlying persistency layer, too.\n>\n> Considering this and taking into account the different implementations\n> of the memoization modules, where Memoize::Storable is not in our control,\n> implementing the missing CLEAR method is not an option, at least not if\n> Memoize::Storable is still used.\n>\n> Therefore the easiest solution to clear the cache is to delete the files\n> on disk in 'git svn reset'. Normally, deleting the files behind the back\n> of the memoization module would be problematic, because the in-memory\n> representation would still exist and contain wrong data. Fortunately, the\n> memoization is active in memory only for a small portion of the code.\n> Invalidating the cache by deleting the files on disk if it isn't active\n> should be safe.\n>\n> Signed-off-by: Peter Baumann <waste.manager@gmx.de>\n> ---\n>  perl/Git/SVN.pm                        | 27 +++++++++++-\n>  t/t9163-git-svn-reset-clears-caches.sh | 78 ++++++++++++++++++++++++++++++++++\n>  2 files changed, 103 insertions(+), 2 deletions(-)\n>  create mode 100755 t/t9163-git-svn-reset-clears-caches.sh\n>\n> diff --git a/perl/Git/SVN.pm b/perl/Git/SVN.pm\n> index 0889145..acb2539 100644\n> --- a/perl/Git/SVN.pm\n> +++ b/perl/Git/SVN.pm\n> @@ -1634,6 +1634,24 @@ sub tie_for_persistent_memoization {\n>                 Memoize::unmemoize 'has_no_changes';\n>         }\n>\n> +       sub clear_memoized_mergeinfo_caches {\n> +               die \"Only call this method in non-memoized context\" if ($memoized);\n> +\n> +               my $cache_path = \"$ENV{GIT_DIR}/svn/.caches/\";\n> +               return unless -d $cache_path;\n> +\n> +               for my $cache_file ((\"$cache_path/lookup_svn_merge\",\n> +                                    \"$cache_path/check_cherry_pick\",\n> +                                    \"$cache_path/has_no_changes\")) {\n> +                       for my $suffix (qw(yaml db)) {\n> +                               my $file = \"$cache_file.$suffix\";\n> +                               next unless -e $file;\n> +                               unlink($file) or die \"unlink($file) failed: $!\\n\";\n> +                       }\n> +               }\n> +       }\n> +\n> +\n>         Memoize::memoize 'Git::SVN::repos_root';\n>  }\n>\n> @@ -2126,8 +2144,13 @@ sub rev_map_set {\n>\n>         sysopen(my $fh, $db_lock, O_RDWR | O_CREAT)\n>              or croak \"Couldn't open $db_lock: $!\\n\";\n> -       $update_ref eq 'reset' ? _rev_map_reset($fh, $rev, $commit) :\n> -                                _rev_map_set($fh, $rev, $commit);\n> +       if ($update_ref eq 'reset') {\n> +               clear_memoized_mergeinfo_caches();\n> +               _rev_map_reset($fh, $rev, $commit);\n> +       } else {\n> +               _rev_map_set($fh, $rev, $commit);\n> +       }\n> +\n>         if ($sync) {\n>                 $fh->flush or die \"Couldn't flush $db_lock: $!\\n\";\n>                 $fh->sync or die \"Couldn't sync $db_lock: $!\\n\";\n> diff --git a/t/t9163-git-svn-reset-clears-caches.sh b/t/t9163-git-svn-reset-clears-caches.sh\n> new file mode 100755\n> index 0000000..cd4c662\n> --- /dev/null\n> +++ b/t/t9163-git-svn-reset-clears-caches.sh\n> @@ -0,0 +1,78 @@\n> +#!/bin/sh\n> +#\n> +# Copyright (c) 2012 Peter Baumann\n> +#\n> +\n> +test_description='git svn reset clears memoized caches'\n> +. ./lib-git-svn.sh\n> +\n> +svn_ver=\"$(svn --version --quiet)\"\n> +case $svn_ver in\n> +0.* | 1.[0-4].*)\n> +       skip_all=\"skipping git-svn test - SVN too old ($svn_ver)\"\n> +       test_done\n> +       ;;\n> +esac\n> +\n> +# ... a  -  b - m   <- trunk\n> +#      \\       /\n> +#       ... c       <- branch1\n> +#\n> +# SVN Commits not interesting for this test are abbreviated with \"...\"\n> +#\n> +test_expect_success 'initialize source svn repo' '\n> +       svn_cmd mkdir -m \"create trunk\" \"$svnrepo\"/trunk &&\n> +       svn_cmd mkdir -m \"create branches\" \"$svnrepo/branches\" &&\n> +       svn_cmd co \"$svnrepo\"/trunk \"$SVN_TREE\" &&\n> +       (\n> +               cd \"$SVN_TREE\" &&\n> +               touch foo &&\n> +               svn_cmd add foo &&\n> +               svn_cmd commit -m \"a\" &&\n> +               svn_cmd cp -m branch \"$svnrepo\"/trunk \"$svnrepo\"/branches/branch1 &&\n> +               svn_cmd switch \"$svnrepo\"/branches/branch1 &&\n> +               touch bar &&\n> +               svn_cmd add bar &&\n> +               svn_cmd commit -m b &&\n> +               svn_cmd switch \"$svnrepo\"/trunk &&\n> +               touch baz &&\n> +               svn_cmd add baz &&\n> +               svn_cmd commit -m c &&\n> +               svn_cmd up &&\n> +               svn_cmd merge \"$svnrepo\"/branches/branch1 &&\n> +               svn_cmd commit -m \"m\"\n> +       ) &&\n> +       rm -rf \"$SVN_TREE\"\n> +'\n> +\n> +test_expect_success 'fetch to merge-base (a)' '\n> +       git svn init -s \"$svnrepo\" &&\n> +       git svn fetch --revision BASE:3\n> +'\n> +\n> +# git svn rebase looses the merge commit\n> +#\n> +# ... a  -  b - m  <- trunk\n> +#      \\\n> +#       ... c\n> +#\n> +test_expect_success 'rebase looses SVN merge (m)' '\n> +       git svn rebase &&\n> +       git svn fetch &&\n> +       test 1 = $(git cat-file -p master|grep parent|wc -l)\n> +'\n> +\n> +# git svn fetch creates correct history with merge commit\n> +#\n> +# ... a  -  b - m  <- trunk\n> +#      \\       /\n> +#       ... c      <- branch1\n> +#\n> +test_expect_success 'reset and fetch gets the SVN merge (m) correctly' '\n> +       git svn reset -r 3 &&\n> +       git reset --hard trunk &&\n> +       git svn fetch &&\n> +       test 2 = $(git cat-file -p trunk|grep parent|wc -l)\n> +'\n> +\n> +test_done\n> --\n> 1.7.12.rc0.10.g476109f\n>\n\n\n\n-- \n-Steven Walter <stevenrwalter@gmail.com>\n\"The rotter who simpers that he sees no difference between the power\nof the dollar and the power of the whip, ought to learn the difference\non his own hide.\"\n    -Francisco d'Anconia, Atlas Shrugged\n"},{"id":"196832","messageId":"20120810202211.GA16606@dcvr.yhbt.net","threadId":"31202","inReplyTo":"20120809064253.GC10899@m62s10.vlinux.de","subject":"Re: [PATCH v2] git svn: reset invalidates the memoized mergeinfo caches","fromName":"Eric Wong","fromEmail":"normalperson@yhbt.net","sentAt":"2012-08-10T20:22:11Z","receivedAt":"2012-08-10T20:22:11Z","isPatch":true,"sender":{"key":"e@80x24.org","avatar":null},"body":"Peter Baumann <waste.manager@gmx.de> wrote:\n> First, let me thank you for your review and your detailed explanation.\n> I really appreciate it.\n\nYou're welcome, Peter.  Thanks again for the patch.  I've signed-off and\npushed for Junio.\n\nThe following changes since commit 034161a94e827ef05790b1c7ce5a6e3e740c864e:\n\n  Merge git://github.com/git-l10n/git-po (2012-08-09 10:51:46 -0700)\n\nare available in the git repository at:\n\n\n  git://bogomips.org/git-svn for-git-master\n\nfor you to fetch changes up to 61b472ed8b090a3e9240590c85041120a54dd268:\n\n  git svn: reset invalidates the memoized mergeinfo caches (2012-08-10 19:53:18 +0000)\n\n----------------------------------------------------------------\nPeter Baumann (1):\n      git svn: reset invalidates the memoized mergeinfo caches\n\nRobert Luberda (1):\n      git svn: handle errors and concurrent commits in dcommit\n\n git-svn.perl                           |  74 ++++++++---\n perl/Git/SVN.pm                        |  27 ++++-\n t/t9163-git-svn-reset-clears-caches.sh |  78 ++++++++++++\n t/t9164-git-svn-dcommit-concrrent.sh   | 216 +++++++++++++++++++++++++++++++++\n 4 files changed, 374 insertions(+), 21 deletions(-)\n create mode 100755 t/t9163-git-svn-reset-clears-caches.sh\n create mode 100755 t/t9164-git-svn-dcommit-concrrent.sh\n"},{"id":"196838","messageId":"7vmx22iggu.fsf@alter.siamese.dyndns.org","threadId":"31202","inReplyTo":"20120810202211.GA16606@dcvr.yhbt.net","subject":"Re: [PATCH v2] git svn: reset invalidates the memoized mergeinfo caches","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-08-10T21:29:05Z","receivedAt":"2012-08-10T21:29:05Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Eric Wong <normalperson@yhbt.net> writes:\n\n> Peter Baumann <waste.manager@gmx.de> wrote:\n>> First, let me thank you for your review and your detailed explanation.\n>> I really appreciate it.\n>\n> You're welcome, Peter.  Thanks again for the patch.  I've signed-off and\n> pushed for Junio.\n>\n> The following changes since commit 034161a94e827ef05790b1c7ce5a6e3e740c864e:\n>\n>   Merge git://github.com/git-l10n/git-po (2012-08-09 10:51:46 -0700)\n>\n> are available in the git repository at:\n>\n>\n>   git://bogomips.org/git-svn for-git-master\n>\n> for you to fetch changes up to 61b472ed8b090a3e9240590c85041120a54dd268:\n>\n>   git svn: reset invalidates the memoized mergeinfo caches (2012-08-10 19:53:18 +0000)\n>\n> ----------------------------------------------------------------\n> Peter Baumann (1):\n>       git svn: reset invalidates the memoized mergeinfo caches\n>\n> Robert Luberda (1):\n>       git svn: handle errors and concurrent commits in dcommit\n\nOK, so these two are fit for 1.7.12-rc3 and later?\n\nWill pull.\n\nThanks.\n\n>\n>  git-svn.perl                           |  74 ++++++++---\n>  perl/Git/SVN.pm                        |  27 ++++-\n>  t/t9163-git-svn-reset-clears-caches.sh |  78 ++++++++++++\n>  t/t9164-git-svn-dcommit-concrrent.sh   | 216 +++++++++++++++++++++++++++++++++\n>  4 files changed, 374 insertions(+), 21 deletions(-)\n>  create mode 100755 t/t9163-git-svn-reset-clears-caches.sh\n>  create mode 100755 t/t9164-git-svn-dcommit-concrrent.sh\n"},{"id":"196839","messageId":"20120810213028.GA8660@dcvr.yhbt.net","threadId":"31202","inReplyTo":"7vmx22iggu.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v2] git svn: reset invalidates the memoized mergeinfo caches","fromName":"Eric Wong","fromEmail":"normalperson@yhbt.net","sentAt":"2012-08-10T21:30:28Z","receivedAt":"2012-08-10T21:30:28Z","isPatch":true,"sender":{"key":"e@80x24.org","avatar":null},"body":"Junio C Hamano <gitster@pobox.com> wrote:\n> Eric Wong <normalperson@yhbt.net> writes:\n> > Peter Baumann (1):\n> >       git svn: reset invalidates the memoized mergeinfo caches\n> >\n> > Robert Luberda (1):\n> >       git svn: handle errors and concurrent commits in dcommit\n> \n> OK, so these two are fit for 1.7.12-rc3 and later?\n\nYes.\n"}]}