static int cached_object_nr, cached_object_alloc;
static struct cached_object empty_tree = {
- { EMPTY_TREE_SHA1_BIN_LITERAL },
- OBJ_TREE,
- "",
- 0
+ .oid = {
+ .hash = EMPTY_TREE_SHA1_BIN_LITERAL,
+ },
+ .type = OBJ_TREE,
+ .buf = "",
};
static struct cached_object *find_cached_object(const struct object_id *oid)
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.
- */
+static int format_object_header_literally(char *str, size_t size,
+ const char *type, size_t objsize)
+{
+ 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 *map, unsigned long size, const char *type,
- struct object_id *real_oidp)
+ void *buf, unsigned long size,
+ enum object_type type)
{
- struct object_id tmp;
- struct object_id *real_oid = real_oidp ? real_oidp : &tmp;
+ 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);
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)
{
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;
die(_("loose object %s (stored in %s) is corrupt"),
oid_to_hex(repl), path);
- if ((p = has_packed_and_bad(r, repl)) != NULL)
+ if ((p = has_packed_and_bad(r, repl)))
die(_("packed object %s (stored in %s) is corrupt"),
oid_to_hex(repl), p->pack_name);
obj_read_unlock();
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;
}
}
+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,
- const char *type, struct object_id *oid,
+ enum object_type 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;
+ *hdrlen = format_object_header(hdr, *hdrlen, type, len);
/* Sha1.. */
- algo->init_fn(&c);
- algo->update_fn(&c, hdr, *hdrlen);
- algo->update_fn(&c, buf, len);
- algo->final_oid_fn(oid, &c);
+ 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;
+
+ *hdrlen = format_object_header_literally(hdr, *hdrlen, type, len);
+ hash_object_body(algo, &c, buf, len, oid, hdr, hdrlen);
}
/*
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. */
-static void close_loose_object(int fd)
+static void close_loose_object(int fd, const char *filename)
{
if (the_repository->objects->odb->will_destroy)
goto out;
if (batch_fsync_enabled(FSYNC_COMPONENT_LOOSE_OBJECT))
- fsync_loose_object_bulk_checkin(fd, "loose object file");
+ fsync_loose_object_bulk_checkin(fd, filename);
else if (fsync_object_files > 0)
- fsync_or_die(fd, "loose object file");
+ fsync_or_die(fd, filename);
else
fsync_component_or_die(FSYNC_COMPONENT_LOOSE_OBJECT, fd,
- "loose object file");
+ filename);
out:
if (close(fd) != 0)
die(_("confused by unstable object source data for %s"),
oid_to_hex(oid));
- close_loose_object(fd);
+ close_loose_object(fd, tmp_file.buf);
if (mtime) {
struct utimbuf utb;
}
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];
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;
/* 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;
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);
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)
}
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;
const char *path,
unsigned flags)
{
- int ret;
+ int ret = 0;
const int write_object = flags & HASH_WRITE_OBJECT;
struct strbuf sbuf = STRBUF_INIT;
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;
}
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;
goto out;
}
- if (unpack_loose_header(&stream, map, mapsize, hdr, sizeof(hdr),
- NULL) < 0) {
+ switch (unpack_loose_header(&stream, map, mapsize, hdr, sizeof(hdr),
+ NULL)) {
+ case ULHR_OK:
+ break;
+ case ULHR_BAD:
+ case ULHR_TOO_LONG:
error(_("unable to unpack header of %s"), path);
goto out;
}
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;
}