git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Junio C Hamano <junkio@cox.net>
To: git@vger.kernel.org
Cc: Linus Torvalds <torvalds@osdl.org>
Subject: [PATCH] fetch-pack: start multi-head pulling.
Date: Fri, 12 Aug 2005 02:41:38 -0700	[thread overview]
Message-ID: <7vwtmr4hm5.fsf@assigned-by-dhcp.cox.net> (raw)

This is a beginning of resurrecting the multi-head pulling support
for git-fetch-pack command.  The git-fetch-script wrapper still
only knows about fetching a single head, without renaming, so it is
not very useful unless you directly call git-fetch-pack itself yet.

It also fixes a longstanding obsolete description of how the command
discovers the list of local commits.
---

Linus, I need a bit of guidance from you about this one; an
ancient commit 4f7770c87ce3c302e1639a7737a6d2531fe4b160 removed
the multi-head support fetch-pack once had, labelling it as "a
misguided attempt", and I would like to know if I am making the
same misguided attempt again.  This update actually makes
clone-pack almost redundant.


 Documentation/git-fetch-pack.txt |   18 +++++-------
 fetch-pack.c                     |   56 +++++++++++++++++++++++++++-----------
 git-fetch-script                 |    4 +++
 3 files changed, 51 insertions(+), 27 deletions(-)

880df673e412bae9603782833d8a80a7c7c59769
diff --git a/Documentation/git-fetch-pack.txt b/Documentation/git-fetch-pack.txt
--- a/Documentation/git-fetch-pack.txt
+++ b/Documentation/git-fetch-pack.txt
@@ -9,19 +9,19 @@ git-fetch-pack - Receive missing objects
 
 SYNOPSIS
 --------
-git-fetch-pack [-q] [--exec=<git-upload-pack>] [<host>:]<directory> [<head>...] < <commit-list>
+git-fetch-pack [-q] [--exec=<git-upload-pack>] [<host>:]<directory> [<refs>...]
 
 DESCRIPTION
 -----------
 Invokes 'git-upload-pack' on a potentially remote repository,
 and asks it to send objects missing from this repository, to
 update the named heads.  The list of commits available locally
-is fed from the standard input, to be sent to 'git-upload-pack'
-running on the other end.
+is found out by scanning local $GIT_DIR/refs/ and sent to
+'git-upload-pack' running on the other end.
 
-This command can be used only when the local side has a common
-(ancestor) commit with the remote head that is being pulled
-from.  Use 'git-clone-pack' for that.
+This command degenerates to download everything to complete the
+asked refs from the remote side when the local side does not
+have a common ancestor commit.
 
 
 OPTIONS
@@ -50,15 +50,11 @@ OPTIONS
 <directory>::
 	The repository to sync from.
 
-<head>...::
+<refs>...::
 	The remote heads to update from. This is relative to
 	$GIT_DIR (e.g. "HEAD", "refs/heads/master").  When
 	unspecified, update from all heads the remote side has.
 
-	However the program refuses to work if more than one
-	remote head matches the specified heads.  I am not sure
-	what this means... Help!!!!!
-
 
 Author
 ------
diff --git a/fetch-pack.c b/fetch-pack.c
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -4,10 +4,13 @@
 #include <sys/wait.h>
 
 static int quiet;
-static const char fetch_pack_usage[] = "git-fetch-pack [-q] [--exec=upload-pack] [host:]directory [heads]* < mycommitlist";
+static int verbose;
+static const char fetch_pack_usage[] =
+"git-fetch-pack [-q] [-v] [--exec=upload-pack] [host:]directory <refs>...";
 static const char *exec = "git-upload-pack";
 
