diff options
author | Edward Thomson <ethomson@edwardthomson.com> | 2023-05-09 20:38:04 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-09 20:38:04 +0100 |
commit | 2bbcdee6b666f34e83d1cf9ca9badc66258202d6 (patch) | |
tree | 26a9d405c75564de8e1a3dc8ac4dc1c8ec7421f7 /src/libgit2/transports/smart_pkt.c | |
parent | 251408cfd4ff8112efaa5c82ec81c9574c4bf022 (diff) | |
parent | 437c5f5a0b6ae6068168081ac6422dba44cff31d (diff) | |
download | libgit2-2bbcdee6b666f34e83d1cf9ca9badc66258202d6.tar.gz |
Merge pull request #6557 from libgit2/ethomson/shallow
Shallow (#6396) with some fixes from review
Diffstat (limited to 'src/libgit2/transports/smart_pkt.c')
-rw-r--r-- | src/libgit2/transports/smart_pkt.c | 149 |
1 files changed, 135 insertions, 14 deletions
diff --git a/src/libgit2/transports/smart_pkt.c b/src/libgit2/transports/smart_pkt.c index 5fce42175..9127ad5fe 100644 --- a/src/libgit2/transports/smart_pkt.c +++ b/src/libgit2/transports/smart_pkt.c @@ -44,9 +44,16 @@ static int flush_pkt(git_pkt **out) } /* the rest of the line will be useful for multi_ack and multi_ack_detailed */ -static int ack_pkt(git_pkt **out, const char *line, size_t len) +static int ack_pkt( + git_pkt **out, + const char *line, + size_t len, + git_pkt_parse_data *data) { git_pkt_ack *pkt; + size_t oid_hexsize = git_oid_hexsize(data->oid_type); + + GIT_ASSERT(data && data->oid_type); pkt = git__calloc(1, sizeof(git_pkt_ack)); GIT_ERROR_CHECK_ALLOC(pkt); @@ -57,11 +64,11 @@ static int ack_pkt(git_pkt **out, const char *line, size_t len) line += 4; len -= 4; - if (len < GIT_OID_SHA1_HEXSIZE || - git_oid__fromstr(&pkt->oid, line, GIT_OID_SHA1) < 0) + if (len < oid_hexsize || + git_oid__fromstr(&pkt->oid, line, data->oid_type) < 0) goto out_err; - line += GIT_OID_SHA1_HEXSIZE; - len -= GIT_OID_SHA1_HEXSIZE; + line += oid_hexsize; + len -= oid_hexsize; if (len && line[0] == ' ') { line++; @@ -436,6 +443,84 @@ static int unpack_pkt(git_pkt **out, const char *line, size_t len) return 0; } +static int shallow_pkt( + git_pkt **out, + const char *line, + size_t len, + git_pkt_parse_data *data) +{ + git_pkt_shallow *pkt; + size_t oid_hexsize = git_oid_hexsize(data->oid_type); + + GIT_ASSERT(data && data->oid_type); + + pkt = git__calloc(1, sizeof(git_pkt_shallow)); + GIT_ERROR_CHECK_ALLOC(pkt); + + pkt->type = GIT_PKT_SHALLOW; + + if (git__prefixncmp(line, len, "shallow ")) + goto out_err; + + line += 8; + len -= 8; + + if (len != oid_hexsize) + goto out_err; + + git_oid__fromstr(&pkt->oid, line, data->oid_type); + line += oid_hexsize + 1; + len -= oid_hexsize + 1; + + *out = (git_pkt *)pkt; + + return 0; + +out_err: + git_error_set(GIT_ERROR_NET, "invalid packet line"); + git__free(pkt); + return -1; +} + +static int unshallow_pkt( + git_pkt **out, + const char *line, + size_t len, + git_pkt_parse_data *data) +{ + git_pkt_shallow *pkt; + size_t oid_hexsize = git_oid_hexsize(data->oid_type); + + GIT_ASSERT(data && data->oid_type); + + pkt = git__calloc(1, sizeof(git_pkt_shallow)); + GIT_ERROR_CHECK_ALLOC(pkt); + + pkt->type = GIT_PKT_UNSHALLOW; + + if (git__prefixncmp(line, len, "unshallow ")) + goto out_err; + + line += 10; + len -= 10; + + if (len != oid_hexsize) + goto out_err; + + git_oid__fromstr(&pkt->oid, line, data->oid_type); + line += oid_hexsize + 1; + len -= oid_hexsize + 1; + + *out = (git_pkt *) pkt; + + return 0; + +out_err: + git_error_set(GIT_ERROR_NET, "invalid packet line"); + git__free(pkt); + return -1; +} + static int parse_len(size_t *out, const char *line, size_t linelen) { char num[PKT_LEN_SIZE + 1]; @@ -553,7 +638,7 @@ int git_pkt_parse_line( else if (*line == GIT_SIDE_BAND_ERROR) error = sideband_error_pkt(pkt, line, len); else if (!git__prefixncmp(line, len, "ACK")) - error = ack_pkt(pkt, line, len); + error = ack_pkt(pkt, line, len, data); else if (!git__prefixncmp(line, len, "NAK")) error = nak_pkt(pkt); else if (!git__prefixncmp(line, len, "ERR")) @@ -566,6 +651,10 @@ int git_pkt_parse_line( error = ng_pkt(pkt, line, len); else if (!git__prefixncmp(line, len, "unpack")) error = unpack_pkt(pkt, line, len); + else if (!git__prefixcmp(line, "shallow")) + error = shallow_pkt(pkt, line, len, data); + else if (!git__prefixcmp(line, "unshallow")) + error = unshallow_pkt(pkt, line, len, data); else error = ref_pkt(pkt, line, len, data); @@ -638,6 +727,9 @@ static int buffer_want_with_caps( if (caps->ofs_delta) git_str_puts(&str, GIT_CAP_OFS_DELTA " "); + if (caps->shallow) + git_str_puts(&str, GIT_CAP_SHALLOW " "); + if (git_str_oom(&str)) return -1; @@ -668,8 +760,7 @@ static int buffer_want_with_caps( */ int git_pkt_buffer_wants( - const git_remote_head * const *refs, - size_t count, + const git_fetch_negotiation *wants, transport_smart_caps *caps, git_str *buf) { @@ -679,7 +770,7 @@ int git_pkt_buffer_wants( size_t oid_hexsize, want_len, i = 0; #ifdef GIT_EXPERIMENTAL_SHA256 - oid_type = count > 0 ? refs[0]->oid.type : GIT_OID_SHA1; + oid_type = wants->refs_len > 0 ? wants->refs[0]->oid.type : GIT_OID_SHA1; #else oid_type = GIT_OID_SHA1; #endif @@ -690,20 +781,20 @@ int git_pkt_buffer_wants( oid_hexsize + 1 /* LF */; if (caps->common) { - for (; i < count; ++i) { - head = refs[i]; + for (; i < wants->refs_len; ++i) { + head = wants->refs[i]; if (!head->local) break; } - if (buffer_want_with_caps(refs[i], caps, oid_type, buf) < 0) + if (buffer_want_with_caps(wants->refs[i], caps, oid_type, buf) < 0) return -1; i++; } - for (; i < count; ++i) { - head = refs[i]; + for (; i < wants->refs_len; ++i) { + head = wants->refs[i]; if (head->local) continue; @@ -718,6 +809,36 @@ int git_pkt_buffer_wants( return -1; } + /* Tell the server about our shallow objects */ + for (i = 0; i < wants->shallow_roots_len; i++) { + char oid[GIT_OID_MAX_HEXSIZE + 1]; + git_str shallow_buf = GIT_STR_INIT; + + git_oid_tostr(oid, GIT_OID_MAX_HEXSIZE + 1, &wants->shallow_roots[i]); + git_str_puts(&shallow_buf, "shallow "); + git_str_puts(&shallow_buf, oid); + git_str_putc(&shallow_buf, '\n'); + + git_str_printf(buf, "%04x%s", (unsigned int)git_str_len(&shallow_buf) + 4, git_str_cstr(&shallow_buf)); + + git_str_dispose(&shallow_buf); + + if (git_str_oom(buf)) + return -1; + } + + if (wants->depth > 0) { + git_str deepen_buf = GIT_STR_INIT; + + git_str_printf(&deepen_buf, "deepen %d\n", wants->depth); + git_str_printf(buf,"%04x%s", (unsigned int)git_str_len(&deepen_buf) + 4, git_str_cstr(&deepen_buf)); + + git_str_dispose(&deepen_buf); + + if (git_str_oom(buf)) + return -1; + } + return git_pkt_buffer_flush(buf); } |