git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH] Don't checkout the full tree if avoidable

From
EWEric Wong <normalperson@yhbt.net>
Date
Oct 1, 2007, 11:08 UTC
Message-ID
<20071001110855.GB10079@muzzle>
In-Reply-To
<7vejgftgef.fsf@gitster.siamese.dyndns.org>
Junio C Hamano <gitster@pobox.com> wrote:
Show 9 quoted lines
> Steven Walter <stevenrwalter@gmail.com> writes:
>
> > In most cases of branching, the tree is copied unmodified from the trunk
> > to the branch.  When that is done, we can simply start with the parent's
> > index and apply the changes on the branch as usual.
> >
> > Signed-off-by: Steven Walter <stevenrwalter@gmail.com>
>
> Eric, do you like this one?

Junio, thanks for pinging me about it, I haven't been following the ML very closely and forgot about this issue.

Steven Walter wrote:
> One criticism of the patch: the trees_match function probably needs to
> be re-written.  My SVN::Perl-foo is weak.
Yep :)
Steven:

How does the following work for you? Which version of SVN do you have, by the way? I just found a bug with the way SVN::Client::diff() is exported for SVN 1.1.4, hence the SVN::Pool->new_default_sub usage.

From: Steven Walter <stevenrwalter@gmail.com>
Date: Fri, 28 Sep 2007 13:24:19 -0400
Subject: [PATCH] Don't checkout the full tree if avoidable

In most cases of branching, the tree is copied unmodified from the trunk to the branch. When that is done, we can simply start with the parent's index and apply the changes on the branch as usual.

[ew: rewritten from Steven's original to use SVN::Client instead
     of the command-line svn client.
     Since SVN::Client connects separately, we'll share our
     authentication providers array between our usages of
     SVN::Client and SVN::Ra, too.  Bypassing the high-level
     SVN::Client library can avoid this, but the code will be
     much more complex.  Regardless, any implementation of this
     seems to require restarting a connection to the remote
     server.
     Also of note is that SVN 1.4 and later allows a more
     efficient diff_summary to be done instead of a full diff,
     but since this code is only to support SVN < 1.4.4, we'll
     ignore it for now.]
Signed-off-by: Steven Walter <stevenrwalter@gmail.com>
Signed-off-by: Eric Wong <normalperson@yhbt.net>
---
 git-svn.perl |   64 +++++++++++++++++++++++++++++++++++++++++++--------------
 1 files changed, 48 insertions(+), 16 deletions(-)
diff --git a/git-svn.perl b/git-svn.perl
index 484b057..777e436 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -1847,6 +1847,16 @@ sub find_parent_branch {
 			$gs->ra->gs_do_switch($r0, $rev, $gs,
 					      $self->full_url, $ed)
 			  or die "SVN connection failed somewhere...\n";
+		} elsif ($self->ra->trees_match($new_url, $r0,
+			                        $self->full_url, $rev)) {
+			print STDERR "Trees match:\n",
+			             "  $new_url\@$r0\n",
+			             "  ${\$self->full_url}\@$rev\n",
+				     "Following parent with no changes\n";
+			$self->tmp_index_do(sub {
+			    command_noisy('read-tree', $parent);
+			});
+			$self->{last_commit} = $parent;
 		} else {
 			print STDERR "Following parent with do_update\n";
 			$ed = SVN::Git::Fetcher->new($self);
@@ -3027,28 +3037,32 @@ BEGIN {
 	}
 }
 
+sub _auth_providers () {
+	[
+	  SVN::Client::get_simple_provider(),
+	  SVN::Client::get_ssl_server_trust_file_provider(),
+	  SVN::Client::get_simple_prompt_provider(
+	    \&Git::SVN::Prompt::simple, 2),
+	  SVN::Client::get_ssl_client_cert_file_provider(),
+	  SVN::Client::get_ssl_client_cert_prompt_provider(
+	    \&Git::SVN::Prompt::ssl_client_cert, 2),
+	  SVN::Client::get_ssl_client_cert_pw_prompt_provider(
+	    \&Git::SVN::Prompt::ssl_client_cert_pw, 2),
+	  SVN::Client::get_username_provider(),
+	  SVN::Client::get_ssl_server_trust_prompt_provider(
+	    \&Git::SVN::Prompt::ssl_server_trust),
+	  SVN::Client::get_username_prompt_provider(
+	    \&Git::SVN::Prompt::username, 2)
+	]
+}
+
 sub new {
 	my ($class, $url) = @_;
 	$url =~ s!/+$!!;
 	return $RA if ($RA && $RA->{url} eq $url);
 
 	SVN::_Core::svn_config_ensure($config_dir, undef);
-	my ($baton, $callbacks) = SVN::Core::auth_open_helper([
-	    SVN::Client::get_simple_provider(),
-	    SVN::Client::get_ssl_server_trust_file_provider(),
-	    SVN::Client::get_simple_prompt_provider(
-	      \&Git::SVN::Prompt::simple, 2),
-	    SVN::Client::get_ssl_client_cert_file_provider(),
-	    SVN::Client::get_ssl_client_cert_prompt_provider(
-	      \&Git::SVN::Prompt::ssl_client_cert, 2),
-	    SVN::Client::get_ssl_client_cert_pw_prompt_provider(
-	      \&Git::SVN::Prompt::ssl_client_cert_pw, 2),
-	    SVN::Client::get_username_provider(),
-	    SVN::Client::get_ssl_server_trust_prompt_provider(
-	      \&Git::SVN::Prompt::ssl_server_trust),
-	    SVN::Client::get_username_prompt_provider(
-	      \&Git::SVN::Prompt::username, 2),
-	  ]);
+	my ($baton, $callbacks) = SVN::Core::auth_open_helper(_auth_providers);
 	my $config = SVN::Core::config_get_config($config_dir);
 	$RA = undef;
 	my $self = SVN::Ra->new(url => $url, auth => $baton,
@@ -3112,6 +3126,24 @@ sub get_log {
 	$ret;
 }
 
+sub trees_match {
+	my ($self, $url1, $rev1, $url2, $rev2) = @_;
+	my $ctx = SVN::Client->new(auth => _auth_providers);
+	my $out = IO::File->new_tmpfile;
+
+	# older SVN (1.1.x) doesn't take $pool as the last parameter for
+	# $ctx->diff(), so we'll create a default one
+	my $pool = SVN::Pool->new_default_sub;
+
+	$ra_invalid = 1; # this will open a new SVN::Ra connection to $url1
+	$ctx->diff([], $url1, $rev1, $url2, $rev2, 1, 1, 0, $out, $out);
+	$out->flush;
+	my $ret = (($out->stat)[7] == 0);
+	close $out or croak $!;
+
+	$ret;
+}
+
 sub get_commit_editor {
 	my ($self, $log, $cb, $pool) = @_;
 	my @lock = $SVN::Core::VERSION ge '1.2.0' ? (undef, 0) : ();
-- 
Eric Wong
Previous: Junio C HamanoNext: Steven Walter
Message 3 of 5 in “Don't checkout the full tree if avoidable”
  1. Don't checkout the full tree if avoidableSteven Walter, Sep 28, 2007
  2. Junio C HamanoOct 1, 2007
  3. Eric WongOct 1, 2007
  4. Steven WalterOct 1, 2007
  5. Eric WongOct 3, 2007

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.