Line Flow Count Block(s) Source
1 - /*
2 - * Copyright (C) the libgit2 contributors. All rights reserved.
3 - *
4 - * This file is part of libgit2, distributed under the GNU GPL v2 with
5 - * a Linking Exception. For full terms see the included COPYING file.
6 - */
7 -
8 - #include "common.h"
9 -
10 - #include "git2/types.h"
11 - #include "git2/errors.h"
12 - #include "git2/refs.h"
13 - #include "git2/revwalk.h"
14 -
15 - #include "smart.h"
16 - #include "util.h"
17 - #include "netops.h"
18 - #include "posix.h"
19 - #include "buffer.h"
20 -
21 - #include <ctype.h>
22 -
23 - #define PKT_LEN_SIZE 4
24 - static const char pkt_done_str[] = "0009done\n";
25 - static const char pkt_flush_str[] = "0000";
26 - static const char pkt_have_prefix[] = "0032have ";
27 - static const char pkt_want_prefix[] = "0032want ";
28 -
29 122 2 static int flush_pkt(git_pkt **out)
30 - {
31 - git_pkt *pkt;
32 -
33 122 2 pkt = git__malloc(sizeof(git_pkt));
34 122 3,4 GIT_ERROR_CHECK_ALLOC(pkt);
35 -
36 122 5 pkt->type = GIT_PKT_FLUSH;
37 122 5 *out = pkt;
38 -
39 122 5 return 0;
40 - }
41 -
42 - /* the rest of the line will be useful for multi_ack and multi_ack_detailed */
43 11 2 static int ack_pkt(git_pkt **out, const char *line, size_t len)
44 - {
45 - git_pkt_ack *pkt;
46 -
47 11 2 pkt = git__calloc(1, sizeof(git_pkt_ack));
48 11 3,4 GIT_ERROR_CHECK_ALLOC(pkt);
49 11 5 pkt->type = GIT_PKT_ACK;
50 -
51 11 5,6 if (git__prefixncmp(line, len, "ACK "))
52 2 7 goto out_err;
53 9 8 line += 4;
54 9 8 len -= 4;
55 -
56 9 8-10 if (len < GIT_OID_HEXSZ || git_oid_fromstr(&pkt->oid, line) < 0)
57 - goto out_err;
58 5 11 line += GIT_OID_HEXSZ;
59 5 11 len -= GIT_OID_HEXSZ;
60 -
61 5 11,12 if (len && line[0] == ' ') {
62 4 13 line++;
63 4 13 len--;
64 -
65 4 13,14 if (!git__prefixncmp(line, len, "continue"))
66 1 15 pkt->status = GIT_ACK_CONTINUE;
67 3 16,17 else if (!git__prefixncmp(line, len, "common"))
68 1 18 pkt->status = GIT_ACK_COMMON;
69 2 19,20 else if (!git__prefixncmp(line, len, "ready"))
70 1 21 pkt->status = GIT_ACK_READY;
71 - else
72 1 22 goto out_err;
73 - }
74 -
75 4 23 *out = (git_pkt *) pkt;
76 -
77 4 23 return 0;
78 -
79 - out_err:
80 7 24 git_error_set(GIT_ERROR_NET, "error parsing ACK pkt-line");
81 7 25 git__free(pkt);
82 7 26 return -1;
83 - }
84 -
85 38 2 static int nak_pkt(git_pkt **out)
86 - {
87 - git_pkt *pkt;
88 -
89 38 2 pkt = git__malloc(sizeof(git_pkt));
90 38 3,4 GIT_ERROR_CHECK_ALLOC(pkt);
91 -
92 38 5 pkt->type = GIT_PKT_NAK;
93 38 5 *out = pkt;
94 -
95 38 5 return 0;
96 - }
97 -
98 34 2 static int comment_pkt(git_pkt **out, const char *line, size_t len)
99 - {
100 - git_pkt_comment *pkt;
101 - size_t alloclen;
102 -
103 34 2-8 GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, sizeof(git_pkt_comment), len);
104 34 9-15 GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, alloclen, 1);
105 34 16 pkt = git__malloc(alloclen);
106 34 17,18 GIT_ERROR_CHECK_ALLOC(pkt);
107 -
108 34 19 pkt->type = GIT_PKT_COMMENT;
109 34 19 memcpy(pkt->comment, line, len);
110 34 19 pkt->comment[len] = '\0';
111 -
112 34 19 *out = (git_pkt *) pkt;
113 -
114 34 19 return 0;
115 - }
116 -
117 5 2 static int err_pkt(git_pkt **out, const char *line, size_t len)
118 - {
119 5 2 git_pkt_err *pkt = NULL;
120 - size_t alloclen;
121 -
122 - /* Remove "ERR " from the line */
123 5 2,3 if (git__prefixncmp(line, len, "ERR "))
124 2 4 goto out_err;
125 3 5 line += 4;
126 3 5 len -= 4;
127 -
128 3 5-11 GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, sizeof(git_pkt_progress), len);
129 3 12-18 GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, alloclen, 1);
130 3 19 pkt = git__malloc(alloclen);
131 3 20,21 GIT_ERROR_CHECK_ALLOC(pkt);
132 3 22 pkt->type = GIT_PKT_ERR;
133 3 22 pkt->len = len;
134 -
135 3 22 memcpy(pkt->error, line, len);
136 3 22 pkt->error[len] = '\0';
137 -
138 3 22 *out = (git_pkt *) pkt;
139 -
140 3 22 return 0;
141 -
142 - out_err:
143 2 23 git_error_set(GIT_ERROR_NET, "error parsing ERR pkt-line");
144 2 24 git__free(pkt);
145 2 25 return -1;
146 - }
147 -
148 104 2 static int data_pkt(git_pkt **out, const char *line, size_t len)
149 - {
150 - git_pkt_data *pkt;
151 - size_t alloclen;
152 -
153 104 2 line++;
154 104 2 len--;
155 -
156 104 2-8 GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, sizeof(git_pkt_progress), len);
157 104 9 pkt = git__malloc(alloclen);
158 104 10,11 GIT_ERROR_CHECK_ALLOC(pkt);
159 -
160 104 12 pkt->type = GIT_PKT_DATA;
161 104 12 pkt->len = len;
162 104 12 memcpy(pkt->data, line, len);
163 -
164 104 12 *out = (git_pkt *) pkt;
165 -
166 104 12 return 0;
167 - }
168 -
169 274 2 static int sideband_progress_pkt(git_pkt **out, const char *line, size_t len)
170 - {
171 - git_pkt_progress *pkt;
172 - size_t alloclen;
173 -
174 274 2 line++;
175 274 2 len--;
176 -
177 274 2-8 GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, sizeof(git_pkt_progress), len);
178 274 9 pkt = git__malloc(alloclen);
179 274 10,11 GIT_ERROR_CHECK_ALLOC(pkt);
180 -
181 274 12 pkt->type = GIT_PKT_PROGRESS;
182 274 12 pkt->len = len;
183 274 12 memcpy(pkt->data, line, len);
184 -
185 274 12 *out = (git_pkt *) pkt;
186 -
187 274 12 return 0;
188 - }
189 -
190 3 2 static int sideband_error_pkt(git_pkt **out, const char *line, size_t len)
191 - {
192 - git_pkt_err *pkt;
193 - size_t alloc_len;
194 -
195 3 2 line++;
196 3 2 len--;
197 -
198 3 2-8 GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, sizeof(git_pkt_err), len);
199 3 9-15 GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 1);
200 3 16 pkt = git__malloc(alloc_len);
201 3 17,18 GIT_ERROR_CHECK_ALLOC(pkt);
202 -
203 3 19 pkt->type = GIT_PKT_ERR;
204 3 19 pkt->len = (int)len;
205 3 19 memcpy(pkt->error, line, len);
206 3 19 pkt->error[len] = '\0';
207 -
208 3 19 *out = (git_pkt *)pkt;
209 -
210 3 19 return 0;
211 - }
212 -
213 - /*
214 - * Parse an other-ref line.
215 - */
216 477 2 static int ref_pkt(git_pkt **out, const char *line, size_t len)
217 - {
218 - git_pkt_ref *pkt;
219 - size_t alloclen;
220 -
221 477 2 pkt = git__calloc(1, sizeof(git_pkt_ref));
222 477 3,4 GIT_ERROR_CHECK_ALLOC(pkt);
223 477 5 pkt->type = GIT_PKT_REF;
224 -
225 477 5-7 if (len < GIT_OID_HEXSZ || git_oid_fromstr(&pkt->head.oid, line) < 0)
226 - goto out_err;
227 471 8 line += GIT_OID_HEXSZ;
228 471 8 len -= GIT_OID_HEXSZ;
229 -
230 471 8,9 if (git__prefixncmp(line, len, " "))
231 3 10 goto out_err;
232 468 11 line++;
233 468 11 len--;
234 -
235 468 11 if (!len)
236 ##### 12 goto out_err;
237 -
238 468 13 if (line[len - 1] == '\n')
239 463 14 --len;
240 -
241 468 15-21 GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, len, 1);
242 468 22 pkt->head.name = git__malloc(alloclen);
243 468 23,24 GIT_ERROR_CHECK_ALLOC(pkt->head.name);
244 -
245 468 25 memcpy(pkt->head.name, line, len);
246 468 25 pkt->head.name[len] = '\0';
247 -
248 468 25 if (strlen(pkt->head.name) < len)
249 57 26 pkt->capabilities = strchr(pkt->head.name, '\0') + 1;
250 -
251 468 27 *out = (git_pkt *)pkt;
252 468 27 return 0;
253 -
254 - out_err:
255 9 28 git_error_set(GIT_ERROR_NET, "error parsing REF pkt-line");
256 9 29 if (pkt)
257 9 30 git__free(pkt->head.name);
258 9 31 git__free(pkt);
259 9 32 return -1;
260 - }
261 -
262 7 2 static int ok_pkt(git_pkt **out, const char *line, size_t len)
263 - {
264 - git_pkt_ok *pkt;
265 - size_t alloc_len;
266 -
267 7 2 pkt = git__malloc(sizeof(*pkt));
268 7 3,4 GIT_ERROR_CHECK_ALLOC(pkt);
269 7 5 pkt->type = GIT_PKT_OK;
270 -
271 7 5,6 if (git__prefixncmp(line, len, "ok "))
272 1 7 goto out_err;
273 6 8 line += 3;
274 6 8 len -= 3;
275 -
276 6 8,9 if (len && line[len - 1] == '\n')
277 3 10 --len;
278 -
279 6 11-17 GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, len, 1);
280 6 18 pkt->ref = git__malloc(alloc_len);
281 6 19,20 GIT_ERROR_CHECK_ALLOC(pkt->ref);
282 -
283 6 21 memcpy(pkt->ref, line, len);
284 6 21 pkt->ref[len] = '\0';
285 -
286 6 21 *out = (git_pkt *)pkt;
287 6 21 return 0;
288 -
289 - out_err:
290 1 22 git_error_set(GIT_ERROR_NET, "error parsing OK pkt-line");
291 1 23 git__free(pkt);
292 1 24 return -1;
293 - }
294 -
295 7 2 static int ng_pkt(git_pkt **out, const char *line, size_t len)
296 - {
297 - git_pkt_ng *pkt;
298 - const char *ptr, *eol;
299 - size_t alloclen;
300 -
301 7 2 pkt = git__malloc(sizeof(*pkt));
302 7 3,4 GIT_ERROR_CHECK_ALLOC(pkt);
303 -
304 7 5 pkt->ref = NULL;
305 7 5 pkt->type = GIT_PKT_NG;
306 -
307 7 5 eol = line + len;
308 -
309 7 5,6 if (git__prefixncmp(line, len, "ng "))
310 1 7 goto out_err;
311 6 8 line += 3;
312 -
313 6 8 if (!(ptr = memchr(line, ' ', eol - line)))
314 3 9 goto out_err;
315 3 10 len = ptr - line;
316 -
317 3 10-16 GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, len, 1);
318 3 17 pkt->ref = git__malloc(alloclen);
319 3 18,19 GIT_ERROR_CHECK_ALLOC(pkt->ref);
320 -
321 3 20 memcpy(pkt->ref, line, len);
322 3 20 pkt->ref[len] = '\0';
323 -
324 3 20 line = ptr + 1;
325 3 20 if (line >= eol)
326 ##### 21 goto out_err;
327 -
328 3 22 if (!(ptr = memchr(line, '\n', eol - line)))
329 ##### 23 goto out_err;
330 3 24 len = ptr - line;
331 -
332 3 24-30 GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, len, 1);
333 3 31 pkt->msg = git__malloc(alloclen);
334 3 32,33 GIT_ERROR_CHECK_ALLOC(pkt->msg);
335 -
336 3 34 memcpy(pkt->msg, line, len);
337 3 34 pkt->msg[len] = '\0';
338 -
339 3 34 *out = (git_pkt *)pkt;
340 3 34 return 0;
341 -
342 - out_err:
343 4 35 git_error_set(GIT_ERROR_NET, "invalid packet line");
344 4 36 git__free(pkt->ref);
345 4 37 git__free(pkt);
346 4 38 return -1;
347 - }
348 -
349 6 2 static int unpack_pkt(git_pkt **out, const char *line, size_t len)
350 - {
351 - git_pkt_unpack *pkt;
352 -
353 6 2 pkt = git__malloc(sizeof(*pkt));
354 6 3,4 GIT_ERROR_CHECK_ALLOC(pkt);
355 6 5 pkt->type = GIT_PKT_UNPACK;
356 -
357 6 5,6 if (!git__prefixncmp(line, len, "unpack ok"))
358 2 7 pkt->unpack_ok = 1;
359 - else
360 4 8 pkt->unpack_ok = 0;
361 -
362 6 9 *out = (git_pkt *)pkt;
363 6 9 return 0;
364 - }
365 -
366 1464 2 static int parse_len(size_t *out, const char *line, size_t linelen)
367 - {
368 - char num[PKT_LEN_SIZE + 1];
369 - int i, k, error;
370 - int32_t len;
371 - const char *num_end;
372 -
373 - /* Not even enough for the length */
374 1464 2 if (linelen < PKT_LEN_SIZE)
375 3 3 return GIT_EBUFS;
376 -
377 1461 4 memcpy(num, line, PKT_LEN_SIZE);
378 1461 4 num[PKT_LEN_SIZE] = '\0';
379 -
380 7298 4,15,16 for (i = 0; i < PKT_LEN_SIZE; ++i) {
381 5841 5,6 if (!isxdigit(num[i])) {
382 - /* Make sure there are no special characters before passing to error message */
383 20 7,11,12 for (k = 0; k < PKT_LEN_SIZE; ++k) {
384 16 8,9 if(!isprint(num[k])) {
385 ##### 10 num[k] = '.';
386 - }
387 - }
388 -
389 4 13 git_error_set(GIT_ERROR_NET, "invalid hex digit in length: '%s'", num);
390 4 14 return -1;
391 - }
392 - }
393 -
394 1457 17,18 if ((error = git__strntol32(&len, num, PKT_LEN_SIZE, &num_end, 16)) < 0)
395 ##### 19 return error;
396 -
397 1457 20 if (len < 0)
398 ##### 21 return -1;
399 -
400 1457 22 *out = (size_t) len;
401 1457 22 return 0;
402 - }
403 -
404 - /*
405 - * As per the documentation, the syntax is:
406 - *
407 - * pkt-line = data-pkt / flush-pkt
408 - * data-pkt = pkt-len pkt-payload
409 - * pkt-len = 4*(HEXDIG)
410 - * pkt-payload = (pkt-len -4)*(OCTET)
411 - * flush-pkt = "0000"
412 - *
413 - * Which means that the first four bytes are the length of the line,
414 - * in ASCII hexadecimal (including itself)
415 - */
416 -
417 1464 2 int git_pkt_parse_line(
418 - git_pkt **pkt, const char **endptr, const char *line, size_t linelen)
419 - {
420 - int error;
421 - size_t len;
422 -
423 1464 2,3 if ((error = parse_len(&len, line, linelen)) < 0) {
424 - /*
425 - * If we fail to parse the length, it might be
426 - * because the server is trying to send us the
427 - * packfile already or because we do not yet have
428 - * enough data.
429 - */
430 7 4 if (error == GIT_EBUFS)
431 - ;
432 4 5,6 else if (!git__prefixncmp(line, linelen, "PACK"))
433 ##### 7 git_error_set(GIT_ERROR_NET, "unexpected pack file");
434 - else
435 4 8 git_error_set(GIT_ERROR_NET, "bad packet length");
436 7 9 return error;
437 - }
438 -
439 - /*
440 - * Make sure there is enough in the buffer to satisfy
441 - * this line.
442 - */
443 1457 10 if (linelen < len)
444 364 11 return GIT_EBUFS;
445 -
446 - /*
447 - * The length has to be exactly 0 in case of a flush
448 - * packet or greater than PKT_LEN_SIZE, as the decoded
449 - * length includes its own encoded length of four bytes.
450 - */
451 1093 12,13 if (len != 0 && len < PKT_LEN_SIZE)
452 5 14 return GIT_ERROR;
453 -
454 1088 15 line += PKT_LEN_SIZE;
455 - /*
456 - * The Git protocol does not specify empty lines as part
457 - * of the protocol. Not knowing what to do with an empty
458 - * line, we should return an error upon hitting one.
459 - */
460 1088 15 if (len == PKT_LEN_SIZE) {
461 ##### 16 git_error_set_str(GIT_ERROR_NET, "Invalid empty packet");
462 ##### 17 return GIT_ERROR;
463 - }
464 -
465 1088 18 if (len == 0) { /* Flush pkt */
466 122 19 *endptr = line;
467 122 19 return flush_pkt(pkt);
468 - }
469 -
470 966 20 len -= PKT_LEN_SIZE; /* the encoded length includes its own size */
471 -
472 966 20 if (*line == GIT_SIDE_BAND_DATA)
473 104 21 error = data_pkt(pkt, line, len);
474 862 22 else if (*line == GIT_SIDE_BAND_PROGRESS)
475 274 23 error = sideband_progress_pkt(pkt, line, len);
476 588 24 else if (*line == GIT_SIDE_BAND_ERROR)
477 3 25 error = sideband_error_pkt(pkt, line, len);
478 585 26,27 else if (!git__prefixncmp(line, len, "ACK"))
479 11 28 error = ack_pkt(pkt, line, len);
480 574 29,30 else if (!git__prefixncmp(line, len, "NAK"))
481 38 31 error = nak_pkt(pkt);
482 536 32,33 else if (!git__prefixncmp(line, len, "ERR"))
483 5 34 error = err_pkt(pkt, line, len);
484 531 35 else if (*line == '#')
485 34 36 error = comment_pkt(pkt, line, len);
486 497 37,38 else if (!git__prefixncmp(line, len, "ok"))
487 7 39 error = ok_pkt(pkt, line, len);
488 490 40,41 else if (!git__prefixncmp(line, len, "ng"))
489 7 42 error = ng_pkt(pkt, line, len);
490 483 43,44 else if (!git__prefixncmp(line, len, "unpack"))
491 6 45 error = unpack_pkt(pkt, line, len);
492 - else
493 477 46 error = ref_pkt(pkt, line, len);
494 -
495 966 47 *endptr = line + len;
496 -
497 966 47 return error;
498 - }
499 -
500 1035 2 void git_pkt_free(git_pkt *pkt)
501 - {
502 1035 2 if (pkt == NULL) {
503 1035 3,13 return;
504 - }
505 999 4 if (pkt->type == GIT_PKT_REF) {
506 468 5 git_pkt_ref *p = (git_pkt_ref *) pkt;
507 468 5 git__free(p->head.name);
508 468 6 git__free(p->head.symref_target);
509 - }
510 -
511 999 7 if (pkt->type == GIT_PKT_OK) {
512 6 8 git_pkt_ok *p = (git_pkt_ok *) pkt;
513 6 8 git__free(p->ref);
514 - }
515 -
516 999 9 if (pkt->type == GIT_PKT_NG) {
517 3 10 git_pkt_ng *p = (git_pkt_ng *) pkt;
518 3 10 git__free(p->ref);
519 3 11 git__free(p->msg);
520 - }
521 -
522 999 12 git__free(pkt);
523 - }
524 -
525 36 2 int git_pkt_buffer_flush(git_buf *buf)
526 - {
527 36 2 return git_buf_put(buf, pkt_flush_str, strlen(pkt_flush_str));
528 - }
529 -
530 36 2 static int buffer_want_with_caps(const git_remote_head *head, transport_smart_caps *caps, git_buf *buf)
531 - {
532 36 2 git_buf str = GIT_BUF_INIT;
533 36 2 char oid[GIT_OID_HEXSZ +1] = {0};
534 - size_t len;
535 -
536 - /* Prefer multi_ack_detailed */
537 36 2 if (caps->multi_ack_detailed)
538 36 3 git_buf_puts(&str, GIT_CAP_MULTI_ACK_DETAILED " ");
539 ##### 4 else if (caps->multi_ack)
540 ##### 5 git_buf_puts(&str, GIT_CAP_MULTI_ACK " ");
541 -
542 - /* Prefer side-band-64k if the server supports both */
543 36 6 if (caps->side_band_64k)
544 36 7 git_buf_printf(&str, "%s ", GIT_CAP_SIDE_BAND_64K);
545 ##### 8 else if (caps->side_band)
546 ##### 9 git_buf_printf(&str, "%s ", GIT_CAP_SIDE_BAND);
547 -
548 36 10 if (caps->include_tag)
549 34 11 git_buf_puts(&str, GIT_CAP_INCLUDE_TAG " ");
550 -
551 36 12 if (caps->thin_pack)
552 36 13 git_buf_puts(&str, GIT_CAP_THIN_PACK " ");
553 -
554 36 14 if (caps->ofs_delta)
555 34 15 git_buf_puts(&str, GIT_CAP_OFS_DELTA " ");
556 -
557 36 16,17 if (git_buf_oom(&str))
558 ##### 18 return -1;
559 -
560 36 20 len = strlen("XXXXwant ") + GIT_OID_HEXSZ + 1 /* NUL */ +
561 36 19 git_buf_len(&str) + 1 /* LF */;
562 -
563 36 20 if (len > 0xffff) {
564 ##### 21 git_error_set(GIT_ERROR_NET,
565 - "tried to produce packet with invalid length %" PRIuZ, len);
566 ##### 22 return -1;
567 - }
568 -
569 36 23 git_buf_grow_by(buf, len);
570 36 24 git_oid_fmt(oid, &head->oid);
571 36 25,26 git_buf_printf(buf,
572 - "%04xwant %s %s\n", (unsigned int)len, oid, git_buf_cstr(&str));
573 36 27 git_buf_dispose(&str);
574 -
575 36 28-31 GIT_ERROR_CHECK_ALLOC_BUF(buf);
576 -
577 36 32 return 0;
578 - }
579 -
580 - /*
581 - * All "want" packets have the same length and format, so what we do
582 - * is overwrite the OID each time.
583 - */
584 -
585 36 2 int git_pkt_buffer_wants(
586 - const git_remote_head * const *refs,
587 - size_t count,
588 - transport_smart_caps *caps,
589 - git_buf *buf)
590 - {
591 36 2 size_t i = 0;
592 - const git_remote_head *head;
593 -
594 36 2 if (caps->common) {
595 36 3,6,7 for (; i < count; ++i) {
596 36 4 head = refs[i];
597 36 4 if (!head->local)
598 36 5 break;
599 - }
600 -
601 36 8,9 if (buffer_want_with_caps(refs[i], caps, buf) < 0)
602 ##### 10 return -1;
603 -
604 36 11 i++;
605 - }
606 -
607 190 12,23,24 for (; i < count; ++i) {
608 - char oid[GIT_OID_HEXSZ];
609 -
610 154 13 head = refs[i];
611 154 13 if (head->local)
612 ##### 14 continue;
613 -
614 154 15 git_oid_fmt(oid, &head->oid);
615 154 16 git_buf_put(buf, pkt_want_prefix, strlen(pkt_want_prefix));
616 154 17 git_buf_put(buf, oid, GIT_OID_HEXSZ);
617 154 18 git_buf_putc(buf, '\n');
618 154 19,20 if (git_buf_oom(buf))
619 154 21,22 return -1;
620 - }
621 -
622 36 25 return git_pkt_buffer_flush(buf);
623 - }
624 -
625 ##### 2 int git_pkt_buffer_have(git_oid *oid, git_buf *buf)
626 - {
627 - char oidhex[GIT_OID_HEXSZ + 1];
628 -
629 ##### 2 memset(oidhex, 0x0, sizeof(oidhex));
630 ##### 2 git_oid_fmt(oidhex, oid);
631 ##### 3 return git_buf_printf(buf, "%s%s\n", pkt_have_prefix, oidhex);
632 - }
633 -
634 36 2 int git_pkt_buffer_done(git_buf *buf)
635 - {
636 36 2 return git_buf_puts(buf, pkt_done_str);
637 - }