odb: compute object hash in `odb_write_object_ext()`

Same as in a preceding commit, compute the object hash in
`odb_write_object_ext()` so that we can unify this logic.

Besides unification, this change also allows us to lift the object
existence check out of the "loose" backend into the generic layer, which
will happen in the next commit.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
jch
Patrick Steinhardt 2026-07-17 11:32:11 +02:00 committed by Junio C Hamano
parent cb5192ea9a
commit 46a586a719
9 changed files with 25 additions and 43 deletions

View File

@ -316,31 +316,6 @@ int parse_loose_header(const char *hdr, struct object_info *oi)
return 0;
}

static void hash_object_body(const struct git_hash_algo *algo, struct git_hash_ctx *c,
const void *buf, size_t len,
struct object_id *oid,
char *hdr, size_t *hdrlen)
{
git_hash_init(c, algo);
git_hash_update(c, hdr, *hdrlen);
git_hash_update(c, buf, len);
git_hash_final_oid(oid, c);
}

void write_object_file_prepare(const struct git_hash_algo *algo,
const void *buf, size_t len,
enum object_type type, struct object_id *oid,
char *hdr, size_t *hdrlen)
{
struct git_hash_ctx c;

/* Generate the header */
*hdrlen = format_object_header(hdr, *hdrlen, type, len);

/* Hash (function pointers) computation */
hash_object_body(algo, &c, buf, len, oid, hdr, hdrlen);
}

#define CHECK_COLLISION_DEST_VANISHED -2

static int check_collision(const char *source, const char *dest)
@ -476,10 +451,16 @@ void hash_object_file(const struct git_hash_algo *algo, const void *buf,
size_t len, enum object_type type,
struct object_id *oid)
{
struct git_hash_ctx c;
char hdr[MAX_HEADER_LEN];
size_t hdrlen = sizeof(hdr);
int hdrlen;

write_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen);
hdrlen = format_object_header(hdr, sizeof(hdr), type, len);

git_hash_init(&c, algo);
git_hash_update(&c, hdr, hdrlen);
git_hash_update(&c, buf, len);
git_hash_final_oid(oid, &c);
}

struct transaction_packfile {

View File

@ -134,10 +134,6 @@ int finalize_object_file_flags(struct repository *repo,
void hash_object_file(const struct git_hash_algo *algo, const void *buf,
size_t len, enum object_type type,
struct object_id *oid);
void write_object_file_prepare(const struct git_hash_algo *algo,
const void *buf, size_t len,
enum object_type type, struct object_id *oid,
char *hdr, size_t *hdrlen);
int write_loose_object(struct odb_source_loose *loose,
const struct object_id *oid, char *hdr,
int hdrlen, const void *buf, unsigned long len,

2
odb.c
View File

@ -995,6 +995,8 @@ int odb_write_object_ext(struct object_database *odb,
const struct git_hash_algo *compat = odb->repo->compat_hash_algo;
struct object_id compat_oid, *compat_oid_p = NULL;

hash_object_file(odb->repo->hash_algo, buf, len, type, oid);

if (compat) {
const struct git_hash_algo *algo = odb->repo->hash_algo;


View File

@ -162,7 +162,7 @@ static int odb_source_files_freshen_object(struct odb_source *source,
static int odb_source_files_write_object(struct odb_source *source,
const void *buf, size_t len,
enum object_type type,
struct object_id *oid,
const struct object_id *oid,
const struct object_id *compat_oid,
enum odb_write_object_flags flags)
{

View File

@ -230,15 +230,13 @@ static int odb_source_inmemory_count_objects(struct odb_source *source,
static int odb_source_inmemory_write_object(struct odb_source *source,
const void *buf, size_t len,
enum object_type type,
struct object_id *oid,
const struct object_id *oid,
const struct object_id *compat_oid UNUSED,
enum odb_write_object_flags flags UNUSED)
{
struct odb_source_inmemory *inmemory = odb_source_inmemory_downcast(source);
struct inmemory_object *object;

hash_object_file(source->odb->repo->hash_algo, buf, len, type, oid);

if (!inmemory->objects) {
CALLOC_ARRAY(inmemory->objects, 1);
oidtree_init(inmemory->objects);
@ -285,6 +283,8 @@ static int odb_source_inmemory_write_object_stream(struct odb_source *source,
goto out;
}

hash_object_file(source->odb->repo->hash_algo, data, total_read, OBJ_BLOB, oid);

ret = odb_source_inmemory_write_object(source, data, len, OBJ_BLOB, oid,
NULL, 0);
if (ret < 0)

View File

@ -584,19 +584,21 @@ static int odb_source_loose_freshen_object(struct odb_source *source,

static int odb_source_loose_write_object(struct odb_source *source,
const void *buf, size_t len,
enum object_type type, struct object_id *oid,
enum object_type type,
const struct object_id *oid,
const struct object_id *compat_oid,
enum odb_write_object_flags flags)
{
struct odb_source_loose *loose = odb_source_loose_downcast(source);
const struct git_hash_algo *algo = source->odb->repo->hash_algo;
char hdr[MAX_HEADER_LEN];
size_t hdrlen = sizeof(hdr);
int hdrlen;

/* Normally if we have it in the pack then we do not bother writing
hdrlen = format_object_header(hdr, sizeof(hdr), type, len);

/*
* Normally if we have it in the pack then we do not bother writing
* it out into .git/objects/??/?{38} file.
*/
write_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen);
if (odb_freshen_object(source->odb, oid))
return 0;
if (write_loose_object(loose, oid, hdr, hdrlen, buf, len, 0, flags))

View File

@ -529,7 +529,7 @@ static int odb_source_packed_write_object(struct odb_source *source UNUSED,
const void *buf UNUSED,
size_t len UNUSED,
enum object_type type UNUSED,
struct object_id *oid UNUSED,
const struct object_id *oid UNUSED,
const struct object_id *compat_oid UNUSED,
unsigned flags UNUSED)
{

View File

@ -206,7 +206,7 @@ struct odb_source {
int (*write_object)(struct odb_source *source,
const void *buf, size_t len,
enum object_type type,
struct object_id *oid,
const struct object_id *oid,
const struct object_id *compat_oid,
enum odb_write_object_flags flags);

@ -416,7 +416,7 @@ static inline int odb_source_freshen_object(struct odb_source *source,
static inline int odb_source_write_object(struct odb_source *source,
const void *buf, unsigned long len,
enum object_type type,
struct object_id *oid,
const struct object_id *oid,
const struct object_id *compat_oid,
enum odb_write_object_flags flags)
{

View File

@ -43,6 +43,7 @@ static void cl_assert_write_object(struct odb_source_inmemory *source,
struct object_id *oid)
{
size_t content_len = strlen(content);
hash_object_file(repo.hash_algo, content, content_len, type, oid);
cl_must_pass(odb_source_write_object(&source->base, content, content_len,
type, oid, NULL, 0));
}