summaryrefslogtreecommitdiff
path: root/src/server.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/server.c')
-rw-r--r--src/server.c46
1 files changed, 46 insertions, 0 deletions
diff --git a/src/server.c b/src/server.c
index 047f8d22e..766726798 100644
--- a/src/server.c
+++ b/src/server.c
@@ -29,6 +29,8 @@ void git_server_free(git_server *server)
if (server == NULL)
return;
+ git_array_clear(server->wants);
+ git_array_clear(server->common);
git__free(server->path);
git__free(server);
}
@@ -98,6 +100,50 @@ cleanup:
return error;
}
+int git_server__negotiation(git_server *server, git_pkt *_pkt)
+{
+ git_oid *id, *have_id;
+ git_pkt_have_want *pkt;
+ git_odb *odb = NULL;
+ int error;
+
+ if (_pkt->type != GIT_PKT_HAVE && _pkt->type != GIT_PKT_WANT) {
+ giterr_set(GITERR_NET, "invalid pkt for negotiation");
+ return -1;
+ }
+
+ pkt = (git_pkt_have_want *) _pkt;
+
+ if (pkt->type == GIT_PKT_WANT) {
+ id = git_array_alloc(server->wants);
+ GITERR_CHECK_ALLOC(id);
+
+ git_oid_cpy(id, &pkt->id);
+ return 0;
+ }
+
+ /* we know it's a 'have', so we check to see if it's common */
+ have_id = &pkt->id;
+ if ((error = git_repository_odb(&odb, server->repo)) < 0)
+ return error;
+
+ if ((error = git_odb_exists(odb, have_id)) < 0)
+ goto cleanup;
+
+ if (error == 1) {
+ error = 0;
+ id = git_array_alloc(server->common);
+ GITERR_CHECK_ALLOC(id);
+
+ git_oid_cpy(id, &pkt->id);
+ }
+
+cleanup:
+ git_odb_free(odb);
+
+ return error;
+}
+
int git_server_run(git_server *server)
{
/* 65535 is the max size of a pkt frame */