{"thread":{"id":"10061","subject":"[PATCH] Don't checkout the full tree if avoidable","startedAt":"2007-09-28T17:24:19Z","lastAt":"2007-10-03T23:26:11Z","messageCount":5,"participants":["Steven Walter","Junio C Hamano","Eric Wong"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"54282","messageId":"1191000259190-git-send-email-stevenrwalter@gmail.com","threadId":"10061","inReplyTo":null,"subject":"[PATCH] Don't checkout the full tree if avoidable","fromName":"Steven Walter","fromEmail":"stevenrwalter@gmail.com","sentAt":"2007-09-28T17:24:19Z","receivedAt":"2007-09-28T17:24:19Z","isPatch":true,"sender":{"key":"stevenrwalter@gmail.com","avatar":"https://avatars.githubusercontent.com/u/79127?v=4"},"body":"In most cases of branching, the tree is copied unmodified from the trunk\nto the branch.  When that is done, we can simply start with the parent's\nindex and apply the changes on the branch as usual.\n\nSigned-off-by: Steven Walter <stevenrwalter@gmail.com>\n---\n git-svn.perl |   18 ++++++++++++++++++\n 1 files changed, 18 insertions(+), 0 deletions(-)\n\ndiff --git a/git-svn.perl b/git-svn.perl\nindex 484b057..2ca2042 100755\n--- a/git-svn.perl\n+++ b/git-svn.perl\n@@ -1847,6 +1847,13 @@ sub find_parent_branch {\n \t\t\t$gs->ra->gs_do_switch($r0, $rev, $gs,\n \t\t\t\t\t      $self->full_url, $ed)\n \t\t\t  or die \"SVN connection failed somewhere...\\n\";\n+\t\t} elsif ($self->trees_match($new_url, $r0,\n+\t\t\t                    $self->full_url, $rev)) {\n+\t\t\t$self->tmp_index_do(sub {\n+\t\t\t    command_noisy('read-tree', $parent);\n+\t\t\t});\n+\t\t\t$self->{last_commit} = $parent;\n+\t\t\t# Assume copy with no changes\n \t\t} else {\n \t\t\tprint STDERR \"Following parent with do_update\\n\";\n \t\t\t$ed = SVN::Git::Fetcher->new($self);\n@@ -1859,6 +1866,17 @@ sub find_parent_branch {\n \treturn undef;\n }\n \n+sub trees_match {\n+    my ($self, $url1, $rev1, $url2, $rev2) = @_;\n+    \n+    my $ret=1;\n+    open(my $fh, \"svn diff $url1\\@$rev1 $url2\\@$rev2 |\");\n+    $ret=0 if (<$fh>);\n+    close($fh);\n+\n+    return $ret;\n+}\n+\n sub do_fetch {\n \tmy ($self, $paths, $rev) = @_;\n \tmy $ed;\n-- \n1.5.3.1\n"},{"id":"54456","messageId":"7vejgftgef.fsf@gitster.siamese.dyndns.org","threadId":"10061","inReplyTo":"1191000259190-git-send-email-stevenrwalter@gmail.com","subject":"Re: [PATCH] Don't checkout the full tree if avoidable","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-10-01T07:58:48Z","receivedAt":"2007-10-01T07:58:48Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Steven Walter <stevenrwalter@gmail.com> writes:\n\n> In most cases of branching, the tree is copied unmodified from the trunk\n> to the branch.  When that is done, we can simply start with the parent's\n> index and apply the changes on the branch as usual.\n>\n> Signed-off-by: Steven Walter <stevenrwalter@gmail.com>\n\nEric, do you like this one?\n\n> ---\n>  git-svn.perl |   18 ++++++++++++++++++\n>  1 files changed, 18 insertions(+), 0 deletions(-)\n>\n> diff --git a/git-svn.perl b/git-svn.perl\n> index 484b057..2ca2042 100755\n> --- a/git-svn.perl\n> +++ b/git-svn.perl\n> @@ -1847,6 +1847,13 @@ sub find_parent_branch {\n>  \t\t\t$gs->ra->gs_do_switch($r0, $rev, $gs,\n>  \t\t\t\t\t      $self->full_url, $ed)\n>  \t\t\t  or die \"SVN connection failed somewhere...\\n\";\n> +\t\t} elsif ($self->trees_match($new_url, $r0,\n> +\t\t\t                    $self->full_url, $rev)) {\n> +\t\t\t$self->tmp_index_do(sub {\n> +\t\t\t    command_noisy('read-tree', $parent);\n> +\t\t\t});\n> +\t\t\t$self->{last_commit} = $parent;\n> +\t\t\t# Assume copy with no changes\n>  \t\t} else {\n>  \t\t\tprint STDERR \"Following parent with do_update\\n\";\n>  \t\t\t$ed = SVN::Git::Fetcher->new($self);\n> @@ -1859,6 +1866,17 @@ sub find_parent_branch {\n>  \treturn undef;\n>  }\n>  \n> +sub trees_match {\n> +    my ($self, $url1, $rev1, $url2, $rev2) = @_;\n> +    \n> +    my $ret=1;\n> +    open(my $fh, \"svn diff $url1\\@$rev1 $url2\\@$rev2 |\");\n> +    $ret=0 if (<$fh>);\n> +    close($fh);\n> +\n> +    return $ret;\n> +}\n> +\n>  sub do_fetch {\n>  \tmy ($self, $paths, $rev) = @_;\n>  \tmy $ed;\n> -- \n> 1.5.3.1\n"},{"id":"54469","messageId":"20071001110855.GB10079@muzzle","threadId":"10061","inReplyTo":"7vejgftgef.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] Don't checkout the full tree if avoidable","fromName":"Eric Wong","fromEmail":"normalperson@yhbt.net","sentAt":"2007-10-01T11:08:55Z","receivedAt":"2007-10-01T11:08:55Z","isPatch":true,"sender":{"key":"e@80x24.org","avatar":null},"body":"Junio C Hamano <gitster@pobox.com> wrote:\n> Steven Walter <stevenrwalter@gmail.com> writes:\n>\n> > In most cases of branching, the tree is copied unmodified from the trunk\n> > to the branch.  When that is done, we can simply start with the parent's\n> > index and apply the changes on the branch as usual.\n> >\n> > Signed-off-by: Steven Walter <stevenrwalter@gmail.com>\n>\n> Eric, do you like this one?\n\nJunio, thanks for pinging me about it, I haven't been following the ML\nvery closely and forgot about this issue.\n\nSteven Walter wrote:\n> One criticism of the patch: the trees_match function probably needs to\n> be re-written.  My SVN::Perl-foo is weak.\n\nYep :)\n\nSteven:\n\nHow does the following work for you?  Which version of SVN do you have,\nby the way?  I just found a bug with the way SVN::Client::diff() is\nexported for SVN 1.1.4, hence the SVN::Pool->new_default_sub usage.\n\nFrom: Steven Walter <stevenrwalter@gmail.com>\nDate: Fri, 28 Sep 2007 13:24:19 -0400\nSubject: [PATCH] Don't checkout the full tree if avoidable\n\nIn most cases of branching, the tree is copied unmodified from the trunk\nto the branch.  When that is done, we can simply start with the parent's\nindex and apply the changes on the branch as usual.\n\n[ew: rewritten from Steven's original to use SVN::Client instead\n     of the command-line svn client.\n\n     Since SVN::Client connects separately, we'll share our\n     authentication providers array between our usages of\n     SVN::Client and SVN::Ra, too.  Bypassing the high-level\n     SVN::Client library can avoid this, but the code will be\n     much more complex.  Regardless, any implementation of this\n     seems to require restarting a connection to the remote\n     server.\n\n     Also of note is that SVN 1.4 and later allows a more\n     efficient diff_summary to be done instead of a full diff,\n     but since this code is only to support SVN < 1.4.4, we'll\n     ignore it for now.]\n\nSigned-off-by: Steven Walter <stevenrwalter@gmail.com>\nSigned-off-by: Eric Wong <normalperson@yhbt.net>\n---\n git-svn.perl |   64 +++++++++++++++++++++++++++++++++++++++++++--------------\n 1 files changed, 48 insertions(+), 16 deletions(-)\n\ndiff --git a/git-svn.perl b/git-svn.perl\nindex 484b057..777e436 100755\n--- a/git-svn.perl\n+++ b/git-svn.perl\n@@ -1847,6 +1847,16 @@ sub find_parent_branch {\n \t\t\t$gs->ra->gs_do_switch($r0, $rev, $gs,\n \t\t\t\t\t      $self->full_url, $ed)\n \t\t\t  or die \"SVN connection failed somewhere...\\n\";\n+\t\t} elsif ($self->ra->trees_match($new_url, $r0,\n+\t\t\t                        $self->full_url, $rev)) {\n+\t\t\tprint STDERR \"Trees match:\\n\",\n+\t\t\t             \"  $new_url\\@$r0\\n\",\n+\t\t\t             \"  ${\\$self->full_url}\\@$rev\\n\",\n+\t\t\t\t     \"Following parent with no changes\\n\";\n+\t\t\t$self->tmp_index_do(sub {\n+\t\t\t    command_noisy('read-tree', $parent);\n+\t\t\t});\n+\t\t\t$self->{last_commit} = $parent;\n \t\t} else {\n \t\t\tprint STDERR \"Following parent with do_update\\n\";\n \t\t\t$ed = SVN::Git::Fetcher->new($self);\n@@ -3027,28 +3037,32 @@ BEGIN {\n \t}\n }\n \n+sub _auth_providers () {\n+\t[\n+\t  SVN::Client::get_simple_provider(),\n+\t  SVN::Client::get_ssl_server_trust_file_provider(),\n+\t  SVN::Client::get_simple_prompt_provider(\n+\t    \\&Git::SVN::Prompt::simple, 2),\n+\t  SVN::Client::get_ssl_client_cert_file_provider(),\n+\t  SVN::Client::get_ssl_client_cert_prompt_provider(\n+\t    \\&Git::SVN::Prompt::ssl_client_cert, 2),\n+\t  SVN::Client::get_ssl_client_cert_pw_prompt_provider(\n+\t    \\&Git::SVN::Prompt::ssl_client_cert_pw, 2),\n+\t  SVN::Client::get_username_provider(),\n+\t  SVN::Client::get_ssl_server_trust_prompt_provider(\n+\t    \\&Git::SVN::Prompt::ssl_server_trust),\n+\t  SVN::Client::get_username_prompt_provider(\n+\t    \\&Git::SVN::Prompt::username, 2)\n+\t]\n+}\n+\n sub new {\n \tmy ($class, $url) = @_;\n \t$url =~ s!/+$!!;\n \treturn $RA if ($RA && $RA->{url} eq $url);\n \n \tSVN::_Core::svn_config_ensure($config_dir, undef);\n-\tmy ($baton, $callbacks) = SVN::Core::auth_open_helper([\n-\t    SVN::Client::get_simple_provider(),\n-\t    SVN::Client::get_ssl_server_trust_file_provider(),\n-\t    SVN::Client::get_simple_prompt_provider(\n-\t      \\&Git::SVN::Prompt::simple, 2),\n-\t    SVN::Client::get_ssl_client_cert_file_provider(),\n-\t    SVN::Client::get_ssl_client_cert_prompt_provider(\n-\t      \\&Git::SVN::Prompt::ssl_client_cert, 2),\n-\t    SVN::Client::get_ssl_client_cert_pw_prompt_provider(\n-\t      \\&Git::SVN::Prompt::ssl_client_cert_pw, 2),\n-\t    SVN::Client::get_username_provider(),\n-\t    SVN::Client::get_ssl_server_trust_prompt_provider(\n-\t      \\&Git::SVN::Prompt::ssl_server_trust),\n-\t    SVN::Client::get_username_prompt_provider(\n-\t      \\&Git::SVN::Prompt::username, 2),\n-\t  ]);\n+\tmy ($baton, $callbacks) = SVN::Core::auth_open_helper(_auth_providers);\n \tmy $config = SVN::Core::config_get_config($config_dir);\n \t$RA = undef;\n \tmy $self = SVN::Ra->new(url => $url, auth => $baton,\n@@ -3112,6 +3126,24 @@ sub get_log {\n \t$ret;\n }\n \n+sub trees_match {\n+\tmy ($self, $url1, $rev1, $url2, $rev2) = @_;\n+\tmy $ctx = SVN::Client->new(auth => _auth_providers);\n+\tmy $out = IO::File->new_tmpfile;\n+\n+\t# older SVN (1.1.x) doesn't take $pool as the last parameter for\n+\t# $ctx->diff(), so we'll create a default one\n+\tmy $pool = SVN::Pool->new_default_sub;\n+\n+\t$ra_invalid = 1; # this will open a new SVN::Ra connection to $url1\n+\t$ctx->diff([], $url1, $rev1, $url2, $rev2, 1, 1, 0, $out, $out);\n+\t$out->flush;\n+\tmy $ret = (($out->stat)[7] == 0);\n+\tclose $out or croak $!;\n+\n+\t$ret;\n+}\n+\n sub get_commit_editor {\n \tmy ($self, $log, $cb, $pool) = @_;\n \tmy @lock = $SVN::Core::VERSION ge '1.2.0' ? (undef, 0) : ();\n-- \nEric Wong\n"},{"id":"54483","messageId":"20071001131227.GA24494@dervierte","threadId":"10061","inReplyTo":"20071001110855.GB10079@muzzle","subject":"Re: [PATCH] Don't checkout the full tree if avoidable","fromName":"Steven Walter","fromEmail":"stevenrwalter@gmail.com","sentAt":"2007-10-01T13:12:27Z","receivedAt":"2007-10-01T13:12:27Z","isPatch":true,"sender":{"key":"stevenrwalter@gmail.com","avatar":"https://avatars.githubusercontent.com/u/79127?v=4"},"body":"On Mon, Oct 01, 2007 at 04:08:55AM -0700, Eric Wong wrote:\n> Steven Walter wrote:\n> > One criticism of the patch: the trees_match function probably needs to\n> > be re-written.  My SVN::Perl-foo is weak.\n> \n> Yep :)\n> \n> Steven:\n> \n> How does the following work for you?  Which version of SVN do you have,\n> by the way?  I just found a bug with the way SVN::Client::diff() is\n> exported for SVN 1.1.4, hence the SVN::Pool->new_default_sub usage.\n\nswalter@sentra:~% svn --version\nsvn, version 1.3.2 (r19776)\n\nThis version works great; seems to have exactly the same behavior as my\npatch.  Verified that it still falls back to the do_update code when\ntrees_match fails.\n-- \n-Steven Walter <stevenrwalter@gmail.com>\n\"A human being should be able to change a diaper, plan an invasion,\nbutcher a hog, conn a ship, design a building, write a sonnet, balance\naccounts, build a wall, set a bone, comfort the dying, take orders,\ngive orders, cooperate, act alone, solve equations, analyze a new\nproblem, pitch manure, program a computer, cook a tasty meal, fight\nefficiently, die gallantly. Specialization is for insects.\"\n   -Robert Heinlein\n"},{"id":"54779","messageId":"20071003232611.GB14972@hand.yhbt.net","threadId":"10061","inReplyTo":"20071001131227.GA24494@dervierte","subject":"Re: [PATCH] Don't checkout the full tree if avoidable","fromName":"Eric Wong","fromEmail":"normalperson@yhbt.net","sentAt":"2007-10-03T23:26:11Z","receivedAt":"2007-10-03T23:26:11Z","isPatch":true,"sender":{"key":"e@80x24.org","avatar":null},"body":"Steven Walter <stevenrwalter@gmail.com> wrote:\n> On Mon, Oct 01, 2007 at 04:08:55AM -0700, Eric Wong wrote:\n> > Steven Walter wrote:\n> > > One criticism of the patch: the trees_match function probably needs to\n> > > be re-written.  My SVN::Perl-foo is weak.\n> > \n> > Yep :)\n> > \n> > Steven:\n> > \n> > How does the following work for you?  Which version of SVN do you have,\n> > by the way?  I just found a bug with the way SVN::Client::diff() is\n> > exported for SVN 1.1.4, hence the SVN::Pool->new_default_sub usage.\n> \n> swalter@sentra:~% svn --version\n> svn, version 1.3.2 (r19776)\n> \n> This version works great; seems to have exactly the same behavior as my\n> patch.  Verified that it still falls back to the do_update code when\n> trees_match fails.\n\nThanks Steven.\n\nJunio: can you please apply my version of Steven's patch?  Thanks.\n\n-- \nEric Wong\n"}]}