All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jonathan Tan <jonathantanmy@google.com>
To: git@vger.kernel.org
Cc: Jonathan Tan <jonathantanmy@google.com>
Subject: [RFC 13/14] fetch: send want-ref and receive fetched refs
Date: Wed, 25 Jan 2017 14:03:06 -0800	[thread overview]
Message-ID: <eef2b77d88df0db08e4a1505b06e0af2d40143d5.1485381677.git.jonathantanmy@google.com> (raw)
In-Reply-To: <cover.1485381677.git.jonathantanmy@google.com>
In-Reply-To: <cover.1485381677.git.jonathantanmy@google.com>

Teach fetch to send refspecs to the underlying transport, and teach all
components used by the HTTP transport (remote-curl, transport-helper,
fetch-pack) to understand and propagate the names and SHA-1s of the refs
fetched.

Signed-off-by: Jonathan Tan <jonathantanmy@google.com>
---
 builtin/clone.c                    |   4 +-
 builtin/fetch-pack.c               |   8 ++-
 builtin/fetch.c                    | 100 ++++++++++++++++++++++++++++++-------
 remote-curl.c                      |  91 ++++++++++++++++++++-------------
 t/t5552-upload-pack-ref-in-want.sh |   4 +-
 transport-helper.c                 |  74 +++++++++++++++++++++------
 transport.c                        |  10 ++--
 transport.h                        |  20 +++++---
 8 files changed, 229 insertions(+), 82 deletions(-)

diff --git a/builtin/clone.c b/builtin/clone.c
index 3191da391..765a3a3b6 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -1078,7 +1078,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 			}
 
 		if (!is_local && !complete_refs_before_fetch) {
-			transport_fetch_refs(transport, mapped_refs,
+			transport_fetch_refs(transport, NULL, 0, mapped_refs,
 					     &new_remote_refs);
 			if (new_remote_refs) {
 				refs = new_remote_refs;
@@ -1124,7 +1124,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	if (is_local)
 		clone_local(path, git_dir);
 	else if (refs && complete_refs_before_fetch)
-		transport_fetch_refs(transport, mapped_refs, NULL);
+		transport_fetch_refs(transport, NULL, 0, mapped_refs, NULL);
 
 	update_remote_refs(refs, mapped_refs, remote_head_points_at,
 			   branch_top.buf, reflog_msg.buf, transport, !is_local);
diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c
index 24af3b7c5..ed1608c12 100644
--- a/builtin/fetch-pack.c
+++ b/builtin/fetch-pack.c
@@ -35,6 +35,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
 	struct fetch_pack_args args;
 	struct sha1_array shallow = SHA1_ARRAY_INIT;
 	struct string_list deepen_not = STRING_LIST_INIT_DUP;
+	int always_print_refs = 0;
 
 	packet_trace_identity("fetch-pack");
 
@@ -126,6 +127,10 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
 			args.update_shallow = 1;
 			continue;
 		}
+		if (!strcmp("--always-print-refs", arg)) {
+			always_print_refs = 1;
+			continue;
+		}
 		usage(fetch_pack_usage);
 	}
 	if (deepen_not.nr)
@@ -218,7 +223,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
 		ret = 1;
 	}
 
-	if (args.stateless_rpc)
+	if (args.stateless_rpc && !always_print_refs)
 		goto cleanup;
 
 	while (ref) {
@@ -226,6 +231,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
 		       oid_to_hex(&ref->old_oid), ref->name);
 		ref = ref->next;
 	}
+	fflush(stdout);
 
 cleanup:
 	close(fd[0]);
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 19e3f40a0..87de00e49 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -302,10 +302,75 @@ static void find_non_local_tags(const struct ref *refs,
 	string_list_clear(&remote_refs, 0);
 }
 
