Merge branch 'ab/object-file-api-updates'

Object-file API shuffling.

* ab/object-file-api-updates:
  object-file API: pass an enum to read_object_with_reference()
  object-file.c: add a literal version of write_object_file_prepare()
  object-file API: have hash_object_file() take "enum object_type"
  object API: rename hash_object_file_literally() to write_*()
  object-file API: split up and simplify check_object_signature()
  object API users + docs: check <0, not !0 with check_object_signature()
  object API docs: move check_object_signature() docs to cache.h
  object API: correct "buf" v.s. "map" mismatch in *.c and *.h
  object-file API: have write_object_file() take "enum object_type"
  object-file API: add a format_object_header() function
  object-file API: return "void", not "int" from hash_object_file()
  object-file.c: split up declaration of unrelated variables
This commit is contained in:
Junio C Hamano
2022-03-16 17:53:08 -07:00
36 changed files with 205 additions and 140 deletions

View File

@ -1049,35 +1049,50 @@ void *xmmap(void *start, size_t length,
return ret;
}
/*
* With an in-core object data in "map", rehash it to make sure the
* object name actually matches "oid" to detect object corruption.
* With "map" == NULL, try reading the object named with "oid" using
* the streaming interface and rehash it to do the same.
*/
int check_object_signature(struct repository *r, const struct object_id *oid,
void *map, unsigned long size, const char *type,
struct object_id *real_oidp)
static int format_object_header_literally(char *str, size_t size,
const char *type, size_t objsize)
{
struct object_id tmp;
struct object_id *real_oid = real_oidp ? real_oidp : &tmp;
return xsnprintf(str, size, "%s %"PRIuMAX, type, (uintmax_t)objsize) + 1;
}
int format_object_header(char *str, size_t size, enum object_type type,
size_t objsize)
{
const char *name = type_name(type);
if (!name)
BUG("could not get a type name for 'enum object_type' value %d", type);
return format_object_header_literally(str, size, name, objsize);
}
int check_object_signature(struct repository *r, const struct object_id *oid,
void *buf, unsigned long size,
enum object_type type)
{
struct object_id real_oid;
hash_object_file(r->hash_algo, buf, size, type, &real_oid);
return !oideq(oid, &real_oid) ? -1 : 0;
}
int stream_object_signature(struct repository *r, const struct object_id *oid)
{
struct object_id real_oid;
unsigned long size;
enum object_type obj_type;
struct git_istream *st;
git_hash_ctx c;
char hdr[MAX_HEADER_LEN];
int hdrlen;
if (map) {
hash_object_file(r->hash_algo, map, size, type, real_oid);
return !oideq(oid, real_oid) ? -1 : 0;
}
st = open_istream(r, oid, &obj_type, &size, NULL);
if (!st)
return -1;
/* Generate the header */
hdrlen = xsnprintf(hdr, sizeof(hdr), "%s %"PRIuMAX , type_name(obj_type), (uintmax_t)size) + 1;
hdrlen = format_object_header(hdr, sizeof(hdr), obj_type, size);
/* Sha1.. */
r->hash_algo->init_fn(&c);
@ -1094,9 +1109,9 @@ int check_object_signature(struct repository *r, const struct object_id *oid,
break;
r->hash_algo->update_fn(&c, buf, readlen);
}
r->hash_algo->final_oid_fn(real_oid, &c);
r->hash_algo->final_oid_fn(&real_oid, &c);
close_istream(st);
return !oideq(oid, real_oid) ? -1 : 0;
return !oideq(oid, &real_oid) ? -1 : 0;
}
int git_open_cloexec(const char *name, int flags)
@ -1662,7 +1677,7 @@ int pretend_object_file(void *buf, unsigned long len, enum object_type type,
{
struct cached_object *co;
hash_object_file(the_hash_algo, buf, len, type_name(type), oid);
hash_object_file(the_hash_algo, buf, len, type, oid);
if (has_object_file_with_flags(oid, OBJECT_INFO_QUICK | OBJECT_INFO_SKIP_FETCH_OBJECT) ||
find_cached_object(oid))
return 0;
@ -1722,16 +1737,15 @@ void *read_object_file_extended(struct repository *r,
void *read_object_with_reference(struct repository *r,
const struct object_id *oid,
const char *required_type_name,
enum object_type required_type,
unsigned long *size,
struct object_id *actual_oid_return)
{
enum object_type type, required_type;
enum object_type type;
void *buffer;
unsigned long isize;
struct object_id actual_oid;
required_type = type_from_string(required_type_name);
oidcpy(&actual_oid, oid);
while (1) {
int ref_length = -1;
@ -1769,21 +1783,40 @@ void *read_object_with_reference(struct repository *r,
}
}
static void hash_object_body(const struct git_hash_algo *algo, git_hash_ctx *c,
const void *buf, unsigned long len,
struct object_id *oid,
char *hdr, int *hdrlen)
{
algo->init_fn(c);
algo->update_fn(c, hdr, *hdrlen);
algo->update_fn(c, buf, len);
algo->final_oid_fn(oid, c);
}
static void write_object_file_prepare(const struct git_hash_algo *algo,
const void *buf, unsigned long len,
enum object_type type, struct object_id *oid,
char *hdr, int *hdrlen)
{
git_hash_ctx c;
/* Generate the header */
*hdrlen = format_object_header(hdr, *hdrlen, type, len);
/* Sha1.. */
hash_object_body(algo, &c, buf, len, oid, hdr, hdrlen);
}
static void write_object_file_prepare_literally(const struct git_hash_algo *algo,
const void *buf, unsigned long len,
const char *type, struct object_id *oid,
char *hdr, int *hdrlen)
{
git_hash_ctx c;
/* Generate the header */
*hdrlen = xsnprintf(hdr, *hdrlen, "%s %"PRIuMAX , type, (uintmax_t)len)+1;
/* Sha1.. */
algo->init_fn(&c);
algo->update_fn(&c, hdr, *hdrlen);
algo->update_fn(&c, buf, len);
algo->final_oid_fn(oid, &c);
*hdrlen = format_object_header_literally(hdr, *hdrlen, type, len);
hash_object_body(algo, &c, buf, len, oid, hdr, hdrlen);
}
/*
@ -1836,14 +1869,21 @@ static int write_buffer(int fd, const void *buf, size_t len)
return 0;
}
int hash_object_file(const struct git_hash_algo *algo, const void *buf,
unsigned long len, const char *type,
struct object_id *oid)
static void hash_object_file_literally(const struct git_hash_algo *algo,
const void *buf, unsigned long len,
const char *type, struct object_id *oid)
{
char hdr[MAX_HEADER_LEN];
int hdrlen = sizeof(hdr);
write_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen);
return 0;
write_object_file_prepare_literally(algo, buf, len, type, oid, hdr, &hdrlen);
}
void hash_object_file(const struct git_hash_algo *algo, const void *buf,
unsigned long len, enum object_type type,
struct object_id *oid)
{
hash_object_file_literally(algo, buf, len, type_name(type), oid);
}
/* Finalize a file on disk, and close it. */
@ -1998,7 +2038,7 @@ static int freshen_packed_object(const struct object_id *oid)
}
int write_object_file_flags(const void *buf, unsigned long len,
const char *type, struct object_id *oid,
enum object_type type, struct object_id *oid,
unsigned flags)
{
char hdr[MAX_HEADER_LEN];
@ -2014,9 +2054,9 @@ int write_object_file_flags(const void *buf, unsigned long len,
return write_loose_object(oid, hdr, hdrlen, buf, len, 0, flags);
}
int hash_object_file_literally(const void *buf, unsigned long len,
const char *type, struct object_id *oid,
unsigned flags)
int write_object_file_literally(const void *buf, unsigned long len,
const char *type, struct object_id *oid,
unsigned flags)
{
char *header;
int hdrlen, status = 0;
@ -2024,8 +2064,8 @@ int hash_object_file_literally(const void *buf, unsigned long len,
/* type string, SP, %lu of the length plus NUL must fit this */
hdrlen = strlen(type) + MAX_HEADER_LEN;
header = xmalloc(hdrlen);
write_object_file_prepare(the_hash_algo, buf, len, type, oid, header,
&hdrlen);
write_object_file_prepare_literally(the_hash_algo, buf, len, type,
oid, header, &hdrlen);
if (!(flags & HASH_WRITE_OBJECT))
goto cleanup;
@ -2052,7 +2092,7 @@ int force_object_loose(const struct object_id *oid, time_t mtime)
buf = read_object(the_repository, oid, &type, &len);
if (!buf)
return error(_("cannot read object for %s"), oid_to_hex(oid));
hdrlen = xsnprintf(hdr, sizeof(hdr), "%s %"PRIuMAX , type_name(type), (uintmax_t)len) + 1;
hdrlen = format_object_header(hdr, sizeof(hdr), type, len);
ret = write_loose_object(oid, hdr, hdrlen, buf, len, mtime, 0);
free(buf);
@ -2118,7 +2158,8 @@ static int index_mem(struct index_state *istate,
enum object_type type,
const char *path, unsigned flags)
{
int ret, re_allocated = 0;
int ret = 0;
int re_allocated = 0;
int write_object = flags & HASH_WRITE_OBJECT;
if (!type)
@ -2145,10 +2186,9 @@ static int index_mem(struct index_state *istate,
}
if (write_object)
ret = write_object_file(buf, size, type_name(type), oid);
ret = write_object_file(buf, size, type, oid);
else
ret = hash_object_file(the_hash_algo, buf, size,
type_name(type), oid);
hash_object_file(the_hash_algo, buf, size, type, oid);
if (re_allocated)
free(buf);
return ret;
@ -2160,7 +2200,7 @@ static int index_stream_convert_blob(struct index_state *istate,
const char *path,
unsigned flags)
{
int ret;
int ret = 0;
const int write_object = flags & HASH_WRITE_OBJECT;
struct strbuf sbuf = STRBUF_INIT;
@ -2171,11 +2211,11 @@ static int index_stream_convert_blob(struct index_state *istate,
get_conv_flags(flags));
if (write_object)
ret = write_object_file(sbuf.buf, sbuf.len, type_name(OBJ_BLOB),
ret = write_object_file(sbuf.buf, sbuf.len, OBJ_BLOB,
oid);
else
ret = hash_object_file(the_hash_algo, sbuf.buf, sbuf.len,
type_name(OBJ_BLOB), oid);
hash_object_file(the_hash_algo, sbuf.buf, sbuf.len, OBJ_BLOB,
oid);
strbuf_release(&sbuf);
return ret;
}
@ -2294,8 +2334,8 @@ int index_path(struct index_state *istate, struct object_id *oid,
return error_errno("readlink(\"%s\")", path);
if (!(flags & HASH_WRITE_OBJECT))
hash_object_file(the_hash_algo, sb.buf, sb.len,
blob_type, oid);
else if (write_object_file(sb.buf, sb.len, blob_type, oid))
OBJ_BLOB, oid);
else if (write_object_file(sb.buf, sb.len, OBJ_BLOB, oid))
rc = error(_("%s: failed to insert into database"), path);
strbuf_release(&sb);
break;
@ -2599,9 +2639,10 @@ int read_loose_object(const char *path,
git_inflate_end(&stream);
goto out;
}
if (check_object_signature(the_repository, expected_oid,
hash_object_file_literally(the_repository->hash_algo,
*contents, *size,
oi->type_name->buf, real_oid))
oi->type_name->buf, real_oid);
if (!oideq(expected_oid, real_oid))
goto out;
}