mirror of
https://github.com/git/git.git
synced 2025-12-12 20:36:24 +01:00
object-file: read objects via the loose object source
When reading an object via `loose_object_info()` or `map_loose_object()` we hand in the whole repository. We then iterate through each of the object sources to figure out whether that source has the object in question. This logic is reversing responsibility though: a specific backend should only care about one specific source, where the object sources themselves are then managed by the object database. Refactor the code accordingly by passing an object source to both of these functions instead. The different sources are then handled by either `do_oid_object_info_extended()`, which sits on the object database level, and by `open_istream_loose()`. The latter function arguably is still at the wrong level, but this will be cleaned up at a later point in time. 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
376016ec71
commit
ff7ad5cb39
@@ -167,25 +167,22 @@ int stream_object_signature(struct repository *r, const struct object_id *oid)
|
||||
}
|
||||
|
||||
/*
|
||||
* Find "oid" as a loose object in the local repository or in an alternate.
|
||||
* Find "oid" as a loose object in given source.
|
||||
* Returns 0 on success, negative on failure.
|
||||
*
|
||||
* The "path" out-parameter will give the path of the object we found (if any).
|
||||
* Note that it may point to static storage and is only valid until another
|
||||
* call to stat_loose_object().
|
||||
*/
|
||||
static int stat_loose_object(struct repository *r, const struct object_id *oid,
|
||||
static int stat_loose_object(struct odb_source_loose *loose,
|
||||
const struct object_id *oid,
|
||||
struct stat *st, const char **path)
|
||||
{
|
||||
struct odb_source *source;
|
||||
static struct strbuf buf = STRBUF_INIT;
|
||||
|
||||
odb_prepare_alternates(r->objects);
|
||||
for (source = r->objects->sources; source; source = source->next) {
|
||||
*path = odb_loose_path(source, &buf, oid);
|
||||
*path = odb_loose_path(loose->source, &buf, oid);
|
||||
if (!lstat(*path, st))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
@@ -194,39 +191,24 @@ static int stat_loose_object(struct repository *r, const struct object_id *oid,
|
||||
* Like stat_loose_object(), but actually open the object and return the
|
||||
* descriptor. See the caveats on the "path" parameter above.
|
||||
*/
|
||||
static int open_loose_object(struct repository *r,
|
||||
static int open_loose_object(struct odb_source_loose *loose,
|
||||
const struct object_id *oid, const char **path)
|
||||
{
|
||||
int fd;
|
||||
struct odb_source *source;
|
||||
int most_interesting_errno = ENOENT;
|
||||
static struct strbuf buf = STRBUF_INIT;
|
||||
int fd;
|
||||
|
||||
odb_prepare_alternates(r->objects);
|
||||
for (source = r->objects->sources; source; source = source->next) {
|
||||
*path = odb_loose_path(source, &buf, oid);
|
||||
*path = odb_loose_path(loose->source, &buf, oid);
|
||||
fd = git_open(*path);
|
||||
if (fd >= 0)
|
||||
return fd;
|
||||
|
||||
if (most_interesting_errno == ENOENT)
|
||||
most_interesting_errno = errno;
|
||||
}
|
||||
errno = most_interesting_errno;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int quick_has_loose(struct repository *r,
|
||||
static int quick_has_loose(struct odb_source_loose *loose,
|
||||
const struct object_id *oid)
|
||||
{
|
||||
struct odb_source *source;
|
||||
|
||||
odb_prepare_alternates(r->objects);
|
||||
for (source = r->objects->sources; source; source = source->next) {
|
||||
if (oidtree_contains(odb_source_loose_cache(source, oid), oid))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
return !!oidtree_contains(odb_source_loose_cache(loose->source, oid), oid);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -252,12 +234,12 @@ static void *map_fd(int fd, const char *path, unsigned long *size)
|
||||
return map;
|
||||
}
|
||||
|
||||
void *map_loose_object(struct repository *r,
|
||||
void *odb_source_loose_map_object(struct odb_source *source,
|
||||
const struct object_id *oid,
|
||||
unsigned long *size)
|
||||
{
|
||||
const char *p;
|
||||
int fd = open_loose_object(r, oid, &p);
|
||||
int fd = open_loose_object(source->loose, oid, &p);
|
||||
|
||||
if (fd < 0)
|
||||
return NULL;
|
||||
@@ -407,7 +389,7 @@ int parse_loose_header(const char *hdr, struct object_info *oi)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int loose_object_info(struct repository *r,
|
||||
int odb_source_loose_read_object_info(struct odb_source *source,
|
||||
const struct object_id *oid,
|
||||
struct object_info *oi, int flags)
|
||||
{
|
||||
@@ -422,7 +404,7 @@ int loose_object_info(struct repository *r,
|
||||
enum object_type type_scratch;
|
||||
|
||||
if (oi->delta_base_oid)
|
||||
oidclr(oi->delta_base_oid, r->hash_algo);
|
||||
oidclr(oi->delta_base_oid, source->odb->repo->hash_algo);
|
||||
|
||||
/*
|
||||
* If we don't care about type or size, then we don't
|
||||
@@ -435,15 +417,15 @@ int loose_object_info(struct repository *r,
|
||||
if (!oi->typep && !oi->sizep && !oi->contentp) {
|
||||
struct stat st;
|
||||
if (!oi->disk_sizep && (flags & OBJECT_INFO_QUICK))
|
||||
return quick_has_loose(r, oid) ? 0 : -1;
|
||||
if (stat_loose_object(r, oid, &st, &path) < 0)
|
||||
return quick_has_loose(source->loose, oid) ? 0 : -1;
|
||||
if (stat_loose_object(source->loose, oid, &st, &path) < 0)
|
||||
return -1;
|
||||
if (oi->disk_sizep)
|
||||
*oi->disk_sizep = st.st_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
fd = open_loose_object(r, oid, &path);
|
||||
fd = open_loose_object(source->loose, oid, &path);
|
||||
if (fd < 0) {
|
||||
if (errno != ENOENT)
|
||||
error_errno(_("unable to open loose object %s"), oid_to_hex(oid));
|
||||
|
||||
@@ -43,6 +43,14 @@ void odb_source_loose_free(struct odb_source_loose *loose);
|
||||
/* Reprepare the loose source by emptying the loose object cache. */
|
||||
void odb_source_loose_reprepare(struct odb_source *source);
|
||||
|
||||
int odb_source_loose_read_object_info(struct odb_source *source,
|
||||
const struct object_id *oid,
|
||||
struct object_info *oi, int flags);
|
||||
|
||||
void *odb_source_loose_map_object(struct odb_source *source,
|
||||
const struct object_id *oid,
|
||||
unsigned long *size);
|
||||
|
||||
/*
|
||||
* Populate and return the loose object cache array corresponding to the
|
||||
* given object ID.
|
||||
@@ -66,9 +74,6 @@ const char *odb_loose_path(struct odb_source *source,
|
||||
int has_loose_object(struct odb_source *source,
|
||||
const struct object_id *oid);
|
||||
|
||||
void *map_loose_object(struct repository *r, const struct object_id *oid,
|
||||
unsigned long *size);
|
||||
|
||||
/*
|
||||
* Iterate over the files in the loose-object parts of the object
|
||||
* directory "path", triggering the following callbacks:
|
||||
@@ -196,10 +201,6 @@ int check_object_signature(struct repository *r, const struct object_id *oid,
|
||||
*/
|
||||
int stream_object_signature(struct repository *r, const struct object_id *oid);
|
||||
|
||||
int loose_object_info(struct repository *r,
|
||||
const struct object_id *oid,
|
||||
struct object_info *oi, int flags);
|
||||
|
||||
enum finalize_object_file_flags {
|
||||
FOF_SKIP_COLLISION_CHECK = 1,
|
||||
};
|
||||
|
||||
7
odb.c
7
odb.c
@@ -697,12 +697,17 @@ static int do_oid_object_info_extended(struct object_database *odb,
|
||||
return 0;
|
||||
}
|
||||
|
||||
odb_prepare_alternates(odb);
|
||||
|
||||
while (1) {
|
||||
struct odb_source *source;
|
||||
|
||||
if (find_pack_entry(odb->repo, real, &e))
|
||||
break;
|
||||
|
||||
/* Most likely it's a loose object. */
|
||||
if (!loose_object_info(odb->repo, real, oi, flags))
|
||||
for (source = odb->sources; source; source = source->next)
|
||||
if (!odb_source_loose_read_object_info(source, real, oi, flags))
|
||||
return 0;
|
||||
|
||||
/* Not a loose object; someone else may have just packed it. */
|
||||
|
||||
11
streaming.c
11
streaming.c
@@ -230,12 +230,21 @@ static int open_istream_loose(struct git_istream *st, struct repository *r,
|
||||
enum object_type *type)
|
||||
{
|
||||
struct object_info oi = OBJECT_INFO_INIT;
|
||||
struct odb_source *source;
|
||||
|
||||
oi.sizep = &st->size;
|
||||
oi.typep = type;
|
||||
|
||||
st->u.loose.mapped = map_loose_object(r, oid, &st->u.loose.mapsize);
|
||||
odb_prepare_alternates(r->objects);
|
||||
for (source = r->objects->sources; source; source = source->next) {
|
||||
st->u.loose.mapped = odb_source_loose_map_object(source, oid,
|
||||
&st->u.loose.mapsize);
|
||||
if (st->u.loose.mapped)
|
||||
break;
|
||||
}
|
||||
if (!st->u.loose.mapped)
|
||||
return -1;
|
||||
|
||||
switch (unpack_loose_header(&st->z, st->u.loose.mapped,
|
||||
st->u.loose.mapsize, st->u.loose.hdr,
|
||||
sizeof(st->u.loose.hdr))) {
|
||||
|
||||
Reference in New Issue
Block a user