summaryrefslogtreecommitdiff
path: root/src/transports/smart_protocol.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/transports/smart_protocol.c')
-rw-r--r--src/transports/smart_protocol.c63
1 files changed, 59 insertions, 4 deletions
diff --git a/src/transports/smart_protocol.c b/src/transports/smart_protocol.c
index 91de163e9..df1931191 100644
--- a/src/transports/smart_protocol.c
+++ b/src/transports/smart_protocol.c
@@ -205,6 +205,12 @@ int git_smart__detect_caps(git_pkt_ref *pkt, transport_smart_caps *caps, git_vec
continue;
}
+ if (!git__prefixcmp(ptr, GIT_CAP_SHALLOW)) {
+ caps->common = caps->shallow = 1;
+ ptr += strlen(GIT_CAP_SHALLOW);
+ continue;
+ }
+
/* We don't know this capability, so skip it */
ptr = strchr(ptr, ' ');
}
@@ -305,7 +311,26 @@ static int wait_while_ack(gitno_buffer *buf)
return 0;
}
-int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, const git_remote_head * const *wants, size_t count)
+static int cap_not_sup_err(const char *cap_name)
+{
+ git_error_set(GIT_ERROR_NET, "server doesn't support %s", cap_name);
+ return GIT_EINVALID;
+}
+
+/* Disables server capabilities we're not interested in */
+static int setup_caps(transport_smart_caps *caps, const git_fetch_negotiation *wants)
+{
+ if (wants->depth) {
+ if (!caps->shallow)
+ return cap_not_sup_err(GIT_CAP_SHALLOW);
+ } else {
+ caps->shallow = 0;
+ }
+
+ 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;
@@ -317,7 +342,10 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c
unsigned int i;
git_oid oid;
- if ((error = git_pkt_buffer_wants(wants, count, &t->caps, &data)) < 0)
+ if ((error = setup_caps(&t->caps, wants)) < 0)
+ return error;
+
+ if ((error = git_pkt_buffer_wants(wants, &t->caps, &data)) < 0)
return error;
if ((error = git_revwalk_new(&walk, repo)) < 0)
@@ -327,6 +355,33 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c
if ((error = git_revwalk__push_glob(walk, "refs/*", &opts)) < 0)
goto on_error;
+ if (wants->depth > 0) {
+ git_pkt_shallow *pkt;
+
+ if ((error = git_smart__negotiation_step(&t->parent, data.ptr, data.size)) < 0)
+ goto on_error;
+
+ while ((error = recv_pkt((git_pkt **)&pkt, NULL, buf)) == 0) {
+
+ if (pkt->type == GIT_PKT_SHALLOW) {
+ printf("shallow %s\n", git_oid_tostr_s(&pkt->oid));
+ git_shallowarray_add(wants->shallow_roots, &pkt->oid);
+ } else if (pkt->type == GIT_PKT_UNSHALLOW) {
+ printf("unshallow %s\n", git_oid_tostr_s(&pkt->oid));
+ git_shallowarray_remove(wants->shallow_roots, &pkt->oid);
+ } else if (pkt->type == GIT_PKT_FLUSH) {
+ /* Server is done, stop processing shallow oids */
+ break;
+ } else {
+ git_error_set(GIT_ERROR_NET, "Unexpected pkt type");
+ goto on_error;
+ }
+ }
+
+ 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
@@ -389,7 +444,7 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c
git_pkt_ack *pkt;
unsigned int j;
- if ((error = git_pkt_buffer_wants(wants, count, &t->caps, &data)) < 0)
+ if ((error = git_pkt_buffer_wants(wants, &t->caps, &data)) < 0)
goto on_error;
git_vector_foreach(&t->common, j, pkt) {
@@ -409,7 +464,7 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c
git_pkt_ack *pkt;
unsigned int j;
- if ((error = git_pkt_buffer_wants(wants, count, &t->caps, &data)) < 0)
+ if ((error = git_pkt_buffer_wants(wants, &t->caps, &data)) < 0)
goto on_error;
git_vector_foreach(&t->common, j, pkt) {