|
| 1 | +#include "git-compat-util.h" |
| 2 | +#include "gettext.h" |
| 3 | +#include "hex.h" |
| 4 | +#include "pkt-line.h" |
| 5 | +#include "connect.h" |
| 6 | +#include "oid-array.h" |
| 7 | +#include "object-store-ll.h" |
| 8 | +#include "fetch-object-info.h" |
| 9 | +#include "string-list.h" |
| 10 | + |
| 11 | +/* Sends git-cat-file object-info command and its arguments into the request buffer. */ |
| 12 | +static void send_object_info_request(const int fd_out, struct object_info_args *args) |
| 13 | +{ |
| 14 | + struct strbuf req_buf = STRBUF_INIT; |
| 15 | + |
| 16 | + write_command_and_capabilities(&req_buf, "object-info", args->server_options); |
| 17 | + |
| 18 | + if (unsorted_string_list_has_string(args->object_info_options, "size")) |
| 19 | + packet_buf_write(&req_buf, "size"); |
| 20 | + |
| 21 | + if (args->oids) |
| 22 | + for (size_t i = 0; i < args->oids->nr; i++) |
| 23 | + packet_buf_write(&req_buf, "oid %s", oid_to_hex(&args->oids->oid[i])); |
| 24 | + |
| 25 | + packet_buf_flush(&req_buf); |
| 26 | + if (write_in_full(fd_out, req_buf.buf, req_buf.len) < 0) |
| 27 | + die_errno(_("unable to write request to remote")); |
| 28 | + |
| 29 | + strbuf_release(&req_buf); |
| 30 | +} |
| 31 | + |
| 32 | +int fetch_object_info(const enum protocol_version version, struct object_info_args *args, |
| 33 | + struct packet_reader *reader, struct object_info *object_info_data, |
| 34 | + const int stateless_rpc, const int fd_out) |
| 35 | +{ |
| 36 | + int size_index = -1; |
| 37 | + |
| 38 | + switch (version) { |
| 39 | + case protocol_v2: |
| 40 | + if (!server_supports_v2("object-info")) |
| 41 | + die(_("object-info capability is not enabled on the server")); |
| 42 | + send_object_info_request(fd_out, args); |
| 43 | + break; |
| 44 | + case protocol_v1: |
| 45 | + case protocol_v0: |
| 46 | + die(_("unsupported protocol version. expected v2")); |
| 47 | + case protocol_unknown_version: |
| 48 | + BUG("unknown protocol version"); |
| 49 | + } |
| 50 | + |
| 51 | + for (size_t i = 0; i < args->object_info_options->nr; i++) { |
| 52 | + if (packet_reader_read(reader) != PACKET_READ_NORMAL) { |
| 53 | + check_stateless_delimiter(stateless_rpc, reader, "stateless delimiter expected"); |
| 54 | + return -1; |
| 55 | + } |
| 56 | + if (!string_list_has_string(args->object_info_options, reader->line)) |
| 57 | + return -1; |
| 58 | + if (!strcmp(reader->line, "size")) { |
| 59 | + size_index = i; |
| 60 | + for (size_t j = 0; j < args->oids->nr; j++) |
| 61 | + object_info_data[j].sizep = xcalloc(1, sizeof(*object_info_data[j].sizep)); |
| 62 | + } |
| 63 | + } |
| 64 | + |
| 65 | + for (size_t i = 0; packet_reader_read(reader) == PACKET_READ_NORMAL && i < args->oids->nr; i++){ |
| 66 | + struct string_list object_info_values = STRING_LIST_INIT_DUP; |
| 67 | + |
| 68 | + string_list_split(&object_info_values, reader->line, ' ', -1); |
| 69 | + if (0 <= size_index) { |
| 70 | + if (!strcmp(object_info_values.items[1 + size_index].string, "")) |
| 71 | + die("object-info: not our ref %s", |
| 72 | + object_info_values.items[0].string); |
| 73 | + |
| 74 | + if (strtoul_ul(object_info_values.items[1 + size_index].string, 10, object_info_data[i].sizep)) |
| 75 | + die("object-info: ref %s has invalid size %s", |
| 76 | + object_info_values.items[0].string, |
| 77 | + object_info_values.items[1 + size_index].string); |
| 78 | + } |
| 79 | + |
| 80 | + string_list_clear(&object_info_values, 0); |
| 81 | + } |
| 82 | + check_stateless_delimiter(stateless_rpc, reader, "stateless delimiter expected"); |
| 83 | + |
| 84 | + return 0; |
| 85 | +} |
0 commit comments