summaryrefslogtreecommitdiff
path: root/src/libgit2/transports/smart_protocol.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libgit2/transports/smart_protocol.c')
-rw-r--r--src/libgit2/transports/smart_protocol.c56
1 files changed, 50 insertions, 6 deletions
diff --git a/src/libgit2/transports/smart_protocol.c b/src/libgit2/transports/smart_protocol.c
index 6167a8074..488ef07c0 100644
--- a/src/libgit2/transports/smart_protocol.c
+++ b/src/libgit2/transports/smart_protocol.c
@@ -364,7 +364,9 @@ static int cap_not_sup_err(const char *cap_name)
}
/* Disables server capabilities we're not interested in */
-static int setup_caps(transport_smart_caps *caps, const git_fetch_negotiation *wants)
+static int setup_caps(
+ transport_smart_caps *caps,
+ const git_fetch_negotiation *wants)
{
if (wants->depth > 0) {
if (!caps->shallow)
@@ -376,7 +378,27 @@ static int setup_caps(transport_smart_caps *caps, const git_fetch_negotiation *w
return 0;
}
-int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, const git_fetch_negotiation *wants)
+static int setup_shallow_roots(
+ git_array_oid_t *out,
+ const git_fetch_negotiation *wants)
+{
+ git_array_clear(*out);
+
+ if (wants->shallow_roots_len > 0) {
+ git_array_init_to_size(*out, wants->shallow_roots_len);
+ GIT_ERROR_CHECK_ALLOC(out->ptr);
+
+ memcpy(out->ptr, wants->shallow_roots,
+ sizeof(git_oid) * wants->shallow_roots_len);
+ }
+
+ return 0;
+}
+
+int git_smart__negotiate_fetch(
+ git_transport *transport,
+ git_repository *repo,
+ const git_fetch_negotiation *wants)
{
transport_smart *t = (transport_smart *)transport;
git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT;
@@ -388,7 +410,8 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c
unsigned int i;
git_oid oid;
- if ((error = setup_caps(&t->caps, wants)) < 0)
+ if ((error = setup_caps(&t->caps, wants)) < 0 ||
+ (error = setup_shallow_roots(&t->shallow_roots, wants)) < 0)
return error;
if ((error = git_pkt_buffer_wants(wants, &t->caps, &data)) < 0)
@@ -411,9 +434,9 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c
bool complete = false;
if (pkt->type == GIT_PKT_SHALLOW) {
- git_shallowarray_add(wants->shallow_roots, &pkt->oid);
+ error = git_oidarray__add(&t->shallow_roots, &pkt->oid);
} else if (pkt->type == GIT_PKT_UNSHALLOW) {
- git_shallowarray_remove(wants->shallow_roots, &pkt->oid);
+ git_oidarray__remove(&t->shallow_roots, &pkt->oid);
} else if (pkt->type == GIT_PKT_FLUSH) {
/* Server is done, stop processing shallow oids */
complete = true;
@@ -431,6 +454,7 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c
if (error < 0)
goto on_error;
}
+
/*
* Our support for ACK extensions is simply to parse them. On
* the first ACK we will accept that as enough common
@@ -531,10 +555,11 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c
goto on_error;
if (t->cancelled.val) {
- git_error_set(GIT_ERROR_NET, "The fetch was cancelled by the user");
+ git_error_set(GIT_ERROR_NET, "the fetch was cancelled");
error = GIT_EUSER;
goto on_error;
}
+
if ((error = git_smart__negotiation_step(&t->parent, data.ptr, data.size)) < 0)
goto on_error;
@@ -562,6 +587,25 @@ on_error:
return error;
}
+int git_smart__shallow_roots(git_oidarray *out, git_transport *transport)
+{
+ transport_smart *t = (transport_smart *)transport;
+ size_t len;
+
+ GIT_ERROR_CHECK_ALLOC_MULTIPLY(&len, t->shallow_roots.size, sizeof(git_oid));
+
+ out->count = t->shallow_roots.size;
+
+ if (len) {
+ out->ids = git__malloc(len);
+ memcpy(out->ids, t->shallow_roots.ptr, len);
+ } else {
+ out->ids = NULL;
+ }
+
+ return 0;
+}
+
static int no_sideband(transport_smart *t, struct git_odb_writepack *writepack, gitno_buffer *buf, git_indexer_progress *stats)
{
int recvd;