@matheusbsbs / matheus-bagliano / commits / 6161ce7bbe
Fork 0

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>

brian m. carlson committed Jun 19, 2020 at 17:56 UTC 6161ce7bbeeb128dd1a176d8355e2ce18168b16a
3 files changed +30 -3
bundle.c
+21 -1
@@ -23,6 +23,17 @@ static void add_to_ref_list(const struct object_id *oid, const char *name,
23 list->nr++;
24 }
25
26 +static const struct git_hash_algo *detect_hash_algo(struct strbuf *buf)
27 +{
28 + size_t len = strcspn(buf->buf, " \n");
29 + int algo;
30 +
31 + algo = hash_algo_by_length(len / 2);
32 + if (algo == GIT_HASH_UNKNOWN)
33 + return NULL;
34 + return &hash_algos[algo];
35 +}
36 +
37 static int parse_bundle_header(int fd, struct bundle_header *header,
38 const char *report_path)
39 {
@@ -52,12 +63,21 @@ static int parse_bundle_header(int fd, struct bundle_header *header,
63 }
64 strbuf_rtrim(&buf);
65
66 + if (!header->hash_algo) {
67 + header->hash_algo = detect_hash_algo(&buf);
68 + if (!header->hash_algo) {
69 + error(_("unknown hash algorithm length"));
70 + status = -1;
71 + break;
72 + }
73 + }
74 +
75 /*
76 * Tip lines have object name, SP, and refname.
77 * Prerequisites have object name that is optionally
78 * followed by SP and subject line.
79 */
60 - if (parse_oid_hex(buf.buf, &oid, &p) ||
80 + if (parse_oid_hex_algop(buf.buf, &oid, &p, header->hash_algo) ||
81 (*p && !isspace(*p)) ||
82 (!is_prereq && !*p)) {
83 if (report_path)
bundle.h
+1
@@ -15,6 +15,7 @@ struct ref_list {
15 struct bundle_header {
16 struct ref_list prerequisites;
17 struct ref_list references;
18 + const struct git_hash_algo *hash_algo;
19 };
20
21 int is_bundle(const char *path, int quiet);
transport.c
+8 -2
@@ -143,6 +143,9 @@ static struct ref *get_refs_from_bundle(struct transport *transport,
143 data->fd = read_bundle_header(transport->url, &data->header);
144 if (data->fd < 0)
145 die(_("could not read bundle '%s'"), transport->url);
146 +
147 + transport->hash_algo = data->header.hash_algo;
148 +
149 for (i = 0; i < data->header.references.nr; i++) {
150 struct ref_list_entry *e = data->header.references.list + i;
151 struct ref *ref = alloc_ref(e->name);
@@ -157,11 +160,14 @@ static int fetch_refs_from_bundle(struct transport *transport,
160 int nr_heads, struct ref **to_fetch)
161 {
162 struct bundle_transport_data *data = transport->data;
163 + int ret;
164
165 if (!data->get_refs_from_bundle_called)
166 get_refs_from_bundle(transport, 0, NULL);
163 - return unbundle(the_repository, &data->header, data->fd,
164 - transport->progress ? BUNDLE_VERBOSE : 0);
167 + ret = unbundle(the_repository, &data->header, data->fd,
168 + transport->progress ? BUNDLE_VERBOSE : 0);
169 + transport->hash_algo = data->header.hash_algo;
170 + return ret;
171 }
172
173 static int close_bundle(struct transport *transport)