Skip to content

Commit 4625003

Browse files
committed
server: handle negotiation lines
A bit of scaffolding for handling the lines from the client telling us about its commits.
1 parent 16b2052 commit 4625003

File tree

4 files changed

+125
-0
lines changed

4 files changed

+125
-0
lines changed

src/server.c

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ void git_server_free(git_server *server)
2929
if (server == NULL)
3030
return;
3131

32+
git_array_clear(server->wants);
33+
git_array_clear(server->common);
3234
git__free(server->path);
3335
git__free(server);
3436
}
@@ -98,6 +100,50 @@ int git_server__ls(git_buf *out, git_server *server)
98100
return error;
99101
}
100102

103+
int git_server__negotiation(git_server *server, git_pkt *_pkt)
104+
{
105+
git_oid *id, *have_id;
106+
git_pkt_have_want *pkt;
107+
git_odb *odb = NULL;
108+
int error;
109+
110+
if (_pkt->type != GIT_PKT_HAVE && _pkt->type != GIT_PKT_WANT) {
111+
giterr_set(GITERR_NET, "invalid pkt for negotiation");
112+
return -1;
113+
}
114+
115+
pkt = (git_pkt_have_want *) _pkt;
116+
117+
if (pkt->type == GIT_PKT_WANT) {
118+
id = git_array_alloc(server->wants);
119+
GITERR_CHECK_ALLOC(id);
120+
121+
git_oid_cpy(id, &pkt->id);
122+
return 0;
123+
}
124+
125+
/* we know it's a 'have', so we check to see if it's common */
126+
have_id = &pkt->id;
127+
if ((error = git_repository_odb(&odb, server->repo)) < 0)
128+
return error;
129+
130+
if ((error = git_odb_exists(odb, have_id)) < 0)
131+
goto cleanup;
132+
133+
if (error == 1) {
134+
error = 0;
135+
id = git_array_alloc(server->common);
136+
GITERR_CHECK_ALLOC(id);
137+
138+
git_oid_cpy(id, &pkt->id);
139+
}
140+
141+
cleanup:
142+
git_odb_free(odb);
143+
144+
return error;
145+
}
146+
101147
int git_server_run(git_server *server)
102148
{
103149
/* 65535 is the max size of a pkt frame */

src/server.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,25 @@
99

1010
#include "common.h"
1111
#include "transports/smart.h"
12+
#include "array.h"
13+
14+
typedef git_array_t(git_oid) git_oid_array;
1215

1316
struct git_server {
1417
enum git_request_type type;
1518
git_repository *repo;
1619
gitno_socket s;
1720
int rpc;
1821
char *path;
22+
git_oid_array common;
23+
git_oid_array wants;
1924
};
2025

2126
extern int git_server_new(git_server **out, git_repository *repo, int fd);
2227
extern void git_server_free(git_server *server);
2328
extern int git_server__handle_request(git_server *server, git_pkt *pkt);
2429
extern int git_server__ls(git_buf *out, git_server *server);
30+
extern int git_server__negotiation(git_server *server, git_pkt *_pkt);
2531

2632
#endif
2733

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#include "clar_libgit2.h"
2+
#include "transports/smart.h"
3+
4+
static git_pkt *pkt;
5+
6+
void test_network_protocol_negotiation__cleanup(void)
7+
{
8+
git_pkt_free(pkt);
9+
pkt = NULL;
10+
}
11+
12+
void test_network_protocol_negotiation__have(void)
13+
{
14+
const char buf[] = "0032have 7e47fe2bd8d01d481f44d7af0531bd93d3b21c01\n";
15+
const char *rest;
16+
git_oid id;
17+
git_pkt_have_want *ppkt;
18+
19+
git_oid_fromstr(&id, "7e47fe2bd8d01d481f44d7af0531bd93d3b21c01");
20+
21+
cl_git_pass(git_pkt_parse_line(&pkt, buf, &rest, sizeof(buf)));
22+
cl_assert_equal_i(GIT_PKT_HAVE, pkt->type);
23+
ppkt = (git_pkt_have_want *) pkt;
24+
cl_assert(!git_oid_cmp(&id, &ppkt->id));
25+
}
26+
27+
void test_network_protocol_negotiation__want(void)
28+
{
29+
const char buf[] = "0032want 7e47fe2bd8d01d481f44d7af0531bd93d3b21c01\n";
30+
const char *rest;
31+
git_oid id;
32+
git_pkt_have_want *ppkt;
33+
34+
git_oid_fromstr(&id, "7e47fe2bd8d01d481f44d7af0531bd93d3b21c01");
35+
36+
cl_git_pass(git_pkt_parse_line(&pkt, buf, &rest, sizeof(buf)));
37+
cl_assert_equal_i(GIT_PKT_WANT, pkt->type);
38+
ppkt = (git_pkt_have_want *) pkt;
39+
cl_assert(!git_oid_cmp(&id, &ppkt->id));
40+
}

tests/network/server.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,36 @@ void test_network_server__upload_pack_ls(void)
8181

8282
git_buf_free(&listing);
8383
}
84+
85+
void test_network_server__want(void)
86+
{
87+
const char buf[] = "0032want 7e47fe2bd8d01d481f44d7af0531bd93d3b21c01\n";
88+
const char *rest;
89+
90+
cl_git_pass(git_pkt_parse_line(&g_pkt, buf, &rest, sizeof(buf)));
91+
cl_git_pass(git_server_new(&g_server, g_repo, 0));
92+
cl_git_pass(git_server__negotiation(g_server, g_pkt));
93+
cl_assert_equal_i(1, git_array_size(g_server->wants));
94+
}
95+
96+
void test_network_server__have_no_common(void)
97+
{
98+
const char buf[] = "0032have 7e47fe2bd8d01d481f44d7af0531bd93d3b21c01\n";
99+
const char *rest;
100+
101+
cl_git_pass(git_pkt_parse_line(&g_pkt, buf, &rest, sizeof(buf)));
102+
cl_git_pass(git_server_new(&g_server, g_repo, 0));
103+
cl_git_pass(git_server__negotiation(g_server, g_pkt));
104+
cl_assert_equal_i(0, git_array_size(g_server->common));
105+
}
106+
107+
void test_network_server__have_common(void)
108+
{
109+
const char buf[] = "0032have a65fedf39aefe402d3bb6e24df4d4f5fe4547750\n";
110+
const char *rest;
111+
112+
cl_git_pass(git_pkt_parse_line(&g_pkt, buf, &rest, sizeof(buf)));
113+
cl_git_pass(git_server_new(&g_server, g_repo, 0));
114+
cl_git_pass(git_server__negotiation(g_server, g_pkt));
115+
cl_assert_equal_i(1, git_array_size(g_server->common));
116+
}

0 commit comments

Comments
 (0)