Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.kernel.org/pub/scm/git/git.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2018-10-19 07:34:07 +0300
committerJunio C Hamano <gitster@pobox.com>2018-10-19 07:34:07 +0300
commit0527fbab689929de47ab3fa7baf1e7618ffa704f (patch)
tree225a1b7916ff4b81f30d661f0014f973eea38642 /transport.c
parentd4cd2dd214c9800c8ccf45cf413acc727f4abcc2 (diff)
parente70a3030e747312327a4f3619247bf8a986aa577 (diff)
Merge branch 'jt/avoid-ls-refs'
Over some transports, fetching objects with an exact commit object name can be done without first seeing the ref advertisements. The code has been optimized to exploit this. * jt/avoid-ls-refs: fetch: do not list refs if fetching only hashes transport: list refs before fetch if necessary transport: do not list refs if possible transport: allow skipping of ref listing
Diffstat (limited to 'transport.c')
-rw-r--r--transport.c54
1 files changed, 48 insertions, 6 deletions
diff --git a/transport.c b/transport.c
index dd7bd3436c..046b2f6d8c 100644
--- a/transport.c
+++ b/transport.c
@@ -252,8 +252,18 @@ static int connect_setup(struct transport *transport, int for_push)
return 0;
}
-static struct ref *get_refs_via_connect(struct transport *transport, int for_push,
- const struct argv_array *ref_prefixes)
+/*
+ * Obtains the protocol version from the transport and writes it to
+ * transport->data->version, first connecting if not already connected.
+ *
+ * If the protocol version is one that allows skipping the listing of remote
+ * refs, and must_list_refs is 0, the listing of remote refs is skipped and
+ * this function returns NULL. Otherwise, this function returns the list of
+ * remote refs.
+ */
+static struct ref *handshake(struct transport *transport, int for_push,
+ const struct argv_array *ref_prefixes,
+ int must_list_refs)
{
struct git_transport_data *data = transport->data;
struct ref *refs = NULL;
@@ -268,8 +278,10 @@ static struct ref *get_refs_via_connect(struct transport *transport, int for_pus
data->version = discover_version(&reader);
switch (data->version) {
case protocol_v2:
- get_remote_refs(data->fd[1], &reader, &refs, for_push,
- ref_prefixes, transport->server_options);
+ if (must_list_refs)
+ get_remote_refs(data->fd[1], &reader, &refs, for_push,
+ ref_prefixes,
+ transport->server_options);
break;
case protocol_v1:
case protocol_v0:
@@ -283,9 +295,18 @@ static struct ref *get_refs_via_connect(struct transport *transport, int for_pus
}
data->got_remote_heads = 1;
+ if (reader.line_peeked)
+ BUG("buffer must be empty at the end of handshake()");
+
return refs;
}
+static struct ref *get_refs_via_connect(struct transport *transport, int for_push,
+ const struct argv_array *ref_prefixes)
+{
+ return handshake(transport, for_push, ref_prefixes, 1);
+}
+
static int fetch_refs_via_pack(struct transport *transport,
int nr_heads, struct ref **to_fetch)
{
@@ -320,8 +341,17 @@ static int fetch_refs_via_pack(struct transport *transport,
args.server_options = transport->server_options;
args.negotiation_tips = data->options.negotiation_tips;
- if (!data->got_remote_heads)
- refs_tmp = get_refs_via_connect(transport, 0, NULL);
+ if (!data->got_remote_heads) {
+ int i;
+ int must_list_refs = 0;
+ for (i = 0; i < nr_heads; i++) {
+ if (!to_fetch[i]->exact_oid) {
+ must_list_refs = 1;
+ break;
+ }
+ }
+ refs_tmp = handshake(transport, 0, NULL, must_list_refs);
+ }
switch (data->version) {
case protocol_v2:
@@ -703,6 +733,7 @@ static int disconnect_git(struct transport *transport)
}
static struct transport_vtable taken_over_vtable = {
+ 1,
NULL,
get_refs_via_connect,
fetch_refs_via_pack,
@@ -852,6 +883,7 @@ void transport_check_allowed(const char *type)
}
static struct transport_vtable bundle_vtable = {
+ 0,
NULL,
get_refs_from_bundle,
fetch_refs_from_bundle,
@@ -861,6 +893,7 @@ static struct transport_vtable bundle_vtable = {
};
static struct transport_vtable builtin_smart_vtable = {
+ 1,
NULL,
get_refs_via_connect,
fetch_refs_via_pack,
@@ -1227,6 +1260,15 @@ int transport_fetch_refs(struct transport *transport, struct ref *refs)
struct ref **heads = NULL;
struct ref *rm;
+ if (!transport->vtable->fetch_without_list)
+ /*
+ * Some transports (e.g. the built-in bundle transport and the
+ * transport helper interface) do not work when fetching is
+ * done immediately after transport creation. List the remote
+ * refs anyway (if not already listed) as a workaround.
+ */
+ transport_get_remote_refs(transport, NULL);
+
for (rm = refs; rm; rm = rm->next) {
nr_refs++;
if (rm->peer_ref &&