summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server.c46
-rw-r--r--src/server.h6
2 files changed, 52 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 */
diff --git a/src/server.h b/src/server.h
index eff5dd4ec..943eaa2cd 100644
--- a/src/server.h
+++ b/src/server.h
@@ -9,6 +9,9 @@
#include "common.h"
#include "transports/smart.h"
+#include "array.h"
+
+typedef git_array_t(git_oid) git_oid_array;
struct git_server {
enum git_request_type type;
@@ -16,12 +19,15 @@ struct git_server {
gitno_socket s;
int rpc;
char *path;
+ git_oid_array common;
+ git_oid_array wants;
};
extern int git_server_new(git_server **out, git_repository *repo, int fd);
extern void git_server_free(git_server *server);
extern int git_server__handle_request(git_server *server, git_pkt *pkt);
extern int git_server__ls(git_buf *out, git_server *server);
+extern int git_server__negotiation(git_server *server, git_pkt *_pkt);
#endif