transport-helper: implement object-format extensions

Implement the object-format extensions that let us determine the hash
algorithm in use when pushing or pulling data.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
brian m. carlson 2020-05-25 19:59:03 +00:00 committed by Junio C Hamano
parent 452e35684f
commit 8b85ee4f47

View file

@ -32,7 +32,8 @@ struct helper_data {
signed_tags : 1, signed_tags : 1,
check_connectivity : 1, check_connectivity : 1,
no_disconnect_req : 1, no_disconnect_req : 1,
no_private_update : 1; no_private_update : 1,
object_format : 1;
/* /*
* As an optimization, the transport code may invoke fetch before * As an optimization, the transport code may invoke fetch before
@ -207,6 +208,8 @@ static struct child_process *get_helper(struct transport *transport)
data->import_marks = xstrdup(arg); data->import_marks = xstrdup(arg);
} else if (starts_with(capname, "no-private-update")) { } else if (starts_with(capname, "no-private-update")) {
data->no_private_update = 1; data->no_private_update = 1;
} else if (starts_with(capname, "object-format")) {
data->object_format = 1;
} else if (mandatory) { } else if (mandatory) {
die(_("unknown mandatory capability %s; this remote " die(_("unknown mandatory capability %s; this remote "
"helper probably needs newer version of Git"), "helper probably needs newer version of Git"),
@ -1103,6 +1106,12 @@ static struct ref *get_refs_list_using_list(struct transport *transport,
data->get_refs_list_called = 1; data->get_refs_list_called = 1;
helper = get_helper(transport); helper = get_helper(transport);
if (data->object_format) {
write_str_in_full(helper->in, "option object-format\n");
if (recvline(data, &buf) || strcmp(buf.buf, "ok"))
exit(128);
}
if (data->push && for_push) if (data->push && for_push)
write_str_in_full(helper->in, "list for-push\n"); write_str_in_full(helper->in, "list for-push\n");
else else
@ -1115,6 +1124,17 @@ static struct ref *get_refs_list_using_list(struct transport *transport,
if (!*buf.buf) if (!*buf.buf)
break; break;
else if (buf.buf[0] == ':') {
const char *value;
if (skip_prefix(buf.buf, ":object-format ", &value)) {
int algo = hash_algo_by_name(value);
if (algo == GIT_HASH_UNKNOWN)
die(_("unsupported object format '%s'"),
value);
transport->hash_algo = &hash_algos[algo];
}
continue;
}
eov = strchr(buf.buf, ' '); eov = strchr(buf.buf, ' ');
if (!eov) if (!eov)
@ -1127,7 +1147,7 @@ static struct ref *get_refs_list_using_list(struct transport *transport,
if (buf.buf[0] == '@') if (buf.buf[0] == '@')
(*tail)->symref = xstrdup(buf.buf + 1); (*tail)->symref = xstrdup(buf.buf + 1);
else if (buf.buf[0] != '?') else if (buf.buf[0] != '?')
get_oid_hex(buf.buf, &(*tail)->old_oid); get_oid_hex_algop(buf.buf, &(*tail)->old_oid, transport->hash_algo);
if (eon) { if (eon) {
if (has_attribute(eon + 1, "unchanged")) { if (has_attribute(eon + 1, "unchanged")) {
(*tail)->status |= REF_STATUS_UPTODATE; (*tail)->status |= REF_STATUS_UPTODATE;