| /* |
| * Copyright (C) 2009-2012 the libgit2 contributors |
| * |
| * This file is part of libgit2, distributed under the GNU GPL v2 with |
| * a Linking Exception. For full terms see the included COPYING file. |
| */ |
| #include "common.h" |
| #include "protocol.h" |
| #include "pkt.h" |
| #include "buffer.h" |
| |
| int git_protocol_store_refs(git_transport *t, int flushes) |
| { |
| gitno_buffer *buf = &t->buffer; |
| git_vector *refs = &t->refs; |
| int error, flush = 0, recvd; |
| const char *line_end; |
| git_pkt *pkt; |
| |
| do { |
| if (buf->offset > 0) |
| error = git_pkt_parse_line(&pkt, buf->data, &line_end, buf->offset); |
| else |
| error = GIT_EBUFS; |
| |
| if (error < 0 && error != GIT_EBUFS) |
| return -1; |
| |
| if (error == GIT_EBUFS) { |
| if ((recvd = gitno_recv(buf)) < 0) |
| return -1; |
| |
| if (recvd == 0 && !flush) { |
| giterr_set(GITERR_NET, "Early EOF"); |
| return -1; |
| } |
| |
| continue; |
| } |
| |
| gitno_consume(buf, line_end); |
| if (pkt->type == GIT_PKT_ERR) { |
| giterr_set(GITERR_NET, "Remote error: %s", ((git_pkt_err *)pkt)->error); |
| git__free(pkt); |
| return -1; |
| } |
| |
| if (pkt->type != GIT_PKT_FLUSH && git_vector_insert(refs, pkt) < 0) |
| return -1; |
| |
| if (pkt->type == GIT_PKT_FLUSH) { |
| flush++; |
| git_pkt_free(pkt); |
| } |
| } while (flush < flushes); |
| |
| return flush; |
| } |
| |
| int git_protocol_detect_caps(git_pkt_ref *pkt, git_transport_caps *caps) |
| { |
| const char *ptr; |
| |
| /* No refs or capabilites, odd but not a problem */ |
| if (pkt == NULL || pkt->capabilities == NULL) |
| return 0; |
| |
| ptr = pkt->capabilities; |
| while (ptr != NULL && *ptr != '\0') { |
| if (*ptr == ' ') |
| ptr++; |
| |
| if(!git__prefixcmp(ptr, GIT_CAP_OFS_DELTA)) { |
| caps->common = caps->ofs_delta = 1; |
| ptr += strlen(GIT_CAP_OFS_DELTA); |
| continue; |
| } |
| |
| if(!git__prefixcmp(ptr, GIT_CAP_MULTI_ACK)) { |
| caps->common = caps->multi_ack = 1; |
| ptr += strlen(GIT_CAP_MULTI_ACK); |
| continue; |
| } |
| |
| if(!git__prefixcmp(ptr, GIT_CAP_INCLUDE_TAG)) { |
| caps->common = caps->include_tag = 1; |
| ptr += strlen(GIT_CAP_INCLUDE_TAG); |
| continue; |
| } |
| |
| /* Keep side-band check after side-band-64k */ |
| if(!git__prefixcmp(ptr, GIT_CAP_SIDE_BAND_64K)) { |
| caps->common = caps->side_band_64k = 1; |
| ptr += strlen(GIT_CAP_SIDE_BAND_64K); |
| continue; |
| } |
| |
| if(!git__prefixcmp(ptr, GIT_CAP_SIDE_BAND)) { |
| caps->common = caps->side_band = 1; |
| ptr += strlen(GIT_CAP_SIDE_BAND); |
| continue; |
| } |
| |
| if(!git__prefixcmp(ptr, GIT_CAP_DELETE_REFS)) { |
| caps->common = caps->delete_refs = 1; |
| ptr += strlen(GIT_CAP_DELETE_REFS); |
| continue; |
| } |
| |
| /* We don't know this capability, so skip it */ |
| ptr = strchr(ptr, ' '); |
| } |
| |
| return 0; |
| } |