mirror of
https://github.com/git/git.git
synced 2026-08-09 09:34:14 +00:00
object-file: adapt stream_object_signature() to take a stream
The function `stream_object_signature()` is responsible for verifying whether the given object ID matches the actual hash of the object's contents. In contrast to `check_object_signature()` it does so in a streaming fashion so that we don't have to load the full object into memory. In a subsequent commit we'll want to adapt one of its callsites to pass a preconstructed stream. Prepare for this by accepting a stream as input that the caller needs to assemble. While at it, improve the error reporting in `parse_object_with_flags()` to tell apart the two failure modes. Helped-by: Jeff King <peff@peff.net> Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
committed by
Junio C Hamano
parent
26fc7b59cd
commit
10a6762719
@@ -129,18 +129,15 @@ int check_object_signature(struct repository *r, const struct object_id *oid,
|
|||||||
return !oideq(oid, &real_oid) ? -1 : 0;
|
return !oideq(oid, &real_oid) ? -1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int stream_object_signature(struct repository *r, const struct object_id *oid)
|
int stream_object_signature(struct repository *r,
|
||||||
|
struct odb_read_stream *st,
|
||||||
|
const struct object_id *oid)
|
||||||
{
|
{
|
||||||
struct object_id real_oid;
|
struct object_id real_oid;
|
||||||
struct odb_read_stream *st;
|
|
||||||
struct git_hash_ctx c;
|
struct git_hash_ctx c;
|
||||||
char hdr[MAX_HEADER_LEN];
|
char hdr[MAX_HEADER_LEN];
|
||||||
int hdrlen;
|
int hdrlen;
|
||||||
|
|
||||||
st = odb_read_stream_open(r->objects, oid, NULL);
|
|
||||||
if (!st)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* Generate the header */
|
/* Generate the header */
|
||||||
hdrlen = format_object_header(hdr, sizeof(hdr), st->type, st->size);
|
hdrlen = format_object_header(hdr, sizeof(hdr), st->type, st->size);
|
||||||
|
|
||||||
@@ -160,7 +157,6 @@ int stream_object_signature(struct repository *r, const struct object_id *oid)
|
|||||||
git_hash_update(&c, buf, readlen);
|
git_hash_update(&c, buf, readlen);
|
||||||
}
|
}
|
||||||
git_hash_final_oid(&real_oid, &c);
|
git_hash_final_oid(&real_oid, &c);
|
||||||
odb_read_stream_close(st);
|
|
||||||
return !oideq(oid, &real_oid) ? -1 : 0;
|
return !oideq(oid, &real_oid) ? -1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -164,7 +164,9 @@ int check_object_signature(struct repository *r, const struct object_id *oid,
|
|||||||
* Try reading the object named with "oid" using
|
* Try reading the object named with "oid" using
|
||||||
* the streaming interface and rehash it to do the same.
|
* the streaming interface and rehash it to do the same.
|
||||||
*/
|
*/
|
||||||
int stream_object_signature(struct repository *r, const struct object_id *oid);
|
int stream_object_signature(struct repository *r,
|
||||||
|
struct odb_read_stream *stream,
|
||||||
|
const struct object_id *oid);
|
||||||
|
|
||||||
enum finalize_object_file_flags {
|
enum finalize_object_file_flags {
|
||||||
FOF_SKIP_COLLISION_CHECK = 1,
|
FOF_SKIP_COLLISION_CHECK = 1,
|
||||||
|
|||||||
19
object.c
19
object.c
@@ -6,6 +6,7 @@
|
|||||||
#include "object.h"
|
#include "object.h"
|
||||||
#include "replace-object.h"
|
#include "replace-object.h"
|
||||||
#include "object-file.h"
|
#include "object-file.h"
|
||||||
|
#include "odb/streaming.h"
|
||||||
#include "blob.h"
|
#include "blob.h"
|
||||||
#include "statinfo.h"
|
#include "statinfo.h"
|
||||||
#include "tree.h"
|
#include "tree.h"
|
||||||
@@ -330,9 +331,21 @@ struct object *parse_object_with_flags(struct repository *r,
|
|||||||
|
|
||||||
if ((!obj || obj->type == OBJ_NONE || obj->type == OBJ_BLOB) &&
|
if ((!obj || obj->type == OBJ_NONE || obj->type == OBJ_BLOB) &&
|
||||||
odb_read_object_info(r->objects, oid, NULL) == OBJ_BLOB) {
|
odb_read_object_info(r->objects, oid, NULL) == OBJ_BLOB) {
|
||||||
if (!skip_hash && stream_object_signature(r, repl) < 0) {
|
if (!skip_hash) {
|
||||||
error(_("hash mismatch %s"), oid_to_hex(oid));
|
struct odb_read_stream *stream = odb_read_stream_open(r->objects, oid, NULL);
|
||||||
return NULL;
|
|
||||||
|
if (!stream) {
|
||||||
|
error(_("unable to open object stream for %s"), oid_to_hex(oid));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stream_object_signature(r, stream, repl) < 0) {
|
||||||
|
error(_("hash mismatch %s"), oid_to_hex(oid));
|
||||||
|
odb_read_stream_close(stream);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
odb_read_stream_close(stream);
|
||||||
}
|
}
|
||||||
parse_blob_buffer(lookup_blob(r, oid));
|
parse_blob_buffer(lookup_blob(r, oid));
|
||||||
return lookup_object(r, oid);
|
return lookup_object(r, oid);
|
||||||
|
|||||||
12
pack-check.c
12
pack-check.c
@@ -9,6 +9,7 @@
|
|||||||
#include "packfile.h"
|
#include "packfile.h"
|
||||||
#include "object-file.h"
|
#include "object-file.h"
|
||||||
#include "odb.h"
|
#include "odb.h"
|
||||||
|
#include "odb/streaming.h"
|
||||||
|
|
||||||
struct idx_entry {
|
struct idx_entry {
|
||||||
off_t offset;
|
off_t offset;
|
||||||
@@ -104,6 +105,7 @@ static int verify_packfile(struct repository *r,
|
|||||||
QSORT(entries, nr_objects, compare_entries);
|
QSORT(entries, nr_objects, compare_entries);
|
||||||
|
|
||||||
for (i = 0; i < nr_objects; i++) {
|
for (i = 0; i < nr_objects; i++) {
|
||||||
|
struct odb_read_stream *stream = NULL;
|
||||||
void *data;
|
void *data;
|
||||||
struct object_id oid;
|
struct object_id oid;
|
||||||
enum object_type type;
|
enum object_type type;
|
||||||
@@ -152,7 +154,9 @@ static int verify_packfile(struct repository *r,
|
|||||||
type) < 0)
|
type) < 0)
|
||||||
err = error("packed %s from %s is corrupt",
|
err = error("packed %s from %s is corrupt",
|
||||||
oid_to_hex(&oid), p->pack_name);
|
oid_to_hex(&oid), p->pack_name);
|
||||||
else if (!data && stream_object_signature(r, &oid) < 0)
|
else if (!data &&
|
||||||
|
(!(stream = odb_read_stream_open(r->objects, &oid, NULL)) ||
|
||||||
|
stream_object_signature(r, stream, &oid) < 0))
|
||||||
err = error("packed %s from %s is corrupt",
|
err = error("packed %s from %s is corrupt",
|
||||||
oid_to_hex(&oid), p->pack_name);
|
oid_to_hex(&oid), p->pack_name);
|
||||||
else if (fn) {
|
else if (fn) {
|
||||||
@@ -163,12 +167,14 @@ static int verify_packfile(struct repository *r,
|
|||||||
}
|
}
|
||||||
if (((base_count + i) & 1023) == 0)
|
if (((base_count + i) & 1023) == 0)
|
||||||
display_progress(progress, base_count + i);
|
display_progress(progress, base_count + i);
|
||||||
free(data);
|
|
||||||
|
|
||||||
|
if (stream)
|
||||||
|
odb_read_stream_close(stream);
|
||||||
|
free(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
display_progress(progress, base_count + i);
|
display_progress(progress, base_count + i);
|
||||||
free(entries);
|
free(entries);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user