git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Junio C Hamano <junkio@cox.net>
To: Linus Torvalds <torvalds@osdl.org>
Cc: Git Mailing List <git@vger.kernel.org>
Subject: Re: [CORRECTED PATCH] git-fetch-pack: avoid unnecessary zero packing
Date: Tue, 18 Oct 2005 11:45:34 -0700	[thread overview]
Message-ID: <7vr7air7e9.fsf@assigned-by-dhcp.cox.net> (raw)
In-Reply-To: <Pine.LNX.4.64.0510181049050.17201@g5.osdl.org> (Linus Torvalds's message of "Tue, 18 Oct 2005 10:52:45 -0700 (PDT)")

Linus Torvalds <torvalds@osdl.org> writes:

> If everything is up-to-date locally, we don't need to even ask for a
> pack-file from the remote, or try to unpack it.
>
> This is especially important for tags - since the pack-file common commit
> logic is based purely on the commit history, it will never be able to find
> a common tag, and will thus always end up re-fetching them.
>
> Especially notably, if the tag points to a non-commit (eg a tagged tree),
> the pack-file would be unnecessarily big, just because it cannot any most
> recent common point between commits for pruning.
>
> Short-circuiting the case where we already have that reference means that
> we avoid a lot of these in the common case.
>
> NOTE! This only matches remote ref names against the same local name,
> which works well for tags, but is not as generic as it could be. If we
> ever need to, we could match against _any_ local ref (if we have it, we
> have it), but this "match against same name" is simpler and more
> efficient, and covers the common case.
>
> Renaming of refs is common for branch heads, but since those are always
> commits, the pack-file generation can optimize that case.
>
> In some cases we might still end up fetching pack-files unnecessarily, but
> this at least avoids the re-fetching of tags over and over if you use a
> regular
>
> 	git fetch --tags ...
>
> which was the main reason behind the change.
>
> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
> ---
>
> Ok, this should be the trivially fixed (famous last words) patch, which 
> should correct the case where we don't have a local name for the remote 
> ref at all.
>
> If you already applied the previous patch, you just need to fix the
>
> 	if (read_ref(...) < 0)
> 		continue
> 	if (memcmp(..)) {
>
> to be one case (a failing read_ref should do the exact same thing as a 
> failed memcmp):
>
> 	if (read_ref(...) < 0 ||
> 	    memcmp(...) {
>
> and everything should be ok.
>
> This has gotten _some_ testing, but obviously not enough ;)
>
> 		Linus
>
> diff --git a/fetch-pack.c b/fetch-pack.c
> index 953c0cf..4597369 100644
> --- a/fetch-pack.c
> +++ b/fetch-pack.c
> @@ -12,6 +12,7 @@ static const char *exec = "git-upload-pa
>  static int find_common(int fd[2], unsigned char *result_sha1,
>  		       struct ref *refs)
>  {
> +	int fetching;
>  	static char line[1000];
>  	int count = 0, flushes = 0, retval;
>  	FILE *revs;
> @@ -20,16 +21,19 @@ static int find_common(int fd[2], unsign
>  	if (!revs)
>  		die("unable to run 'git-rev-list'");
>  
> -	while (refs) {
> +	fetching = 0;
> +	for ( ; refs ; refs = refs->next) {
>  		unsigned char *remote = refs->old_sha1;
> -		if (verbose)
> -			fprintf(stderr,
> -				"want %s (%s)\n", sha1_to_hex(remote),
> -				refs->name);
> +		unsigned char *local = refs->new_sha1;
> +
> +		if (!memcmp(remote, local, 20))
> +			continue;
>  		packet_write(fd[1], "want %s\n", sha1_to_hex(remote));
> -		refs = refs->next;
> +		fetching++;
>  	}
>  	packet_flush(fd[1]);
> +	if (!fetching)
> +		return 1;
>  	flushes = 1;
>  	retval = -1;
>  	while (fgets(line, sizeof(line), revs) != NULL) {
> @@ -74,6 +78,35 @@ static int find_common(int fd[2], unsign
>  	return retval;
>  }
>  
> +static int everything_local(struct ref *refs)
> +{
> +	int retval;
> +
> +	for (retval = 1; refs ; refs = refs->next) {
> +		const unsigned char *remote = refs->old_sha1;
> +		unsigned char local[20];
> +
> +		if (read_ref(git_path("%s", refs->name), local) < 0 ||
> +		    memcmp(remote, local, 20)) {
> +			retval = 0;
> +			if (!verbose)
> +				continue;
> +			fprintf(stderr,
> +				"want %s (%s)\n", sha1_to_hex(remote),
> +				refs->name);
> +			continue;
> +		}
> +
> +		memcpy(refs->new_sha1, local, 20);
> +		if (!verbose)
> +			continue;
> +		fprintf(stderr,
> +			"already have %s (%s)\n", sha1_to_hex(remote),
> +			refs->name);
> +	}
> +	return retval;
> +}
> +
>  static int fetch_pack(int fd[2], int nr_match, char **match)
>  {
>  	struct ref *ref;
> @@ -86,6 +119,10 @@ static int fetch_pack(int fd[2], int nr_
>  		packet_flush(fd[1]);
>  		die("no matching remote head");
>  	}
> +	if (everything_local(ref)) {
> +		packet_flush(fd[1]);
> +		goto all_done;
> +	}
>  	if (find_common(fd, sha1, ref) < 0)
>  		fprintf(stderr, "warning: no common commits\n");
>  	pid = fork();
> @@ -109,6 +146,7 @@ static int fetch_pack(int fd[2], int nr_
>  		int code = WEXITSTATUS(status);
>  		if (code)
>  			die("git-unpack-objects died with error code %d", code);
> +all_done:
>  		while (ref) {
>  			printf("%s %s\n",
>  			       sha1_to_hex(ref->old_sha1), ref->name);

  reply	other threads:[~2005-10-18 18:45 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-10-18 17:52 [CORRECTED PATCH] git-fetch-pack: avoid unnecessary zero packing Linus Torvalds
2005-10-18 18:45 ` Junio C Hamano [this message]
2005-10-18 18:49 ` Junio C Hamano
2005-10-18 19:19   ` Junio C Hamano
2005-10-18 20:38   ` Linus Torvalds
2005-10-18 20:42     ` Linus Torvalds
2005-10-19  0:27       ` Junio C Hamano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=7vr7air7e9.fsf@assigned-by-dhcp.cox.net \
    --to=junkio@cox.net \
    --cc=git@vger.kernel.org \
    --cc=torvalds@osdl.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).