bundle: detect hash algorithm when reading refs
Much like with the dumb HTTP transport, there isn't a way to explicitly specify the hash algorithm when dealing with a bundle, so detect the algorithm based on the length of the object IDs in the prerequisites and ref advertisements. Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:

committed by
Junio C Hamano

parent
371c4079f4
commit
6161ce7bbe
22
bundle.c
22
bundle.c
@ -23,6 +23,17 @@ static void add_to_ref_list(const struct object_id *oid, const char *name,
|
|||||||
list->nr++;
|
list->nr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct git_hash_algo *detect_hash_algo(struct strbuf *buf)
|
||||||
|
{
|
||||||
|
size_t len = strcspn(buf->buf, " \n");
|
||||||
|
int algo;
|
||||||
|
|
||||||
|
algo = hash_algo_by_length(len / 2);
|
||||||
|
if (algo == GIT_HASH_UNKNOWN)
|
||||||
|
return NULL;
|
||||||
|
return &hash_algos[algo];
|
||||||
|
}
|
||||||
|
|
||||||
static int parse_bundle_header(int fd, struct bundle_header *header,
|
static int parse_bundle_header(int fd, struct bundle_header *header,
|
||||||
const char *report_path)
|
const char *report_path)
|
||||||
{
|
{
|
||||||
@ -52,12 +63,21 @@ static int parse_bundle_header(int fd, struct bundle_header *header,
|
|||||||
}
|
}
|
||||||
strbuf_rtrim(&buf);
|
strbuf_rtrim(&buf);
|
||||||
|
|
||||||
|
if (!header->hash_algo) {
|
||||||
|
header->hash_algo = detect_hash_algo(&buf);
|
||||||
|
if (!header->hash_algo) {
|
||||||
|
error(_("unknown hash algorithm length"));
|
||||||
|
status = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Tip lines have object name, SP, and refname.
|
* Tip lines have object name, SP, and refname.
|
||||||
* Prerequisites have object name that is optionally
|
* Prerequisites have object name that is optionally
|
||||||
* followed by SP and subject line.
|
* followed by SP and subject line.
|
||||||
*/
|
*/
|
||||||
if (parse_oid_hex(buf.buf, &oid, &p) ||
|
if (parse_oid_hex_algop(buf.buf, &oid, &p, header->hash_algo) ||
|
||||||
(*p && !isspace(*p)) ||
|
(*p && !isspace(*p)) ||
|
||||||
(!is_prereq && !*p)) {
|
(!is_prereq && !*p)) {
|
||||||
if (report_path)
|
if (report_path)
|
||||||
|
1
bundle.h
1
bundle.h
@ -15,6 +15,7 @@ struct ref_list {
|
|||||||
struct bundle_header {
|
struct bundle_header {
|
||||||
struct ref_list prerequisites;
|
struct ref_list prerequisites;
|
||||||
struct ref_list references;
|
struct ref_list references;
|
||||||
|
const struct git_hash_algo *hash_algo;
|
||||||
};
|
};
|
||||||
|
|
||||||
int is_bundle(const char *path, int quiet);
|
int is_bundle(const char *path, int quiet);
|
||||||
|
@ -143,6 +143,9 @@ static struct ref *get_refs_from_bundle(struct transport *transport,
|
|||||||
data->fd = read_bundle_header(transport->url, &data->header);
|
data->fd = read_bundle_header(transport->url, &data->header);
|
||||||
if (data->fd < 0)
|
if (data->fd < 0)
|
||||||
die(_("could not read bundle '%s'"), transport->url);
|
die(_("could not read bundle '%s'"), transport->url);
|
||||||
|
|
||||||
|
transport->hash_algo = data->header.hash_algo;
|
||||||
|
|
||||||
for (i = 0; i < data->header.references.nr; i++) {
|
for (i = 0; i < data->header.references.nr; i++) {
|
||||||
struct ref_list_entry *e = data->header.references.list + i;
|
struct ref_list_entry *e = data->header.references.list + i;
|
||||||
struct ref *ref = alloc_ref(e->name);
|
struct ref *ref = alloc_ref(e->name);
|
||||||
@ -157,11 +160,14 @@ static int fetch_refs_from_bundle(struct transport *transport,
|
|||||||
int nr_heads, struct ref **to_fetch)
|
int nr_heads, struct ref **to_fetch)
|
||||||
{
|
{
|
||||||
struct bundle_transport_data *data = transport->data;
|
struct bundle_transport_data *data = transport->data;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (!data->get_refs_from_bundle_called)
|
if (!data->get_refs_from_bundle_called)
|
||||||
get_refs_from_bundle(transport, 0, NULL);
|
get_refs_from_bundle(transport, 0, NULL);
|
||||||
return unbundle(the_repository, &data->header, data->fd,
|
ret = unbundle(the_repository, &data->header, data->fd,
|
||||||
transport->progress ? BUNDLE_VERBOSE : 0);
|
transport->progress ? BUNDLE_VERBOSE : 0);
|
||||||
|
transport->hash_algo = data->header.hash_algo;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int close_bundle(struct transport *transport)
|
static int close_bundle(struct transport *transport)
|
||||||
|
Reference in New Issue
Block a user