-static int find_common(int fd[2], unsigned char *result_sha1, unsigned char *remote)
+static int find_common(int fd[2], unsigned char *result_sha1,
+		       struct ref *refs)
 {
 	static char line[1000];
 	int count = 0, flushes = 0, retval;
@@ -16,7 +19,16 @@ static int find_common(int fd[2], unsign
 	revs = popen("git-rev-list $(git-rev-parse --all)", "r");
 	if (!revs)
 		die("unable to run 'git-rev-list'");
-	packet_write(fd[1], "want %s\n", sha1_to_hex(remote));
+
+	while (refs) {
+		unsigned char *remote = refs->old_sha1;
+		if (verbose)
+			fprintf(stderr,
+				"want %s (%s)\n", sha1_to_hex(remote),
+				refs->name);
+		packet_write(fd[1], "want %s\n", sha1_to_hex(remote));
+		refs = refs->next;
+	}
 	packet_flush(fd[1]);
 	flushes = 1;
 	retval = -1;
@@ -25,6 +37,8 @@ static int find_common(int fd[2], unsign
 		if (get_sha1_hex(line, sha1))
 			die("git-fetch-pack: expected object name, got crud");
 		packet_write(fd[1], "have %s\n", sha1_to_hex(sha1));
+		if (verbose)
+			fprintf(stderr, "have %s\n", sha1_to_hex(sha1));
 		if (!(31 & ++count)) {
 			packet_flush(fd[1]);
 			flushes++;
@@ -38,6 +52,8 @@ static int find_common(int fd[2], unsign
 			if (get_ack(fd[0], result_sha1)) {
 				flushes = 0;
 				retval = 0;
+				if (verbose)
+					fprintf(stderr, "got ack\n");
 				break;
 			}
 			flushes--;
@@ -45,19 +61,19 @@ static int find_common(int fd[2], unsign
 	}
 	pclose(revs);
 	packet_write(fd[1], "done\n");
+	if (verbose)
+		fprintf(stderr, "done\n");
 	while (flushes) {
 		flushes--;
-		if (get_ack(fd[0], result_sha1))
+		if (get_ack(fd[0], result_sha1)) {
+			if (verbose)
+				fprintf(stderr, "got ack\n");
 			return 0;
+		}
 	}
 	return retval;
 }
 
-/*
- * Eventually we'll want to be able to fetch multiple heads.
- *
- * Right now we'll just require a single match.
- */
 static int fetch_pack(int fd[2], int nr_match, char **match)
 {
 	struct ref *ref;
@@ -70,12 +86,8 @@ static int fetch_pack(int fd[2], int nr_
 		packet_flush(fd[1]);
 		die("no matching remote head");
 	}
-	if (ref->next) {
-		packet_flush(fd[1]);
-		die("multiple remote heads");
-	}
-	if (find_common(fd, sha1, ref->old_sha1) < 0)
-		die("git-fetch-pack: no common commits");
+	if (find_common(fd, sha1, ref) < 0)
+		fprintf(stderr, "warning: no common commits\n");
 	pid = fork();
 	if (pid < 0)
 		die("git-fetch-pack: unable to fork off git-unpack-objects");
@@ -97,7 +109,11 @@ 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);
-		puts(sha1_to_hex(ref->old_sha1));
+		while (ref) {
+			printf("%s %s\n",
+			       sha1_to_hex(ref->old_sha1), ref->name);
+			ref = ref->next;
+		}
 		return 0;
 	}
 	if (WIFSIGNALED(status)) {
@@ -124,6 +140,14 @@ int main(int argc, char **argv)
 				exec = arg + 7;
 				continue;
 			}
+			if (!strcmp("-q", arg)) {
+				quiet = 1;
+				continue;
+			}
+			if (!strcmp("-v", arg)) {
+				verbose = 1;
+				continue;
+			}
 			usage(fetch_pack_usage);
 		}
 		dest = arg;
diff --git a/git-fetch-script b/git-fetch-script
--- a/git-fetch-script
+++ b/git-fetch-script
@@ -31,6 +31,10 @@ rsync://*)
 	;;
 *)
 	head=$(git-fetch-pack "$merge_repo" "$merge_head")
+	if h=`expr "$head" : '\([^ ][^ ]*\) '`
+	then
+	    head=$h
+	fi
 	;;
 esac || exit 1
 

             reply	other threads:[~2005-08-12  9:41 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-08-12  9:41 Junio C Hamano [this message]
2005-08-12 16:12 ` [PATCH] fetch-pack: start multi-head pulling Linus Torvalds
2005-08-12 16:19   ` Johannes Schindelin
2005-08-12 16:43     ` Junio C Hamano
2005-08-13  3:25       ` Matthias Urlichs
2005-08-13  9:09         ` Junio C Hamano
2005-08-12 17:12     ` Linus Torvalds

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

  List information: http://vger.kernel.org/majordomo-info.html

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

  git send-email \
    --in-reply-to=7vwtmr4hm5.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.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

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 read-only IMAP folder(s) and NNTP newsgroup(s).