+static void get_effective_refspecs(struct refspec **e_rs, int *e_rs_nr,
+				   const struct remote *remote,
+				   const struct refspec *cli_rs, int cli_rs_nr,
+				   int tags, int *autotags)
+{
+	static struct refspec head_refspec;
+
+	const struct refspec *base_rs;
+	int base_rs_nr;
+	struct branch *merge_branch = NULL;
+	int i;
+
+	struct refspec *rs;
+	int nr, alloc;
+
+	if (cli_rs_nr) {
+		base_rs = cli_rs;
+		base_rs_nr = cli_rs_nr;
+	} else if (refmap_array) {
+		die("--refmap option is only meaningful with command-line refspec(s).");
+	} else {
+		/* Use the defaults */
+		struct branch *branch = branch_get(NULL);
+		int has_merge = branch_has_merge_config(branch);
+		/* Note: has_merge implies non-NULL branch->remote_name */
+		if (has_merge && !strcmp(branch->remote_name, remote->name))
+			/*
+			 * if the remote we're fetching from is the same
+			 * as given in branch.<name>.remote, we add the
+			 * ref given in branch.<name>.merge, too.
+			 */
+			merge_branch = branch;
+		if (remote &&
+		    (remote->fetch_refspec_nr || merge_branch)) {
+			base_rs = remote->fetch;
+			base_rs_nr = remote->fetch_refspec_nr;
+		} else {
+			head_refspec.src = "HEAD";
+			base_rs = &head_refspec;
+			base_rs_nr = 1;
+		}
+	}
+
+	for (i = 0; i < base_rs_nr; i++)
+		if (base_rs[i].dst && base_rs[i].dst[0]) {
+			*autotags = 1;
+			break;
+		}
+
+	alloc = base_rs_nr +
+		(merge_branch ? merge_branch->merge_nr : 0) +
+		(tags == TAGS_SET);
+	rs = xcalloc(alloc, sizeof(*rs));
+	memcpy(rs, base_rs, base_rs_nr * sizeof(*rs));
+	nr = base_rs_nr;
+	if (merge_branch)
+		for (i = 0; i < merge_branch->merge_nr; i++)
+			rs[nr++].src = merge_branch->merge[i]->src;
+	if (tags == TAGS_SET)
+		rs[nr++] = *tag_refspec;
+
+	*e_rs = rs;
+	*e_rs_nr = nr;
+}
+
 static struct ref *get_ref_map(const struct remote *remote,
 			       const struct ref *remote_refs,
 			       struct refspec *refspecs, int refspec_count,
-			       int tags, int *autotags)
+			       int tags, int autotags)
 {
 	int i;
 	struct ref *rm;
@@ -321,11 +386,8 @@ static struct ref *get_ref_map(const struct remote *remote,
 		struct refspec *fetch_refspec;
 		int fetch_refspec_nr;
 
-		for (i = 0; i < refspec_count; i++) {
+		for (i = 0; i < refspec_count; i++)
 			get_fetch_map(remote_refs, &refspecs[i], &tail, 0);
-			if (refspecs[i].dst && refspecs[i].dst[0])
-				*autotags = 1;
-		}
 		/* Merge everything on the command line (but not --tags) */
 		for (rm = ref_map; rm; rm = rm->next)
 			rm->fetch_head_status = FETCH_HEAD_MERGE;
@@ -372,9 +434,6 @@ static struct ref *get_ref_map(const struct remote *remote,
 		     (has_merge && !strcmp(branch->remote_name, remote->name)))) {
 			for (i = 0; i < remote->fetch_refspec_nr; i++) {
 				get_fetch_map(remote_refs, &remote->fetch[i], &tail, 0);
-				if (remote->fetch[i].dst &&
-				    remote->fetch[i].dst[0])
-					*autotags = 1;
 				if (!i && !has_merge && ref_map &&
 				    !remote->fetch[0].pattern)
 					ref_map->fetch_head_status = FETCH_HEAD_MERGE;
@@ -401,7 +460,7 @@ static struct ref *get_ref_map(const struct remote *remote,
 	if (tags == TAGS_SET)
 		/* also fetch all tags */
 		get_fetch_map(remote_refs, tag_refspec, &tail, 0);
-	else if (tags == TAGS_DEFAULT && *autotags)
+	else if (tags == TAGS_DEFAULT && autotags)
 		find_non_local_tags(remote_refs, &ref_map, &tail);
 
 	/* Now append any refs to be updated opportunistically: */
@@ -911,13 +970,14 @@ static int quickfetch(struct ref *ref_map)
 	return check_connected(iterate_ref_map, &rm, &opt);
 }
 
-static int fetch_refs(struct transport *transport, struct ref *ref_map,
-		      struct ref **updated_remote_refs)
+static int fetch_refs(struct transport *transport,
+		      struct refspec *refspecs, int refspec_nr,
+		      struct ref *ref_map, struct ref **updated_remote_refs)
 {
 	int ret = quickfetch(ref_map);
 	if (ret)
-		ret = transport_fetch_refs(transport, ref_map,
-					   updated_remote_refs);
+		ret = transport_fetch_refs(transport, refspecs, refspec_nr,
+					   ref_map, updated_remote_refs);
 	if (ret)
 		transport_unlock_pack(transport);
 	return ret;
@@ -1068,7 +1128,7 @@ static void backfill_tags(struct transport *transport, struct ref *ref_map)
 	transport_set_option(transport, TRANS_OPT_FOLLOWTAGS, NULL);
 	transport_set_option(transport, TRANS_OPT_DEPTH, "0");
 	transport_set_option(transport, TRANS_OPT_DEEPEN_RELATIVE, NULL);
-	if (!fetch_refs(transport, ref_map, NULL))
+	if (!fetch_refs(transport, NULL, 0, ref_map, NULL))
 		consume_refs(transport, ref_map);
 
 	if (gsecondary) {
@@ -1083,6 +1143,10 @@ static int do_fetch(struct transport *transport,
 	struct ref *ref_map;
 	int autotags = (transport->remote->fetch_tags == 1);
 	int retcode = 0;
+
+	struct refspec *e_rs;
+	int e_rs_nr;
+
 	const struct ref *remote_refs;
 	struct ref *new_remote_refs = NULL;
 
@@ -1103,9 +1167,11 @@ static int do_fetch(struct transport *transport,
 			goto cleanup;
 	}
 
+	get_effective_refspecs(&e_rs, &e_rs_nr, transport->remote,
+			       refs, ref_count, tags, &autotags);
 	remote_refs = transport_get_remote_refs(transport);
 	ref_map = get_ref_map(transport->remote, remote_refs, refs, ref_count,
-			      tags, &autotags);
+			      tags, autotags);
 	if (!update_head_ok)
 		check_not_current_branch(ref_map);
 
@@ -1126,7 +1192,7 @@ static int do_fetch(struct transport *transport,
 				   transport->url);
 		}
 	}
-	if (fetch_refs(transport, ref_map, &new_remote_refs)) {
+	if (fetch_refs(transport, e_rs, e_rs_nr, ref_map, &new_remote_refs)) {
 		free_refs(ref_map);
 		retcode = 1;
 		goto cleanup;
@@ -1134,7 +1200,7 @@ static int do_fetch(struct transport *transport,
 	if (new_remote_refs) {
 		free_refs(ref_map);
 		ref_map = get_ref_map(transport->remote, new_remote_refs,
-				      refs, ref_count, tags, &autotags);
+				      refs, ref_count, tags, autotags);
 		free_refs(new_remote_refs);
 	}
 
diff --git a/remote-curl.c b/remote-curl.c
index 34a97e732..e78959d47 100644
--- a/remote-curl.c
+++ b/remote-curl.c
@@ -12,6 +12,7 @@
 #include "credential.h"
 #include "sha1-array.h"
 #include "send-pack.h"
+#include "refs.h"
 
 static struct remote *remote;
 /* always ends with a trailing slash */
@@ -31,7 +32,8 @@ struct options {
 		thin : 1,
 		/* One of the SEND_PACK_PUSH_CERT_* constants. */
 		push_cert : 2,
-		deepen_relative : 1;
+		deepen_relative : 1,
+		echo_refs : 1;
 };
 static struct options options;
 static struct string_list cas_options = STRING_LIST_INIT_DUP;
@@ -139,6 +141,14 @@ static int set_option(const char *name, const char *value)
 		else
 			return -1;
 		return 0;
+	} else if (!strcmp(name, "echo-refs")) {
+		if (!strcmp(value, "true"))
+			options.echo_refs = 1;
+		else if (!strcmp(value, "false"))
+			options.echo_refs = 0;
+		else
+			return -1;
+		return 0;
 
 #if LIBCURL_VERSION_NUM >= 0x070a08
 	} else if (!strcmp(name, "family")) {
@@ -750,7 +760,7 @@ static int rpc_service(struct rpc_state *rpc, struct discovery *heads)
 	return err;
 }
 
-static int fetch_dumb(int nr_heads, struct ref **to_fetch)
+static int fetch_dumb(int nr_heads, const struct ref **to_fetch)
 {
 	struct walker *walker;
 	char **targets;
@@ -775,11 +785,24 @@ static int fetch_dumb(int nr_heads, struct ref **to_fetch)
 		free(targets[i]);
 	free(targets);
 
+	if (options.echo_refs) {
+		struct strbuf sb = STRBUF_INIT;
+		for (i = 0; i < nr_heads; i++) {
+			strbuf_reset(&sb);
+			strbuf_addf(&sb,
+				    "%s %s\n",
+				    oid_to_hex(&to_fetch[i]->old_oid),
+				    to_fetch[i]->name);
+			write_or_die(1, sb.buf, sb.len);
+		}
+	}
+
 	return ret ? error("fetch failed.") : 0;
 }
 
 static int fetch_git(struct discovery *heads,
-	int nr_heads, struct ref **to_fetch)
+	int nr_refspec, const struct refspec *refspecs,
+	int nr_heads, const struct ref **to_fetch)
 {
 	struct rpc_state rpc;
 	struct strbuf preamble = STRBUF_INIT;
@@ -811,10 +834,15 @@ static int fetch_git(struct discovery *heads,
 				 options.deepen_not.items[i].string);
 	if (options.deepen_relative && options.depth)
 		argv_array_push(&args, "--deepen-relative");
+	if (options.echo_refs)
+		argv_array_push(&args, "--always-print-refs");
 	argv_array_push(&args, url.buf);
 
-	for (i = 0; i < nr_heads; i++) {
-		struct ref *ref = to_fetch[i];
+	if (refspecs) {
+		for (i = 0; i < nr_refspec; i++)
+			packet_buf_write(&preamble, "%s\n", refspecs[i].src);
+	} else {
+		const struct ref *ref = to_fetch[i];
 		if (!*ref->name)
 			die("cannot fetch by sha1 over smart http");
 		packet_buf_write(&preamble, "%s %s\n",
@@ -837,46 +865,38 @@ static int fetch_git(struct discovery *heads,
 	return err;
 }
 
-static int fetch(int nr_heads, struct ref **to_fetch)
+static int fetch(int nr_refspec, const struct refspec *refspecs)
 {
+	const struct ref **to_fetch;
+	int nr;
+	int ret, i;
 	struct discovery *d = discover_refs("git-upload-pack", 0);
+	get_ref_array(&to_fetch, &nr, d->refs, refspecs, nr_refspec);
+
 	if (d->proto_git)
-		return fetch_git(d, nr_heads, to_fetch);
+		ret = fetch_git(d, nr_refspec, refspecs, nr, to_fetch);
 	else
-		return fetch_dumb(nr_heads, to_fetch);
+		ret = fetch_dumb(nr, to_fetch);
+
+	for (i = 0; i < nr; i++) {
+		free((void *) to_fetch[i]);
+	}
+	free(to_fetch);
+
+	return ret;
 }
 
 static void parse_fetch(struct strbuf *buf)
 {
-	struct ref **to_fetch = NULL;
-	struct ref *list_head = NULL;
-	struct ref **list = &list_head;
-	int alloc_heads = 0, nr_heads = 0;
+	struct refspec *to_fetch = NULL;
+	int alloc = 0, nr = 0;
 
 	do {
 		const char *p;
 		if (skip_prefix(buf->buf, "fetch ", &p)) {
-			const char *name;
-			struct ref *ref;
-			struct object_id old_oid;
-
-			if (get_oid_hex(p, &old_oid))
-				die("protocol error: expected sha/ref, got %s'", p);
-			if (p[GIT_SHA1_HEXSZ] == ' ')
-				name = p + GIT_SHA1_HEXSZ + 1;
-			else if (!p[GIT_SHA1_HEXSZ])
-				name = "";
-			else
-				die("protocol error: expected sha/ref, got %s'", p);
-
-			ref = alloc_ref(name);
-			oidcpy(&ref->old_oid, &old_oid);
-
-			*list = ref;
-			list = &ref->next;
-
-			ALLOC_GROW(to_fetch, nr_heads + 1, alloc_heads);
-			to_fetch[nr_heads++] = ref;
+			nr++;
+			ALLOC_GROW(to_fetch, nr, alloc);
+			parse_ref_or_pattern(&to_fetch[nr - 1], p);
 		}
 		else
 			die("http transport does not support %s", buf->buf);
@@ -888,10 +908,8 @@ static void parse_fetch(struct strbuf *buf)
 			break;
 	} while (1);
 
-	if (fetch(nr_heads, to_fetch))
+	if (fetch(nr, to_fetch))
 		exit(128); /* error already reported */
-	free_refs(list_head);
-	free(to_fetch);
 
 	printf("\n");
 	fflush(stdout);
@@ -1084,6 +1102,7 @@ int cmd_main(int argc, const char **argv)
 			printf("option\n");
 			printf("push\n");
 			printf("check-connectivity\n");
+			printf("echo-refs\n");
 			printf("\n");
 			fflush(stdout);
 		} else {
diff --git a/t/t5552-upload-pack-ref-in-want.sh b/t/t5552-upload-pack-ref-in-want.sh
index 80cf2263a..26e785f3b 100755
--- a/t/t5552-upload-pack-ref-in-want.sh
+++ b/t/t5552-upload-pack-ref-in-want.sh
@@ -345,7 +345,7 @@ test_expect_success 'server is initially ahead - no ref in want' '
 	grep "ERR upload-pack: not our ref" err
 '
 
-test_expect_failure 'server is initially ahead - ref in want' '
+test_expect_success 'server is initially ahead - ref in want' '
 	git -C "$REPO" config uploadpack.advertiseRefInWant true &&
 	rm -rf local &&
 	cp -r "$LOCAL_PRISTINE" local &&
@@ -369,7 +369,7 @@ test_expect_success 'server is initially behind - no ref in want' '
 	test_cmp expected actual
 '
 
-test_expect_failure 'server is initially behind - ref in want' '
+test_expect_success 'server is initially behind - ref in want' '
 	git -C "$REPO" config uploadpack.advertiseRefInWant true &&
 	rm -rf local &&
 	cp -r "$LOCAL_PRISTINE" local &&
diff --git a/transport-helper.c b/transport-helper.c
index be0aa6d39..fcd9edcdc 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -28,7 +28,8 @@ struct helper_data {
 		signed_tags : 1,
 		check_connectivity : 1,
 		no_disconnect_req : 1,
-		no_private_update : 1;
+		no_private_update : 1,
+		echo_refs : 1;
 	char *export_marks;
 	char *import_marks;
 	/* These go from remote name (as in "list") to private name */
@@ -195,6 +196,8 @@ static struct child_process *get_helper(struct transport *transport)
 			data->import_marks = xstrdup(arg);
 		} else if (starts_with(capname, "no-private-update")) {
 			data->no_private_update = 1;
+		} else if (!strcmp(capname, "echo-refs")) {
+			data->echo_refs = 1;
 		} else if (mandatory) {
 			die("Unknown mandatory capability %s. This remote "
 			    "helper probably needs newer version of Git.",
@@ -383,27 +386,49 @@ static int release_helper(struct transport *transport)
 	return res;
 }
 
+static struct ref *copy_ref_array(struct ref **array, int nr)
+{
+	struct ref *head = NULL, **tail = &head;
+	int i;
+	for (i = 0; i < nr; i++) {
+		*tail = copy_ref(array[i]);
+		tail = &(*tail)->next;
+	}
+	return head;
+}
+
 static int fetch_with_fetch(struct transport *transport,
-			    int nr_heads, const struct ref **to_fetch)
+			    int nr_refspec, const struct refspec *refspecs,
+			    int nr_heads, const struct ref **to_fetch,
+			    struct ref **fetched_refs)
 {
 	struct helper_data *data = transport->data;
 	int i;
 	struct strbuf buf = STRBUF_INIT;
-
-	for (i = 0; i < nr_heads; i++) {
-		const struct ref *posn = to_fetch[i];
-		if (posn->status & REF_STATUS_UPTODATE)
-			continue;
-
-		strbuf_addf(&buf, "fetch %s %s\n",
-			    oid_to_hex(&posn->old_oid),
-			    posn->symref ? posn->symref : posn->name);
+	int use_echo_refs = data->echo_refs && refspecs;
+	struct ref *fetched = NULL;
+
+	if (use_echo_refs) {
+		set_helper_option(transport, "echo-refs", "true");
+		for (i = 0; i < nr_refspec; i++)
+			strbuf_addf(&buf, "fetch %s\n", refspecs[i].src);
+	} else {
+		for (i = 0; i < nr_heads; i++) {
+			const struct ref *posn = to_fetch[i];
+			if (posn->status & REF_STATUS_UPTODATE)
+				continue;
+
+			strbuf_addf(&buf, "fetch %s %s\n",
+				    oid_to_hex(&posn->old_oid),
+				    posn->symref ? posn->symref : posn->name);
+		}
 	}
 
 	strbuf_addch(&buf, '\n');
 	sendline(data, &buf);
 
 	while (1) {
+		struct object_id oid;
 		if (recvline(data, &buf))
 			exit(128);
 
@@ -418,12 +443,29 @@ static int fetch_with_fetch(struct transport *transport,
 			 data->transport_options.check_self_contained_and_connected &&
 			 !strcmp(buf.buf, "connectivity-ok"))
 			data->transport_options.self_contained_and_connected = 1;
-		else if (!buf.len)
+		else if (use_echo_refs && !get_oid_hex(buf.buf, &oid)
+			 && buf.buf[GIT_SHA1_HEXSZ] == ' ') {
+			struct ref *ref = alloc_ref(buf.buf + GIT_SHA1_HEXSZ + 1);
+			oidcpy(&ref->old_oid, &oid);
+			ref->next = fetched;
+			fetched = ref;
+		} else if (!buf.len)
 			break;
 		else
 			warning("%s unexpectedly said: '%s'", data->name, buf.buf);
 	}
 	strbuf_release(&buf);
+
+	if (use_echo_refs) {
+		if (fetched_refs)
+			*fetched_refs = fetched;
+	} else {
+		assert(fetched == NULL);
+		if (fetched_refs)
+			*fetched_refs = copy_ref_array((struct ref **) to_fetch,
+						       nr_heads);
+	}
+
 	return 0;
 }
 
@@ -657,6 +699,7 @@ static int connect_helper(struct transport *transport, const char *name,
 }
 
 static int fetch(struct transport *transport,
+		 int nr_refspec, const struct refspec *refspecs,
 		 int nr_heads, const struct ref **to_fetch,
 		 struct ref **fetched_refs)
 {
@@ -665,8 +708,8 @@ static int fetch(struct transport *transport,
 
 	if (process_connect(transport, 0)) {
 		do_take_over(transport);
-		return transport->fetch(transport, nr_heads, to_fetch,
-					fetched_refs);
+		return transport->fetch(transport, nr_refspec, refspecs,
+					nr_heads, to_fetch, fetched_refs);
 	}
 
 	count = 0;
@@ -688,7 +731,8 @@ static int fetch(struct transport *transport,
 		set_helper_option(transport, "update-shallow", "true");
 
 	if (data->fetch)
-		return fetch_with_fetch(transport, nr_heads, to_fetch);
+		return fetch_with_fetch(transport, nr_refspec, refspecs,
+					nr_heads, to_fetch, fetched_refs);
 
 	if (data->import)
 		return fetch_with_import(transport, nr_heads, to_fetch, fetched_refs);
diff --git a/transport.c b/transport.c
index 85a4c5369..734c605b1 100644
--- a/transport.c
+++ b/transport.c
@@ -95,6 +95,7 @@ static struct ref *get_refs_from_bundle(struct transport *transport, int for_pus
 }
 
 static int fetch_refs_from_bundle(struct transport *transport,
+			       int nr_refspec, const struct refspec *refspecs,
 			       int nr_heads, const struct ref **to_fetch,
 			       struct ref **fetched_refs)
 {
@@ -203,6 +204,7 @@ static struct ref *get_refs_via_connect(struct transport *transport, int for_pus
 }
 
 static int fetch_refs_via_pack(struct transport *transport,
+			       int nr_refspec, const struct refspec *refspecs,
 			       int nr_heads, const struct ref **to_fetch,
 			       struct ref **fetched_refs)
 {
@@ -1096,8 +1098,9 @@ const struct ref *transport_get_remote_refs(struct transport *transport)
 	return transport->remote_refs;
 }
 
-int transport_fetch_refs(struct transport *transport, struct ref *refs,
-			 struct ref **fetched_refs)
+int transport_fetch_refs(struct transport *transport,
+			 const struct refspec *refspecs, int refspec_nr,
+			 struct ref *refs, struct ref **fetched_refs)
 {
 	int rc;
 	int nr_heads = 0, nr_alloc = 0, nr_refs = 0;
@@ -1136,7 +1139,8 @@ int transport_fetch_refs(struct transport *transport, struct ref *refs,
 			heads[nr_heads++] = rm;
 	}
 
-	rc = transport->fetch(transport, nr_heads, heads, fetched_refs);
+	rc = transport->fetch(transport, refspec_nr, refspecs,
+			      nr_heads, heads, fetched_refs);
 	if (nop_head) {
 		*nop_tail = *fetched_refs;
 		*fetched_refs = nop_head;
diff --git a/transport.h b/transport.h
index 326ff9bd6..d7a007d21 100644
--- a/transport.h
+++ b/transport.h
@@ -82,13 +82,20 @@ struct transport {
 	 * Fetch the objects for the given refs. Note that this gets
 	 * an array, and should ignore the list structure.
 	 *
+	 * The user may provide the array of refspecs used to generate the
+	 * given refs. If provided, the transport should prefer the refspecs if
+	 * possible (but may still use the refs for pre-fetch optimizations,
+	 * for example).
+	 *
 	 * The transport *may* provide, in fetched_refs, the list of refs that
-	 * it fetched. If the transport knows anything about the fetched refs
-	 * that the caller does not know (for example, shallow status or ref
-	 * hashes), it should provide that list of refs and include that
-	 * information in the list.
+	 * it fetched, and must do so if it is different from the given refs.
+	 * If the transport knows anything about the fetched refs that the
+	 * caller does not know (for example, shallow status or ref hashes), it
+	 * should provide that list of refs and include that information in the
+	 * list.
 	 **/
 	int (*fetch)(struct transport *transport,
+		     int refspec_nr, const struct refspec *refspecs,
 		     int refs_nr, const struct ref **refs,
 		     struct ref **fetched_refs);
 
@@ -234,8 +241,9 @@ int transport_push(struct transport *connection,
 
 const struct ref *transport_get_remote_refs(struct transport *transport);
 
-int transport_fetch_refs(struct transport *transport, struct ref *refs,
-			 struct ref **fetched_refs);
+int transport_fetch_refs(struct transport *transport,
+			 const struct refspec *refspecs, int refspec_nr,
+			 struct ref *refs, struct ref **fetched_refs);
 void transport_unlock_pack(struct transport *transport);
 int transport_disconnect(struct transport *transport);
 char *transport_anonymize_url(const char *url);
-- 
2.11.0.483.g087da7b7c-goog


  parent reply	other threads:[~2017-01-25 22:03 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-01-25 22:02 [RFC 00/14] Allow fetch-pack to send ref names (globs allowed) Jonathan Tan
2017-01-25 22:02 ` [RFC 01/14] upload-pack: move parsing of "want" line Jonathan Tan
2017-01-25 22:02 ` [RFC 02/14] upload-pack: allow ref name and glob requests Jonathan Tan
2017-01-26 22:23   ` Junio C Hamano
2017-01-27  0:35     ` Jonathan Tan
2017-01-27  1:54       ` Junio C Hamano
2017-01-25 22:02 ` [RFC 03/14] upload-pack: test negotiation with changing repo Jonathan Tan
2017-01-26 22:33   ` Junio C Hamano
2017-01-27  0:44     ` Jonathan Tan
2017-02-22 23:36       ` Junio C Hamano
2017-02-23 18:43         ` [PATCH] upload-pack: report "not our ref" to client Jonathan Tan
2017-02-23 20:14           ` Junio C Hamano
2017-01-25 22:02 ` [RFC 04/14] fetch: refactor the population of hashes Jonathan Tan
2017-01-25 22:02 ` [RFC 05/14] fetch: refactor fetch_refs into two functions Jonathan Tan
2017-01-25 22:02 ` [RFC 06/14] fetch: refactor to make function args narrower Jonathan Tan
2017-01-25 22:03 ` [RFC 07/14] fetch-pack: put shallow info in out param Jonathan Tan
2017-01-25 22:03 ` [RFC 08/14] fetch-pack: check returned refs for matches Jonathan Tan
2017-01-25 22:03 ` [RFC 09/14] transport: put ref oid in out param Jonathan Tan
2017-01-25 22:03 ` [RFC 10/14] fetch-pack: support partial names and globs Jonathan Tan
2017-01-25 22:03 ` [RFC 11/14] fetch-pack: support want-ref Jonathan Tan
2017-01-25 22:03 ` [RFC 12/14] fetch-pack: do not printf after closing stdout Jonathan Tan
2017-01-26  0:50   ` Stefan Beller
2017-01-26 18:18     ` Jonathan Tan
2017-01-25 22:03 ` Jonathan Tan [this message]
2017-01-25 22:03 ` [RFC 14/14] DONT USE advertise_ref_in_want=1 Jonathan Tan
2017-01-26 22:15 ` [RFC 00/14] Allow fetch-pack to send ref names (globs allowed) Stefan Beller
2017-01-26 23:00 ` Jeff King
2017-01-27  0:26   ` Jonathan Tan
2017-02-07 23:53 ` Jonathan Tan
2017-02-09  0:26   ` 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=eef2b77d88df0db08e4a1505b06e0af2d40143d5.1485381677.git.jonathantanmy@google.com \
    --to=jonathantanmy@google.com \
    --cc=git@vger.kernel.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.