mirror of
https://github.com/git-for-windows/git.git
synced 2026-05-29 22:43:24 -05:00
Merge branch 'ps/object-source-loose'
A part of code paths that deals with loose objects has been cleaned up. * ps/object-source-loose: object-file: refactor writing objects via a stream object-file: rename `write_object_file()` object-file: refactor freshening of objects object-file: rename `has_loose_object()` object-file: read objects via the loose object source object-file: move loose object map into loose source object-file: hide internals when we need to reprepare loose sources object-file: move loose object cache into loose source object-file: introduce `struct odb_source_loose` object-file: move `fetch_if_missing` odb: adjust naming to free object sources odb: introduce `odb_source_new()` odb: fix subtle logic to check whether an alternate is usable
This commit is contained in:
175
object-file.c
175
object-file.c
@@ -99,8 +99,8 @@ static int check_and_freshen_source(struct odb_source *source,
|
||||
return check_and_freshen_file(path.buf, freshen);
|
||||
}
|
||||
|
||||
int has_loose_object(struct odb_source *source,
|
||||
const struct object_id *oid)
|
||||
int odb_source_loose_has_object(struct odb_source *source,
|
||||
const struct object_id *oid)
|
||||
{
|
||||
return check_and_freshen_source(source, oid, 0);
|
||||
}
|
||||
@@ -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);
|
||||
if (!lstat(*path, st))
|
||||
return 0;
|
||||
}
|
||||
*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);
|
||||
fd = git_open(*path);
|
||||
if (fd >= 0)
|
||||
return fd;
|
||||
*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_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,
|
||||
const struct object_id *oid,
|
||||
unsigned long *size)
|
||||
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,9 +389,9 @@ int parse_loose_header(const char *hdr, struct object_info *oi)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int loose_object_info(struct repository *r,
|
||||
const struct object_id *oid,
|
||||
struct object_info *oi, int flags)
|
||||
int odb_source_loose_read_object_info(struct odb_source *source,
|
||||
const struct object_id *oid,
|
||||
struct object_info *oi, int flags)
|
||||
{
|
||||
int status = 0;
|
||||
int fd;
|
||||
@@ -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));
|
||||
@@ -986,35 +968,15 @@ static int write_loose_object(struct odb_source *source,
|
||||
FOF_SKIP_COLLISION_CHECK);
|
||||
}
|
||||
|
||||
static int freshen_loose_object(struct object_database *odb,
|
||||
const struct object_id *oid)
|
||||
int odb_source_loose_freshen_object(struct odb_source *source,
|
||||
const struct object_id *oid)
|
||||
{
|
||||
odb_prepare_alternates(odb);
|
||||
for (struct odb_source *source = odb->sources; source; source = source->next)
|
||||
if (check_and_freshen_source(source, oid, 1))
|
||||
return 1;
|
||||
return 0;
|
||||
return !!check_and_freshen_source(source, oid, 1);
|
||||
}
|
||||
|
||||
static int freshen_packed_object(struct object_database *odb,
|
||||
const struct object_id *oid)
|
||||
{
|
||||
struct pack_entry e;
|
||||
if (!find_pack_entry(odb->repo, oid, &e))
|
||||
return 0;
|
||||
if (e.p->is_cruft)
|
||||
return 0;
|
||||
if (e.p->freshened)
|
||||
return 1;
|
||||
if (!freshen_file(e.p->pack_name))
|
||||
return 0;
|
||||
e.p->freshened = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int stream_loose_object(struct odb_source *source,
|
||||
struct input_stream *in_stream, size_t len,
|
||||
struct object_id *oid)
|
||||
int odb_source_loose_write_stream(struct odb_source *source,
|
||||
struct odb_write_stream *in_stream, size_t len,
|
||||
struct object_id *oid)
|
||||
{
|
||||
const struct git_hash_algo *compat = source->odb->repo->compat_hash_algo;
|
||||
struct object_id compat_oid;
|
||||
@@ -1091,12 +1053,10 @@ int stream_loose_object(struct odb_source *source,
|
||||
die(_("deflateEnd on stream object failed (%d)"), ret);
|
||||
close_loose_object(source, fd, tmp_file.buf);
|
||||
|
||||
if (freshen_packed_object(source->odb, oid) ||
|
||||
freshen_loose_object(source->odb, oid)) {
|
||||
if (odb_freshen_object(source->odb, oid)) {
|
||||
unlink_or_warn(tmp_file.buf);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
odb_loose_path(source, &filename, oid);
|
||||
|
||||
/* We finally know the object path, and create the missing dir. */
|
||||
@@ -1124,10 +1084,10 @@ cleanup:
|
||||
return err;
|
||||
}
|
||||
|
||||
int write_object_file(struct odb_source *source,
|
||||
const void *buf, unsigned long len,
|
||||
enum object_type type, struct object_id *oid,
|
||||
struct object_id *compat_oid_in, unsigned flags)
|
||||
int odb_source_loose_write_object(struct odb_source *source,
|
||||
const void *buf, unsigned long len,
|
||||
enum object_type type, struct object_id *oid,
|
||||
struct object_id *compat_oid_in, unsigned flags)
|
||||
{
|
||||
const struct git_hash_algo *algo = source->odb->repo->hash_algo;
|
||||
const struct git_hash_algo *compat = source->odb->repo->compat_hash_algo;
|
||||
@@ -1155,8 +1115,7 @@ int write_object_file(struct odb_source *source,
|
||||
* it out into .git/objects/??/?{38} file.
|
||||
*/
|
||||
write_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen);
|
||||
if (freshen_packed_object(source->odb, oid) ||
|
||||
freshen_loose_object(source->odb, oid))
|
||||
if (odb_freshen_object(source->odb, oid))
|
||||
return 0;
|
||||
if (write_loose_object(source, oid, hdr, hdrlen, buf, len, 0, flags))
|
||||
return -1;
|
||||
@@ -1179,7 +1138,7 @@ int force_object_loose(struct odb_source *source,
|
||||
int ret;
|
||||
|
||||
for (struct odb_source *s = source->odb->sources; s; s = s->next)
|
||||
if (has_loose_object(s, oid))
|
||||
if (odb_source_loose_has_object(s, oid))
|
||||
return 0;
|
||||
|
||||
oi.typep = &type;
|
||||
@@ -1806,44 +1765,49 @@ static int append_loose_object(const struct object_id *oid,
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct oidtree *odb_loose_cache(struct odb_source *source,
|
||||
const struct object_id *oid)
|
||||
struct oidtree *odb_source_loose_cache(struct odb_source *source,
|
||||
const struct object_id *oid)
|
||||
{
|
||||
int subdir_nr = oid->hash[0];
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
size_t word_bits = bitsizeof(source->loose_objects_subdir_seen[0]);
|
||||
size_t word_bits = bitsizeof(source->loose->subdir_seen[0]);
|
||||
size_t word_index = subdir_nr / word_bits;
|
||||
size_t mask = (size_t)1u << (subdir_nr % word_bits);
|
||||
uint32_t *bitmap;
|
||||
|
||||
if (subdir_nr < 0 ||
|
||||
(size_t) subdir_nr >= bitsizeof(source->loose_objects_subdir_seen))
|
||||
(size_t) subdir_nr >= bitsizeof(source->loose->subdir_seen))
|
||||
BUG("subdir_nr out of range");
|
||||
|
||||
bitmap = &source->loose_objects_subdir_seen[word_index];
|
||||
bitmap = &source->loose->subdir_seen[word_index];
|
||||
if (*bitmap & mask)
|
||||
return source->loose_objects_cache;
|
||||
if (!source->loose_objects_cache) {
|
||||
ALLOC_ARRAY(source->loose_objects_cache, 1);
|
||||
oidtree_init(source->loose_objects_cache);
|
||||
return source->loose->cache;
|
||||
if (!source->loose->cache) {
|
||||
ALLOC_ARRAY(source->loose->cache, 1);
|
||||
oidtree_init(source->loose->cache);
|
||||
}
|
||||
strbuf_addstr(&buf, source->path);
|
||||
for_each_file_in_obj_subdir(subdir_nr, &buf,
|
||||
source->odb->repo->hash_algo,
|
||||
append_loose_object,
|
||||
NULL, NULL,
|
||||
source->loose_objects_cache);
|
||||
source->loose->cache);
|
||||
*bitmap |= mask;
|
||||
strbuf_release(&buf);
|
||||
return source->loose_objects_cache;
|
||||
return source->loose->cache;
|
||||
}
|
||||
|
||||
void odb_clear_loose_cache(struct odb_source *source)
|
||||
static void odb_source_loose_clear_cache(struct odb_source_loose *loose)
|
||||
{
|
||||
oidtree_clear(source->loose_objects_cache);
|
||||
FREE_AND_NULL(source->loose_objects_cache);
|
||||
memset(&source->loose_objects_subdir_seen, 0,
|
||||
sizeof(source->loose_objects_subdir_seen));
|
||||
oidtree_clear(loose->cache);
|
||||
FREE_AND_NULL(loose->cache);
|
||||
memset(&loose->subdir_seen, 0,
|
||||
sizeof(loose->subdir_seen));
|
||||
}
|
||||
|
||||
void odb_source_loose_reprepare(struct odb_source *source)
|
||||
{
|
||||
odb_source_loose_clear_cache(source->loose);
|
||||
}
|
||||
|
||||
static int check_stream_oid(git_zstream *stream,
|
||||
@@ -1999,3 +1963,20 @@ void object_file_transaction_commit(struct odb_transaction *transaction)
|
||||
transaction->odb->transaction = NULL;
|
||||
free(transaction);
|
||||
}
|
||||
|
||||
struct odb_source_loose *odb_source_loose_new(struct odb_source *source)
|
||||
{
|
||||
struct odb_source_loose *loose;
|
||||
CALLOC_ARRAY(loose, 1);
|
||||
loose->source = source;
|
||||
return loose;
|
||||
}
|
||||
|
||||
void odb_source_loose_free(struct odb_source_loose *loose)
|
||||
{
|
||||
if (!loose)
|
||||
return;
|
||||
odb_source_loose_clear_cache(loose);
|
||||
loose_object_map_clear(&loose->map);
|
||||
free(loose);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user