{"thread":{"id":"33686","subject":"[PATCH 4/5] git-svn: fix bottleneck in stash_placeholder_list()","startedAt":"2013-04-30T17:37:18Z","lastAt":"2013-04-30T17:37:18Z","messageCount":1,"participants":["Ilya Basin"],"isPatch":true,"patchVersion":1,"patchTotal":5},"messages":[{"id":"216025","messageId":"51800470.6905700a.65c8.00b8@mx.google.com","threadId":"33686","inReplyTo":null,"subject":"[PATCH 4/5] git-svn: fix bottleneck in stash_placeholder_list()","fromName":"Ilya Basin","fromEmail":"basinilya@gmail.com","sentAt":"2013-04-30T17:37:18Z","receivedAt":"2013-04-30T17:37:18Z","isPatch":true,"sender":{"key":"basinilya@gmail.com","avatar":null},"body":".git/config is written on each commit. It's slow\n---\n perl/Git/SVN/Fetcher.pm | 77 +++++++++++++++++++++++++++++++------------------\n 1 file changed, 49 insertions(+), 28 deletions(-)\n\ndiff --git a/perl/Git/SVN/Fetcher.pm b/perl/Git/SVN/Fetcher.pm\nindex e658889..a5ad4cd 100644\n--- a/perl/Git/SVN/Fetcher.pm\n+++ b/perl/Git/SVN/Fetcher.pm\n@@ -1,5 +1,6 @@\n package Git::SVN::Fetcher;\n use vars qw/@ISA $_ignore_regex $_preserve_empty_dirs $_placeholder_filename\n+            $_package_inited\n             @deleted_gpath %added_placeholder $repo_id/;\n use strict;\n use warnings;\n@@ -26,32 +27,9 @@ sub new {\n \t\t                  _mark_empty_symlinks($git_svn, $switch_path);\n \t}\n \n-\t# some options are read globally, but can be overridden locally\n-\t# per [svn-remote \"...\"] section.  Command-line options will *NOT*\n-\t# override options set in an [svn-remote \"...\"] section\n-\t$repo_id = $git_svn->{repo_id};\n-\tmy $k = \"svn-remote.$repo_id.ignore-paths\";\n-\tmy $v = eval { command_oneline('config', '--get', $k) };\n-\t$self->{ignore_regex} = $v;\n-\n-\t$k = \"svn-remote.$repo_id.preserve-empty-dirs\";\n-\t$v = eval { command_oneline('config', '--get', '--bool', $k) };\n-\tif ($v && $v eq 'true') {\n-\t\t$_preserve_empty_dirs = 1;\n-\t\t$k = \"svn-remote.$repo_id.placeholder-filename\";\n-\t\t$v = eval { command_oneline('config', '--get', $k) };\n-\t\t$_placeholder_filename = $v;\n-\t}\n-\n-\t# Load the list of placeholder files added during previous invocations.\n-\t$k = \"svn-remote.$repo_id.added-placeholder\";\n-\t$v = eval { command_oneline('config', '--get-all', $k) };\n-\tif ($_preserve_empty_dirs && $v) {\n-\t\t# command() prints errors to stderr, so we only call it if\n-\t\t# command_oneline() succeeded.\n-\t\tmy @v = command('config', '--get-all', $k);\n-\t\t$added_placeholder{ dirname($_) } = $_ foreach @v;\n-\t}\n+\t_try_init_package($git_svn);\n+\t$self->{_save_ph} = { %added_placeholder };\n+\t$self->{ignore_regex} = $_ignore_regex;\n \n \t$self->{empty} = {};\n \t$self->{dir_prop} = {};\n@@ -64,6 +42,43 @@ sub new {\n \t$self;\n }\n \n+sub _try_init_package {\n+\tif (!$_package_inited) {\n+\t\tmy ( $git_svn ) = @_;\n+\n+\t\t$_package_inited = 1;\n+\t\t$repo_id = $git_svn->{repo_id};\n+\n+\t\t# some options are read globally, but can be overridden locally\n+\t\t# per [svn-remote \"...\"] section.  Command-line options will *NOT*\n+\t\t# override options set in an [svn-remote \"...\"] section\n+\n+\t\tmy $k = \"svn-remote.$repo_id.ignore-paths\";\n+\t\tmy $v = eval { command_oneline('config', '--get', $k) };\n+\t\t$_ignore_regex = $v;\n+\n+\t\t$k = \"svn-remote.$repo_id.preserve-empty-dirs\";\n+\t\t$v = eval { command_oneline('config', '--get', '--bool', $k) };\n+\t\tif ($v && $v eq 'true') {\n+\t\t\t$_preserve_empty_dirs = 1;\n+\t\t\t$k = \"svn-remote.$repo_id.placeholder-filename\";\n+\t\t\t$v = eval { command_oneline('config', '--get', $k) };\n+\t\t\t$_placeholder_filename = $v;\n+\n+\t\t\t# Load the list of placeholder files added during previous invocations.\n+\t\t\t$k = \"svn-remote.$repo_id.added-placeholder\";\n+\t\t\t$v = eval { command_oneline('config', '--get-all', $k) };\n+\t\t\tif ($v) {\n+\t\t\t\t# command() prints errors to stderr, so we only call it if\n+\t\t\t\t# command_oneline() succeeded.\n+\t\t\t\tmy @v = command('config', '--get-all', $k);\n+\t\t\t\t$added_placeholder{ dirname($_) } = $_ foreach @v;\n+\t\t\t}\n+\t\t}\n+\t}\n+\tundef\n+}\n+\n # this uses the Ra object, so it must be called before do_{switch,update},\n # not inside them (when the Git::SVN::Fetcher object is passed) to\n # do_{switch,update}\n@@ -123,8 +138,6 @@ sub is_path_ignored {\n \treturn 1 if in_dot_git($path);\n \treturn 1 if defined($self->{ignore_regex}) &&\n \t            $path =~ m!$self->{ignore_regex}!;\n-\treturn 0 unless defined($_ignore_regex);\n-\treturn 1 if $path =~ m!$_ignore_regex!o;\n \treturn 0;\n }\n \n@@ -506,6 +519,14 @@ sub add_placeholder_file {\n \n sub stash_placeholder_list {\n \tmy ($self) = @_;\n+\n+\tfor ( keys %added_placeholder ) {\n+\t\tgoto theydiffer if (!delete $self->{_save_ph}{$_});\n+\t}\n+\treturn undef if (!keys $self->{_save_ph});\n+\n+theydiffer:\n+\n \tmy $k = \"svn-remote.$repo_id.added-placeholder\";\n \tmy $v = eval { command_oneline('config', '--get-all', $k) };\n \tcommand_noisy('config', '--unset-all', $k) if $v;\n-- \n1.8.1.5\n"}]}