Merge branch 'ps/odb-files-alternates' into ps/odb-files-alternates-cleanups

* ps/odb-files-alternates:
  odb/source: drop `read_alternates` callback
  odb/source-files: move alternates into the backend
  odb/source-files: extract reading alternates
  odb/source: make `will_destroy` an implementation detail
  tmp-objdir: replace primary source at creation time
  tmp-objdir: manage quarantine as an object directory
  tmp-objdir: absorb logic to set and restore primary sources
  odb/source-files: add the ability to have multiple object dirs
  odb: refactor `odb_find_source()` to yield dirs
  odb: refactor `odb_for_each_alternate()` to yield dirs
  odb/source-files: introduce `struct odb_files_dir`
  commit-graph: stop depending on `struct odb_source`
  commit-graph: require resolved packfile paths for `stdin_packs`
This commit is contained in:
Junio C Hamano committed 2026-10-13 07:28:54 -07:00
commit b2ef8d5d4d
52 files changed
+883 -954

No files matched your search

+29 -12
View File
@@ -8,6 +8,8 @@
#include "parse-options.h"
#include "commit-graph.h"
#include "odb.h"
#include "odb/source.h"
#include "odb/source-files.h"
#include "progress.h"
#include "replace-object.h"
#include "strbuf.h"
@@ -67,7 +69,7 @@ static int graph_verify(int argc, const char **argv, const char *prefix,
struct repository *repo UNUSED)
{
struct commit_graph *graph = NULL;
struct odb_source *source = NULL;
struct odb_files_dir *dir = NULL;
char *graph_name;
char *chain_name;
enum { OPENED_NONE, OPENED_GRAPH, OPENED_CHAIN } opened = OPENED_NONE;
@@ -102,9 +104,12 @@ static int graph_verify(int argc, const char **argv, const char *prefix,
if (opts.progress)
flags |= COMMIT_GRAPH_WRITE_PROGRESS;
source = odb_find_source_or_die(the_repository->objects, opts.obj_dir);
graph_name = get_commit_graph_filename(source);
chain_name = get_commit_graph_chain_filename(source);
dir = odb_source_files_find_dir(the_repository->objects, opts.obj_dir);
if (!dir)
die(_("could not find object directory matching %s"), opts.obj_dir);
graph_name = get_commit_graph_filename(dir->abspath);
chain_name = get_commit_graph_chain_filename(dir->abspath);
if (open_commit_graph(graph_name, &fd, &st))
opened = OPENED_GRAPH;
else if (errno != ENOENT)
@@ -122,7 +127,7 @@ static int graph_verify(int argc, const char **argv, const char *prefix,
if (opened == OPENED_NONE)
return 0;
else if (opened == OPENED_GRAPH)
graph = load_commit_graph_one_fd_st(source, fd, &st);
graph = load_commit_graph_one_fd_st(the_repository, dir->abspath, fd, &st);
else
graph = load_commit_graph_chain_fd_st(the_repository->objects, fd, &st,
&incomplete_chain);
@@ -225,7 +230,7 @@ static int graph_write(int argc, const char **argv, const char *prefix,
struct string_list pack_indexes = STRING_LIST_INIT_DUP;
struct strbuf buf = STRBUF_INIT;
struct oidset commits = OIDSET_INIT;
struct odb_source *source = NULL;
struct odb_files_dir *dir = NULL;
int result = 0;
enum commit_graph_write_flags flags = 0;
struct progress *progress = NULL;
@@ -293,18 +298,30 @@ static int graph_write(int argc, const char **argv, const char *prefix,
git_env_bool(GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS, 0))
flags |= COMMIT_GRAPH_WRITE_BLOOM_FILTERS;
source = odb_find_source_or_die(the_repository->objects, opts.obj_dir);
dir = odb_source_files_find_dir(the_repository->objects, opts.obj_dir);
if (!dir)
die(_("could not find object directory matching %s"), opts.obj_dir);
if (opts.reachable) {
if (write_commit_graph_reachable(source, flags, &write_opts))
if (write_commit_graph_reachable(the_repository, dir->abspath, flags, &write_opts))
result = 1;
goto cleanup;
}
if (opts.stdin_packs) {
while (strbuf_getline(&buf, stdin) != EOF)
string_list_append_nodup(&pack_indexes,
strbuf_detach(&buf, NULL));
struct strbuf packname = STRBUF_INIT;
size_t dirlen;
strbuf_addf(&packname, "%s/pack/", dir->abspath);
dirlen = packname.len;
while (strbuf_getline(&buf, stdin) != EOF) {
strbuf_setlen(&packname, dirlen);
strbuf_addbuf(&packname, &buf);
string_list_append(&pack_indexes, packname.buf);
}
strbuf_release(&packname);
} else if (opts.stdin_commits) {
oidset_init(&commits, 0);
if (opts.progress)
@@ -323,7 +340,7 @@ static int graph_write(int argc, const char **argv, const char *prefix,
stop_progress(&progress);
}
if (write_commit_graph(source,
if (write_commit_graph(the_repository, dir->abspath,
opts.stdin_packs ? &pack_indexes : NULL,
opts.stdin_commits ? &commits : NULL,
flags,
+1 -1
View File
@@ -1959,7 +1959,7 @@ int cmd_commit(int argc,
"new index file. Check that disk is not full and quota is\n"
"not exceeded, and then \"git restore --staged :/\" to recover."));
git_test_write_commit_graph_or_die(the_repository->objects->sources);
git_test_write_commit_graph_or_die(the_repository);
repo_rerere(the_repository, 0);
run_auto_maintenance(the_repository, quiet);
+3 -3
View File
@@ -81,10 +81,10 @@ static int count_cruft(const char *basename UNUSED, const char *path,
return 0;
}
static int print_alternate(struct odb_source *alternate, void *data UNUSED)
static int print_alternate(struct odb_files_dir *alternate, void *data UNUSED)
{
printf("alternate: ");
quote_c_style(alternate->path, NULL, stdout, 0);
quote_c_style(alternate->abspath, NULL, stdout, 0);
putchar('\n');
return 0;
}
@@ -118,7 +118,7 @@ int cmd_count_objects(int argc,
report_linked_checkout_garbage(the_repository);
}
for_each_loose_file_in_source(the_repository->objects->sources,
for_each_loose_file_in_source(the_repository->objects->source,
count_loose, count_cruft, NULL, NULL);
if (verbose) {
+8 -12
View File
@@ -895,7 +895,7 @@ static void end_packfile(void)
running = 1;
clear_delta_base_cache();
if (object_count) {
struct odb_source_files *files = odb_source_files_downcast(pack_data->repo->objects->sources);
struct odb_source_files *files = odb_source_files_downcast(pack_data->repo->objects->source);
struct packed_git *new_p;
struct object_id cur_pack_oid;
char *idx_name;
@@ -921,7 +921,7 @@ static void end_packfile(void)
idx_name = keep_pack(create_index());
/* Register the packfile with core git's machinery. */
new_p = packfile_store_load_pack(files->packed, idx_name, 1);
new_p = packfile_store_load_pack(files->dirs->packed, idx_name, 1);
if (!new_p)
die(_("core Git rejected index %s"), idx_name);
all_packs[pack_id] = new_p;
@@ -975,7 +975,7 @@ static int store_object(
struct object_id *oidout,
uintmax_t mark)
{
struct odb_source *source;
struct odb_source_files *files = odb_source_files_downcast(the_repository->objects->source);
void *out, *delta;
struct object_entry *e;
unsigned char hdr[96];
@@ -1002,10 +1002,8 @@ static int store_object(
return 1;
}
for (source = the_repository->objects->sources; source; source = source->next) {
struct odb_source_files *files = odb_source_files_downcast(source);
if (!packfile_list_find_oid(packfile_store_get_packs(files->packed), &oid))
for (struct odb_files_dir *dir = files->dirs; dir; dir = dir->next) {
if (!packfile_list_find_oid(packfile_store_get_packs(dir->packed), &oid))
continue;
e->type = type;
e->pack_id = MAX_PACK_ID;
@@ -1125,10 +1123,10 @@ static void truncate_pack(struct hashfile_checkpoint *checkpoint)
static void stream_blob(uintmax_t len, struct object_id *oidout, uintmax_t mark)
{
struct odb_source_files *files = odb_source_files_downcast(the_repository->objects->source);
size_t in_sz = 64 * 1024, out_sz = 64 * 1024;
unsigned char *in_buf = xmalloc(in_sz);
unsigned char *out_buf = xmalloc(out_sz);
struct odb_source *source;
struct object_entry *e;
struct object_id oid;
unsigned long hdrlen;
@@ -1212,10 +1210,8 @@ static void stream_blob(uintmax_t len, struct object_id *oidout, uintmax_t mark)
goto out;
}
for (source = the_repository->objects->sources; source; source = source->next) {
struct odb_source_files *files = odb_source_files_downcast(source);
if (!packfile_list_find_oid(packfile_store_get_packs(files->packed), &oid))
for (struct odb_files_dir *dir = files->dirs; dir; dir = dir->next) {
if (!packfile_list_find_oid(packfile_store_get_packs(dir->packed), &oid))
continue;
e->type = OBJ_BLOB;
e->pack_id = MAX_PACK_ID;
+3 -1
View File
@@ -15,6 +15,7 @@
#include "refspec.h"
#include "object-name.h"
#include "odb.h"
#include "odb/source.h"
#include "oidset.h"
#include "oid-array.h"
#include "commit.h"
@@ -2900,7 +2901,8 @@ int cmd_fetch(int argc,
commit_graph_flags |= COMMIT_GRAPH_WRITE_PROGRESS;
trace2_region_enter("fetch", "write-commit-graph", the_repository);
write_commit_graph_reachable(the_repository->objects->sources,
write_commit_graph_reachable(the_repository,
the_repository->objects->source->path,
commit_graph_flags,
NULL);
trace2_region_leave("fetch", "write-commit-graph", the_repository);
+3 -3
View File
@@ -868,7 +868,6 @@ int cmd_fsck(int argc,
OPT_BOOL(0, "references", &check_references, N_("check reference database consistency")),
OPT_END(),
};
struct odb_source *source;
struct snapshot snap = {
.nr = 0,
.alloc = 0,
@@ -983,13 +982,14 @@ int cmd_fsck(int argc,
check_connectivity(repo);
if (repo->settings.core_commit_graph) {
struct odb_source_files *files = odb_source_files_downcast(repo->objects->source);
struct child_process commit_graph_verify = CHILD_PROCESS_INIT;
for (source = repo->objects->sources; source; source = source->next) {
for (struct odb_files_dir *dir = files->dirs; dir; dir = dir->next) {
child_process_init(&commit_graph_verify);
commit_graph_verify.git_cmd = 1;
strvec_pushl(&commit_graph_verify.args, "commit-graph",
"verify", "--object-dir", source->path, NULL);
"verify", "--object-dir", dir->abspath, NULL);
if (show_progress)
strvec_push(&commit_graph_verify.args, "--progress");
else
+8 -7
View File
@@ -733,7 +733,8 @@ int cmd_gc(int argc,
}
if (the_repository->settings.gc_write_commit_graph == 1)
write_commit_graph_reachable(the_repository->objects->sources,
write_commit_graph_reachable(the_repository,
the_repository->objects->source->path,
!opts.quiet && !daemonized ? COMMIT_GRAPH_WRITE_PROGRESS : 0,
NULL);
@@ -997,7 +998,7 @@ static int loose_object_auto_condition(struct gc_config *cfg UNUSED)
if (loose_object_auto_limit < 0)
return 1;
return for_each_loose_file_in_source(the_repository->objects->sources,
return for_each_loose_file_in_source(the_repository->objects->source,
loose_object_count,
NULL, NULL, &count);
}
@@ -1032,7 +1033,7 @@ static int pack_loose(struct maintenance_run_opts *opts)
* Do not start pack-objects process
* if there are no loose objects.
*/
if (!for_each_loose_file_in_source(r->objects->sources,
if (!for_each_loose_file_in_source(r->objects->source,
bail_on_loose,
NULL, NULL, NULL))
return 0;
@@ -1044,7 +1045,7 @@ static int pack_loose(struct maintenance_run_opts *opts)
strvec_push(&pack_proc.args, "--quiet");
else
strvec_push(&pack_proc.args, "--no-quiet");
strvec_pushf(&pack_proc.args, "%s/pack/loose", r->objects->sources->path);
strvec_pushf(&pack_proc.args, "%s/pack/loose", r->objects->source->path);
pack_proc.in = -1;
@@ -1072,7 +1073,7 @@ static int pack_loose(struct maintenance_run_opts *opts)
else if (data.batch_size > 0)
data.batch_size--; /* Decrease for equality on limit. */
for_each_loose_file_in_source(r->objects->sources,
for_each_loose_file_in_source(r->objects->source,
write_loose_object_to_stdin,
NULL, NULL, &data);
@@ -1395,7 +1396,7 @@ static int maintenance_run_tasks(struct maintenance_run_opts *opts,
int result = 0;
struct lock_file lk;
struct repository *r = the_repository;
char *lock_path = xstrfmt("%s/maintenance", r->objects->sources->path);
char *lock_path = xstrfmt("%s/maintenance", r->objects->source->path);
enum auto_gc_hook_result auto_gc_hook_result = AUTO_GC_HOOK_UNDECIDED;
if (repo_hold_lock_file_for_update(r, &lk, lock_path, LOCK_NO_DEREF) < 0) {
@@ -2971,7 +2972,7 @@ static int update_background_schedule(const struct maintenance_start_opts *opts,
unsigned int i;
int result = 0;
struct lock_file lk;
char *lock_path = xstrfmt("%s/schedule", the_repository->objects->sources->path);
char *lock_path = xstrfmt("%s/schedule", the_repository->objects->source->path);
if (hold_lock_file_for_update(&lk, lock_path, LOCK_NO_DEREF) < 0) {
if (errno == EEXIST)
+2 -2
View File
@@ -1640,8 +1640,8 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
if (do_fsck_object && startup_info->have_repository) {
struct odb_source_files *files =
odb_source_files_downcast(the_repository->objects->sources);
packfile_store_load_pack(files->packed, final_index_name, 0);
odb_source_files_downcast(the_repository->objects->source);
packfile_store_load_pack(files->dirs->packed, final_index_name, 0);
}
if (!from_stdin) {
+1 -1
View File
@@ -1863,7 +1863,7 @@ int cmd_merge(int argc,
if (squash) {
finish(head_commit, remoteheads, NULL, NULL);
git_test_write_commit_graph_or_die(the_repository->objects->sources);
git_test_write_commit_graph_or_die(the_repository);
} else
write_merge_state(remoteheads);
+24 -24
View File
@@ -80,19 +80,19 @@ static int parse_object_dir(const struct option *opt, const char *arg,
char **value = opt->value;
free(*value);
if (unset)
*value = xstrdup(the_repository->objects->sources->path);
*value = xstrdup(the_repository->objects->source->path);
else
*value = real_pathdup(arg, 1);
return 0;
}
static struct odb_source_files *handle_object_dir_option(struct repository *repo)
static struct odb_source_packed *handle_object_dir_option(struct repository *repo)
{
struct odb_source *source = odb_find_source(repo->objects, opts.object_dir);
if (!source)
struct odb_files_dir *dir = odb_source_files_find_dir(repo->objects, opts.object_dir);
if (!dir)
die(_("object directory is not an alternate of the current repository: '%s'"),
opts.object_dir);
return odb_source_files_downcast(source);
return dir->packed;
}
static struct option common_opts[] = {
@@ -169,7 +169,7 @@ static int cmd_multi_pack_index_write(int argc, const char **argv,
N_("refs snapshot for selecting bitmap commits")),
OPT_END(),
};
struct odb_source_files *source;
struct odb_source_packed *packed_source;
int ret;
opts.flags |= MIDX_WRITE_BITMAP_HASH_CACHE;
@@ -204,7 +204,7 @@ static int cmd_multi_pack_index_write(int argc, const char **argv,
options);
}
source = handle_object_dir_option(repo);
packed_source = handle_object_dir_option(repo);
FREE_AND_NULL(options);
@@ -213,7 +213,7 @@ static int cmd_multi_pack_index_write(int argc, const char **argv,
read_packs_from_stdin(&packs);
ret = write_midx_file_only(source->packed, &packs,
ret = write_midx_file_only(packed_source, &packs,
opts.preferred_pack,
opts.refs_snapshot,
opts.incremental_base, opts.flags);
@@ -225,7 +225,7 @@ static int cmd_multi_pack_index_write(int argc, const char **argv,
}
ret = write_midx_file(source->packed, opts.preferred_pack,
ret = write_midx_file(packed_source, opts.preferred_pack,
opts.refs_snapshot, opts.flags);
free(opts.refs_snapshot);
@@ -239,7 +239,7 @@ static int cmd_multi_pack_index_compact(int argc, const char **argv,
struct multi_pack_index *m, *cur;
struct multi_pack_index *from_midx = NULL;
struct multi_pack_index *to_midx = NULL;
struct odb_source_files *source;
struct odb_source_packed *packed_source;
int ret;
struct option *options;
@@ -280,11 +280,11 @@ static int cmd_multi_pack_index_compact(int argc, const char **argv,
options);
}
source = handle_object_dir_option(the_repository);
packed_source = handle_object_dir_option(the_repository);
FREE_AND_NULL(options);
m = get_multi_pack_index(source->packed);
m = get_multi_pack_index(packed_source);
for (cur = m; cur && !(from_midx && to_midx); cur = cur->base_midx) {
const char *midx_csum = midx_get_checksum_hex(cur);
@@ -307,7 +307,7 @@ static int cmd_multi_pack_index_compact(int argc, const char **argv,
die(_("MIDX %s must be an ancestor of %s"), argv[0], argv[1]);
}
ret = write_midx_file_compact(source->packed, from_midx, to_midx,
ret = write_midx_file_compact(packed_source, from_midx, to_midx,
opts.incremental_base, opts.flags);
return ret;
@@ -321,7 +321,7 @@ static int cmd_multi_pack_index_verify(int argc, const char **argv,
static struct option builtin_multi_pack_index_verify_options[] = {
OPT_END(),
};
struct odb_source_files *source;
struct odb_source_packed *packed_source;
options = add_common_options(builtin_multi_pack_index_verify_options);
@@ -335,11 +335,11 @@ static int cmd_multi_pack_index_verify(int argc, const char **argv,
if (argc)
usage_with_options(builtin_multi_pack_index_verify_usage,
options);
source = handle_object_dir_option(the_repository);
packed_source = handle_object_dir_option(the_repository);
FREE_AND_NULL(options);
return verify_midx_file(source->packed, opts.flags);
return verify_midx_file(packed_source, opts.flags);
}
static int cmd_multi_pack_index_expire(int argc, const char **argv,
@@ -350,7 +350,7 @@ static int cmd_multi_pack_index_expire(int argc, const char **argv,
static struct option builtin_multi_pack_index_expire_options[] = {
OPT_END(),
};
struct odb_source_files *source;
struct odb_source_packed *packed_source;
options = add_common_options(builtin_multi_pack_index_expire_options);
@@ -364,11 +364,11 @@ static int cmd_multi_pack_index_expire(int argc, const char **argv,
if (argc)
usage_with_options(builtin_multi_pack_index_expire_usage,
options);
source = handle_object_dir_option(the_repository);
packed_source = handle_object_dir_option(the_repository);
FREE_AND_NULL(options);
return expire_midx_packs(source->packed, opts.flags);
return expire_midx_packs(packed_source, opts.flags);
}
static int cmd_multi_pack_index_repack(int argc, const char **argv,
@@ -381,7 +381,7 @@ static int cmd_multi_pack_index_repack(int argc, const char **argv,
N_("during repack, collect pack-files of smaller size into a batch that is larger than this size")),
OPT_END(),
};
struct odb_source_files *source;
struct odb_source_packed *packed_source;
options = add_common_options(builtin_multi_pack_index_repack_options);
@@ -396,11 +396,11 @@ static int cmd_multi_pack_index_repack(int argc, const char **argv,
if (argc)
usage_with_options(builtin_multi_pack_index_repack_usage,
options);
source = handle_object_dir_option(the_repository);
packed_source = handle_object_dir_option(the_repository);
FREE_AND_NULL(options);
return midx_repack(source->packed, (size_t)opts.batch_size, opts.flags);
return midx_repack(packed_source, (size_t)opts.batch_size, opts.flags);
}
int cmd_multi_pack_index(int argc,
@@ -426,8 +426,8 @@ int cmd_multi_pack_index(int argc,
if (the_repository &&
the_repository->objects &&
the_repository->objects->sources)
opts.object_dir = xstrdup(the_repository->objects->sources->path);
the_repository->objects->source)
opts.object_dir = xstrdup(the_repository->objects->source->path);
argc = parse_options(argc, argv, prefix, options,
builtin_multi_pack_index_usage, 0);
+28 -38
View File
@@ -1566,11 +1566,10 @@ static int want_cruft_object_mtime(struct repository *r,
const struct object_id *oid,
unsigned flags, uint32_t mtime)
{
struct odb_source *source;
struct odb_source_files *files = odb_source_files_downcast(r->objects->source);
for (source = r->objects->sources; source; source = source->next) {
struct odb_source_files *files = odb_source_files_downcast(source);
struct packed_git **cache = packfile_store_get_kept_pack_cache(files->packed, flags);
for (struct odb_files_dir *dir = files->dirs; dir; dir = dir->next) {
struct packed_git **cache = packfile_store_get_kept_pack_cache(dir->packed, flags);
for (; *cache; cache++) {
struct packed_git *p = *cache;
@@ -1753,21 +1752,19 @@ static int want_object_in_pack_mtime(const struct object_id *oid,
off_t *found_offset,
uint32_t found_mtime)
{
struct odb_source_files *files =
odb_source_files_downcast(the_repository->objects->source);
int want;
struct packfile_list_entry *e;
struct odb_source *source;
if (!exclude && local) {
/*
* Note that we start iterating at `sources->next` so that we
* skip the local object source.
* Note that we start iterating at `dirs->next` so that we
* skip the local object directory.
*/
struct odb_source *source = the_repository->objects->sources->next;
for (; source; source = source->next) {
struct odb_source_files *files = odb_source_files_downcast(source);
if (!odb_source_read_object_info(&files->loose->base, oid, NULL, 0, NULL))
for (struct odb_files_dir *dir = files->dirs->next; dir; dir = dir->next)
if (!odb_source_read_object_info(&dir->loose->base, oid, NULL, 0, NULL))
return 0;
}
}
/*
@@ -1785,9 +1782,8 @@ static int want_object_in_pack_mtime(const struct object_id *oid,
*found_offset = 0;
}
for (source = the_repository->objects->sources; source; source = source->next) {
struct odb_source_files *files = odb_source_files_downcast(source);
struct multi_pack_index *m = get_multi_pack_index(files->packed);
for (struct odb_files_dir *dir = files->dirs; dir; dir = dir->next) {
struct multi_pack_index *m = get_multi_pack_index(dir->packed);
struct pack_entry e;
if (m && midx_fill_entry(m, oid, &e, NULL) == MIDX_FILL_HIT) {
@@ -1797,14 +1793,12 @@ static int want_object_in_pack_mtime(const struct object_id *oid,
}
}
for (source = the_repository->objects->sources; source; source = source->next) {
struct odb_source_files *files = odb_source_files_downcast(source);
for (e = files->packed->packs.head; e; e = e->next) {
for (struct odb_files_dir *dir = files->dirs; dir; dir = dir->next) {
for (e = dir->packed->packs.head; e; e = e->next) {
struct packed_git *p = e->pack;
want = want_object_in_pack_one(p, oid, exclude, found_pack, found_offset, found_mtime);
if (!exclude && want > 0)
packfile_list_prepend(&files->packed->packs, p);
packfile_list_prepend(&dir->packed->packs, p);
if (want != -1)
return want;
}
@@ -4170,14 +4164,13 @@ static void add_cruft_object_entry(const struct object_id *oid, enum object_type
if (!want_object_in_pack_mtime(oid, 0, &pack, &offset, mtime))
return;
if (!pack && type == OBJ_BLOB) {
struct odb_source *source = the_repository->objects->sources;
struct odb_source_files *files =
odb_source_files_downcast(the_repository->objects->source);
int found = 0;
for (; !found && source; source = source->next) {
struct odb_source_files *files = odb_source_files_downcast(source);
if (!odb_source_read_object_info(&files->loose->base, oid, NULL, 0, NULL))
for (struct odb_files_dir *dir = files->dirs; !found && dir; dir = dir->next)
if (!odb_source_read_object_info(&dir->loose->base, oid, NULL, 0, NULL))
found = 1;
}
/*
* If a traversed tree has a missing blob then we want
@@ -4512,7 +4505,8 @@ static int add_object_in_unpacked_pack(const struct object_id *oid,
static void add_objects_in_unpacked_packs(void)
{
struct odb_source *source;
struct odb_source_files *files =
odb_source_files_downcast(to_pack.repo->objects->source);
time_t mtime;
struct odb_for_each_object_options opts = {
.flags = ODB_FOR_EACH_OBJECT_PACK_ORDER |
@@ -4526,13 +4520,11 @@ static void add_objects_in_unpacked_packs(void)
.source_infop = &source_info,
};
for (source = to_pack.repo->objects->sources; source; source = source->next) {
struct odb_source_files *files = odb_source_files_downcast(source);
if (!source->local)
for (struct odb_files_dir *dir = files->dirs; dir; dir = dir->next) {
if (!dir->local)
continue;
if (odb_source_for_each_object(&files->packed->base, &oi,
if (odb_source_for_each_object(&dir->packed->base, &oi,
add_object_in_unpacked_pack, NULL, &opts))
die(_("cannot open pack index"));
}
@@ -4576,7 +4568,7 @@ static int add_loose_object(const struct object_id *oid, const char *path,
*/
static void add_unreachable_loose_objects(struct rev_info *revs)
{
for_each_loose_file_in_source(the_repository->objects->sources,
for_each_loose_file_in_source(the_repository->objects->source,
add_loose_object, NULL, NULL, revs);
}
@@ -4640,11 +4632,9 @@ static int force_object_loose(struct odb_source *source,
size_t len;
int ret;
for (struct odb_source *s = source->odb->sources; s; s = s->next) {
struct odb_source_files *files = odb_source_files_downcast(s);
if (!odb_source_read_object_info(&files->loose->base, oid, NULL, 0, NULL))
for (struct odb_files_dir *dir = files->dirs; dir; dir = dir->next)
if (!odb_source_read_object_info(&dir->loose->base, oid, NULL, 0, NULL))
return 0;
}
oi.typep = &type;
oi.sizep = &len;
@@ -4664,7 +4654,7 @@ static int force_object_loose(struct odb_source *source,
compat_oid_p = &compat_oid;
}
ret = odb_source_write_object(&files->loose->base, buf, len, type, oid,
ret = odb_source_write_object(&files->dirs->loose->base, buf, len, type, oid,
compat_oid_p, mtime, 0);
out:
@@ -4691,7 +4681,7 @@ static void loosen_unused_packed_objects(void)
if (!packlist_find(&to_pack, &oid) &&
!has_sha1_pack_kept_or_nonlocal(&oid) &&
!loosened_object_can_be_discarded(&oid, p->mtime)) {
if (force_object_loose(the_repository->objects->sources,
if (force_object_loose(the_repository->objects->source,
&oid, &p->mtime))
die(_("unable to force loose object"));
loosened_objects_nr++;
+1 -1
View File
@@ -198,7 +198,7 @@ int cmd_prune(int argc,
revs.exclude_promisor_objects = 1;
}
for_each_loose_file_in_source(repo->objects->sources,
for_each_loose_file_in_source(repo->objects->source,
prune_object, prune_cruft, prune_subdir, &revs);
prune_packed_objects(show_only ? PRUNE_PACKED_DRY_RUN : 0);
+2 -2
View File
@@ -617,7 +617,7 @@ int cmd_repack(int argc,
* midx_has_unknown_packs() will make the decision for
* us.
*/
if (!get_multi_pack_index(files->packed))
if (!get_multi_pack_index(files->dirs->packed))
midx_must_contain_cruft = 1;
}
@@ -775,7 +775,7 @@ int cmd_repack(int argc,
if (git_env_bool(GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL, 0))
flags |= MIDX_WRITE_INCREMENTAL;
write_midx_file(files->packed, NULL, NULL, flags);
write_midx_file(files->dirs->packed, NULL, NULL, flags);
}
cleanup:
+4 -3
View File
@@ -30,6 +30,7 @@
#include "object-name.h"
#include "odb.h"
#include "odb/source.h"
#include "odb/source-files.h"
#include "advice.h"
#include "branch.h"
#include "list-objects-filter-options.h"
@@ -1770,7 +1771,7 @@ static const char alternate_error_advice[] = N_(
);
static int add_possible_reference_from_superproject(
struct odb_source *alt_odb, void *sas_cb)
struct odb_files_dir *alt_odb, void *sas_cb)
{
struct submodule_alternate_setup *sas = sas_cb;
size_t len;
@@ -1779,12 +1780,12 @@ static int add_possible_reference_from_superproject(
* If the alternate object store is another repository, try the
* standard layout with .git/(modules/<name>)+/objects
*/
if (strip_suffix(alt_odb->path, "/objects", &len)) {
if (strip_suffix(alt_odb->abspath, "/objects", &len)) {
struct repository alternate;
char *sm_alternate;
struct strbuf sb = STRBUF_INIT;
struct strbuf err = STRBUF_INIT;
strbuf_add(&sb, alt_odb->path, len);
strbuf_add(&sb, alt_odb->abspath, len);
if (repo_init(&alternate, sb.buf, NULL) < 0)
die(_("could not get a repository handle for gitdir '%s'"),
+1 -1
View File
@@ -239,7 +239,7 @@ int verify_bundle(struct repository *r,
.quiet = 1,
};
if (!r || !r->objects || !r->objects->sources)
if (!r || !r->objects || !r->objects->source)
return error(_("need a repository to verify a bundle"));
for (i = 0; i < p->nr; i++) {
+80 -70
View File
@@ -1,6 +1,7 @@
#define DISABLE_SIGN_COMPARE_WARNINGS
#include "git-compat-util.h"
#include "abspath.h"
#include "config.h"
#include "csum-file.h"
#include "environment.h"
@@ -14,6 +15,7 @@
#include "hash-lookup.h"
#include "commit-graph.h"
#include "odb.h"
#include "odb/source-files.h"
#include "oid-array.h"
#include "path.h"
#include "alloc.h"
@@ -28,7 +30,7 @@
#include "tree.h"
#include "chunk-format.h"
void git_test_write_commit_graph_or_die(struct odb_source *source)
void git_test_write_commit_graph_or_die(struct repository *repo)
{
int flags = 0;
if (!git_env_bool(GIT_TEST_COMMIT_GRAPH, 0))
@@ -37,7 +39,7 @@ void git_test_write_commit_graph_or_die(struct odb_source *source)
if (git_env_bool(GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS, 0))
flags = COMMIT_GRAPH_WRITE_BLOOM_FILTERS;
if (write_commit_graph_reachable(source, flags, NULL))
if (write_commit_graph_reachable(repo, repo->objects->source->path, flags, NULL))
die("failed to write commit-graph under GIT_TEST_COMMIT_GRAPH");
}
@@ -196,21 +198,21 @@ static int commit_gen_cmp(const void *va, const void *vb)
return 0;
}
char *get_commit_graph_filename(struct odb_source *source)
char *get_commit_graph_filename(const char *dir)
{
return xstrfmt("%s/info/commit-graph", source->path);
return xstrfmt("%s/info/commit-graph", dir);
}
static char *get_split_graph_filename(struct odb_source *source,
static char *get_split_graph_filename(const char *dir,
const char *oid_hex)
{
return xstrfmt("%s/info/commit-graphs/graph-%s.graph", source->path,
return xstrfmt("%s/info/commit-graphs/graph-%s.graph", dir,
oid_hex);
}
char *get_commit_graph_chain_filename(struct odb_source *source)
char *get_commit_graph_chain_filename(const char *dir)
{
return xstrfmt("%s/info/commit-graphs/commit-graph-chain", source->path);
return xstrfmt("%s/info/commit-graphs/commit-graph-chain", dir);
}
static struct commit_graph *alloc_commit_graph(void)
@@ -253,7 +255,8 @@ int open_commit_graph(const char *graph_file, int *fd, struct stat *st)
return 1;
}
struct commit_graph *load_commit_graph_one_fd_st(struct odb_source *source,
struct commit_graph *load_commit_graph_one_fd_st(struct repository *repo,
const char *dir,
int fd, struct stat *st)
{
void *graph_map;
@@ -262,7 +265,7 @@ struct commit_graph *load_commit_graph_one_fd_st(struct odb_source *source,
graph_size = xsize_t(st->st_size);
if (graph_size < graph_min_size(source->odb->repo->hash_algo)) {
if (graph_size < graph_min_size(repo->hash_algo)) {
close(fd);
error(_("commit-graph file is too small"));
return NULL;
@@ -270,9 +273,9 @@ struct commit_graph *load_commit_graph_one_fd_st(struct odb_source *source,
graph_map = xmmap(NULL, graph_size, PROT_READ, MAP_PRIVATE, fd, 0);
close(fd);
ret = parse_commit_graph(source->odb->repo, graph_map, graph_size);
ret = parse_commit_graph(repo, graph_map, graph_size);
if (ret)
ret->odb_source = source;
ret->dir = absolute_pathdup(dir);
else
munmap(graph_map, graph_size);
@@ -410,6 +413,7 @@ struct commit_graph *parse_commit_graph(struct repository *r,
graph = alloc_commit_graph();
graph->repo = r;
graph->hash_algo = r->hash_algo;
graph->num_chunks = *(unsigned char*)(data + 6);
graph->data = graph_map;
@@ -490,7 +494,8 @@ free_and_return:
return NULL;
}
static struct commit_graph *load_commit_graph_one(struct odb_source *source,
static struct commit_graph *load_commit_graph_one(struct repository *repo,
const char *dir,
const char *graph_file)
{
struct stat st;
@@ -501,17 +506,18 @@ static struct commit_graph *load_commit_graph_one(struct odb_source *source,
if (!open_ok)
return NULL;
g = load_commit_graph_one_fd_st(source, fd, &st);
g = load_commit_graph_one_fd_st(repo, dir, fd, &st);
if (g)
g->filename = xstrdup(graph_file);
g->filename = absolute_pathdup(graph_file);
return g;
}
static struct commit_graph *load_commit_graph_v1(struct odb_source *source)
static struct commit_graph *load_commit_graph_v1(struct repository *repo,
const char *dir)
{
char *graph_name = get_commit_graph_filename(source);
struct commit_graph *g = load_commit_graph_one(source, graph_name);
char *graph_name = get_commit_graph_filename(dir);
struct commit_graph *g = load_commit_graph_one(repo, dir, graph_name);
free(graph_name);
return g;
@@ -652,7 +658,7 @@ struct commit_graph *load_commit_graph_chain_fd_st(struct object_database *odb,
CALLOC_ARRAY(oids, count);
for (i = 0; i < count; i++) {
struct odb_source *source;
struct odb_source_files *files;
if (strbuf_getline_lf(&line, fp) == EOF)
break;
@@ -665,9 +671,11 @@ struct commit_graph *load_commit_graph_chain_fd_st(struct object_database *odb,
}
valid = 0;
for (source = odb->sources; source; source = source->next) {
char *graph_name = get_split_graph_filename(source, line.buf);
struct commit_graph *g = load_commit_graph_one(source, graph_name);
files = odb_source_files_downcast(odb->source);
for (struct odb_files_dir *dir = files->dirs; dir; dir = dir->next) {
char *graph_name = get_split_graph_filename(dir->abspath, line.buf);
struct commit_graph *g = load_commit_graph_one(odb->repo, dir->abspath, graph_name);
free(graph_name);
@@ -700,29 +708,31 @@ struct commit_graph *load_commit_graph_chain_fd_st(struct object_database *odb,
return graph_chain;
}
static struct commit_graph *load_commit_graph_chain(struct odb_source *source)
static struct commit_graph *load_commit_graph_chain(struct repository *repo,
const char *dir)
{
char *chain_file = get_commit_graph_chain_filename(source);
char *chain_file = get_commit_graph_chain_filename(dir);
struct stat st;
int fd;
struct commit_graph *g = NULL;
if (open_commit_graph_chain(chain_file, &fd, &st, source->odb->repo->hash_algo)) {
if (open_commit_graph_chain(chain_file, &fd, &st, repo->hash_algo)) {
int incomplete;
/* ownership of fd is taken over by load function */
g = load_commit_graph_chain_fd_st(source->odb, fd, &st, &incomplete);
g = load_commit_graph_chain_fd_st(repo->objects, fd, &st, &incomplete);
}
free(chain_file);
return g;
}
struct commit_graph *read_commit_graph_one(struct odb_source *source)
struct commit_graph *read_commit_graph_one(struct repository *repo,
const char *dir)
{
struct commit_graph *g = load_commit_graph_v1(source);
struct commit_graph *g = load_commit_graph_v1(repo, dir);
if (!g)
g = load_commit_graph_chain(source);
g = load_commit_graph_chain(repo, dir);
return g;
}
@@ -735,7 +745,7 @@ struct commit_graph *read_commit_graph_one(struct odb_source *source)
*/
static struct commit_graph *prepare_commit_graph(struct repository *r)
{
struct odb_source *source;
struct odb_source_files *files;
/*
* Early return if there is no object database or if the commit graph is
@@ -766,8 +776,9 @@ static struct commit_graph *prepare_commit_graph(struct repository *r)
if (!commit_graph_compatible(r))
return NULL;
for (source = r->objects->sources; source; source = source->next) {
r->objects->commit_graph = read_commit_graph_one(source);
files = odb_source_files_downcast(r->objects->source);
for (struct odb_files_dir *dir = files->dirs; dir; dir = dir->next) {
r->objects->commit_graph = read_commit_graph_one(r, dir->abspath);
if (r->objects->commit_graph)
break;
}
@@ -866,7 +877,7 @@ static struct commit_list **insert_parent_or_die(struct commit_graph *g,
die("invalid parent position %"PRIu32, pos);
load_oid_from_graph(g, pos, &oid);
c = lookup_commit(g->odb_source->odb->repo, &oid);
c = lookup_commit(g->repo, &oid);
if (!c)
die(_("could not find commit %s"), oid_to_hex(&oid));
commit_graph_data_at(c)->graph_pos = pos;
@@ -1103,7 +1114,7 @@ static struct tree *load_tree_for_commit(struct commit_graph *g,
graph_pos - g->num_commits_in_base);
oidread(&oid, commit_data, g->hash_algo);
set_commit_tree(c, lookup_tree(g->odb_source->odb->repo, &oid));
set_commit_tree(c, lookup_tree(g->repo, &oid));
return c->maybe_tree;
}
@@ -1126,7 +1137,7 @@ struct tree *get_commit_tree_in_graph(struct repository *r, const struct commit
struct write_commit_graph_context {
struct repository *r;
struct odb_source *odb_source;
char *dir;
char *graph_name;
struct oid_array oids;
struct commit_stack commits;
@@ -1902,7 +1913,8 @@ static int add_ref_to_set(const struct reference *ref, void *cb_data)
return 0;
}
int write_commit_graph_reachable(struct odb_source *source,
int write_commit_graph_reachable(struct repository *repo,
const char *dir,
enum commit_graph_write_flags flags,
const struct commit_graph_opts *opts)
{
@@ -1911,20 +1923,20 @@ int write_commit_graph_reachable(struct odb_source *source,
int result;
memset(&data, 0, sizeof(data));
data.repo = source->odb->repo;
data.repo = repo;
data.commits = &commits;
if (flags & COMMIT_GRAPH_WRITE_PROGRESS)
data.progress = start_delayed_progress(
source->odb->repo,
repo,
_("Collecting referenced commits"), 0);
refs_for_each_ref(get_main_ref_store(source->odb->repo), add_ref_to_set,
refs_for_each_ref(get_main_ref_store(repo), add_ref_to_set,
&data);
stop_progress(&data.progress);
result = write_commit_graph(source, NULL, &commits,
result = write_commit_graph(repo, dir, NULL, &commits,
flags, opts);
oidset_clear(&commits);
@@ -1936,12 +1948,8 @@ static int fill_oids_from_packs(struct write_commit_graph_context *ctx,
{
uint32_t i;
struct strbuf progress_title = STRBUF_INIT;
struct strbuf packname = STRBUF_INIT;
int dirlen;
int ret = 0;
strbuf_addf(&packname, "%s/pack/", ctx->odb_source->path);
dirlen = packname.len;
if (ctx->report_progress) {
strbuf_addf(&progress_title,
Q_("Finding commits for commit graph in %"PRIuMAX" pack",
@@ -1954,15 +1962,15 @@ static int fill_oids_from_packs(struct write_commit_graph_context *ctx,
}
for (i = 0; i < pack_indexes->nr; i++) {
struct packed_git *p;
strbuf_setlen(&packname, dirlen);
strbuf_addstr(&packname, pack_indexes->items[i].string);
p = add_packed_git(ctx->r, packname.buf, packname.len, 1);
p = add_packed_git(ctx->r, pack_indexes->items[i].string,
strlen(pack_indexes->items[i].string), 1);
if (!p) {
ret = error(_("error adding pack %s"), packname.buf);
ret = error(_("error adding pack %s"), pack_indexes->items[i].string);
goto cleanup;
}
if (open_pack_index(p)) {
ret = error(_("error opening index for %s"), packname.buf);
ret = error(_("error opening index for %s"), pack_indexes->items[i].string);
close_pack(p);
free(p);
goto cleanup;
@@ -1976,7 +1984,6 @@ static int fill_oids_from_packs(struct write_commit_graph_context *ctx,
cleanup:
stop_progress(&ctx->progress);
strbuf_release(&progress_title);
strbuf_release(&packname);
return ret;
}
@@ -2000,7 +2007,7 @@ static int fill_oids_from_commits(struct write_commit_graph_context *ctx,
static void fill_oids_from_all_packs(struct write_commit_graph_context *ctx)
{
struct odb_source *source;
struct odb_source_files *files;
enum object_type type;
struct odb_for_each_object_options opts = {
.flags = ODB_FOR_EACH_OBJECT_PACK_ORDER,
@@ -2015,9 +2022,9 @@ static void fill_oids_from_all_packs(struct write_commit_graph_context *ctx)
_("Finding commits for commit graph among packed objects"),
ctx->approx_nr_objects);
for (source = ctx->r->objects->sources; source; source = source->next) {
struct odb_source_files *files = odb_source_files_downcast(source);
odb_source_for_each_object(&files->packed->base, &oi, add_packed_commits_oi,
files = odb_source_files_downcast(ctx->r->objects->source);
for (struct odb_files_dir *dir = files->dirs; dir; dir = dir->next) {
odb_source_for_each_object(&dir->packed->base, &oi, add_packed_commits_oi,
ctx, &opts);
}
@@ -2108,10 +2115,10 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)
strbuf_addf(&tmp_file,
"%s/info/commit-graphs/tmp_graph_XXXXXX",
ctx->odb_source->path);
ctx->dir);
ctx->graph_name = strbuf_detach(&tmp_file, NULL);
} else {
ctx->graph_name = get_commit_graph_filename(ctx->odb_source);
ctx->graph_name = get_commit_graph_filename(ctx->dir);
}
if (safe_create_leading_directories(ctx->r, ctx->graph_name)) {
@@ -2121,7 +2128,7 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)
}
if (ctx->split) {
char *lock_name = get_commit_graph_chain_filename(ctx->odb_source);
char *lock_name = get_commit_graph_chain_filename(ctx->dir);
repo_hold_lock_file_for_update_mode(ctx->r, &lk, lock_name,
LOCK_DIE_ON_ERROR, 0444);
@@ -2210,7 +2217,7 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)
if (ctx->split && ctx->base_graph_name && ctx->num_commit_graphs_after > 1) {
char *new_base_hash = xstrdup(oid_to_hex(&ctx->new_base_graph->oid));
char *new_base_name = get_split_graph_filename(ctx->new_base_graph->odb_source, new_base_hash);
char *new_base_name = get_split_graph_filename(ctx->new_base_graph->dir, new_base_hash);
free(ctx->commit_graph_filenames_after[ctx->num_commit_graphs_after - 2]);
free(ctx->commit_graph_hash_after[ctx->num_commit_graphs_after - 2]);
@@ -2250,7 +2257,7 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)
}
}
} else {
char *graph_name = get_commit_graph_filename(ctx->odb_source);
char *graph_name = get_commit_graph_filename(ctx->dir);
unlink(graph_name);
free(graph_name);
}
@@ -2258,7 +2265,7 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)
free(ctx->commit_graph_hash_after[ctx->num_commit_graphs_after - 1]);
ctx->commit_graph_hash_after[ctx->num_commit_graphs_after - 1] =
xstrdup(hash_to_hex_algop(file_hash, ctx->r->hash_algo));
final_graph_name = get_split_graph_filename(ctx->odb_source,
final_graph_name = get_split_graph_filename(ctx->dir,
ctx->commit_graph_hash_after[ctx->num_commit_graphs_after - 1]);
free(ctx->commit_graph_filenames_after[ctx->num_commit_graphs_after - 1]);
ctx->commit_graph_filenames_after[ctx->num_commit_graphs_after - 1] = final_graph_name;
@@ -2310,7 +2317,7 @@ static void split_graph_merge_strategy(struct write_commit_graph_context *ctx,
flags != COMMIT_GRAPH_SPLIT_REPLACE) {
while (g && (g->num_commits <= st_mult(size_mult, num_commits) ||
(max_commits && num_commits > max_commits))) {
if (g->odb_source != ctx->odb_source)
if (strcmp(g->dir, ctx->dir))
break;
if (unsigned_add_overflows(num_commits, g->num_commits))
@@ -2332,10 +2339,10 @@ static void split_graph_merge_strategy(struct write_commit_graph_context *ctx,
"should be 1 with --split=replace");
if (ctx->num_commit_graphs_after == 2) {
char *old_graph_name = get_commit_graph_filename(g->odb_source);
char *old_graph_name = get_commit_graph_filename(g->dir);
if (!strcmp(g->filename, old_graph_name) &&
g->odb_source != ctx->odb_source) {
strcmp(g->dir, ctx->dir)) {
ctx->num_commit_graphs_after = 1;
ctx->new_base_graph = NULL;
}
@@ -2505,13 +2512,13 @@ static void expire_commit_graphs(struct write_commit_graph_context *ctx)
if (ctx->opts && ctx->opts->expire_time)
expire_time = ctx->opts->expire_time;
if (!ctx->split) {
char *chain_file_name = get_commit_graph_chain_filename(ctx->odb_source);
char *chain_file_name = get_commit_graph_chain_filename(ctx->dir);
unlink(chain_file_name);
free(chain_file_name);
ctx->num_commit_graphs_after = 0;
}
strbuf_addstr(&path, ctx->odb_source->path);
strbuf_addstr(&path, ctx->dir);
strbuf_addstr(&path, "/info/commit-graphs");
dir = opendir(path.buf);
@@ -2553,16 +2560,15 @@ out:
strbuf_release(&path);
}
int write_commit_graph(struct odb_source *source,
int write_commit_graph(struct repository *r,
const char *dir,
const struct string_list *const pack_indexes,
struct oidset *commits,
enum commit_graph_write_flags flags,
const struct commit_graph_opts *opts)
{
struct repository *r = source->odb->repo;
struct write_commit_graph_context ctx = {
.r = r,
.odb_source = source,
.append = flags & COMMIT_GRAPH_WRITE_APPEND ? 1 : 0,
.report_progress = flags & COMMIT_GRAPH_WRITE_PROGRESS ? 1 : 0,
.split = flags & COMMIT_GRAPH_WRITE_SPLIT ? 1 : 0,
@@ -2593,6 +2599,8 @@ int write_commit_graph(struct odb_source *source,
return 0;
}
ctx.dir = absolute_pathdup(dir);
bloom_settings.hash_version = r->settings.commit_graph_changed_paths_version;
bloom_settings.bits_per_entry = git_env_ulong("GIT_TEST_BLOOM_SETTINGS_BITS_PER_ENTRY",
bloom_settings.bits_per_entry);
@@ -2715,6 +2723,7 @@ int write_commit_graph(struct odb_source *source,
cleanup:
free(ctx.graph_name);
free(ctx.base_graph_name);
free(ctx.dir);
commit_stack_clear(&ctx.commits);
oid_array_clear(&ctx.oids);
clear_topo_level_slab(&topo_levels);
@@ -2767,7 +2776,7 @@ static int verify_one_commit_graph(struct commit_graph *g,
struct progress *progress,
uint64_t *seen)
{
struct repository *r = g->odb_source->odb->repo;
struct repository *r = g->repo;
uint32_t i, cur_fanout_pos = 0;
struct object_id prev_oid, cur_oid;
struct commit *seen_gen_zero = NULL;
@@ -2931,7 +2940,7 @@ int verify_commit_graph(struct commit_graph *g, int flags)
if (!(flags & COMMIT_GRAPH_VERIFY_SHALLOW))
total += g->num_commits_in_base;
progress = start_progress(g->odb_source->odb->repo,
progress = start_progress(g->repo,
_("Verifying commits in commit graph"),
total);
}
@@ -2954,6 +2963,7 @@ void free_commit_graph(struct commit_graph *g)
if (g->data)
munmap((void *)g->data, g->data_len);
free(g->dir);
free(g->filename);
free(g->bloom_filter_settings);
free(g);
+23 -8
View File
@@ -21,7 +21,7 @@
* call this method outside of a builtin, and only if you know what
* you are doing!
*/
void git_test_write_commit_graph_or_die(struct odb_source *source);
void git_test_write_commit_graph_or_die(struct repository *repo);
struct commit;
struct bloom_filter_settings;
@@ -29,8 +29,8 @@ struct repository;
struct object_database;
struct string_list;
char *get_commit_graph_filename(struct odb_source *source);
char *get_commit_graph_chain_filename(struct odb_source *source);
char *get_commit_graph_filename(const char *dir);
char *get_commit_graph_chain_filename(const char *dir);
int open_commit_graph(const char *graph_file, int *fd, struct stat *st);
int open_commit_graph_chain(const char *chain_file, int *fd, struct stat *st,
const struct git_hash_algo *hash_algo);
@@ -85,12 +85,13 @@ struct commit_graph {
const unsigned char *data;
size_t data_len;
struct repository *repo;
const struct git_hash_algo *hash_algo;
unsigned char num_chunks;
uint32_t num_commits;
struct object_id oid;
char *dir;
char *filename;
struct odb_source *odb_source;
uint32_t num_commits_in_base;
unsigned int read_generation_data;
@@ -114,12 +115,20 @@ struct commit_graph {
struct bloom_filter_settings *bloom_filter_settings;
};
struct commit_graph *load_commit_graph_one_fd_st(struct odb_source *source,
/*
* Load commit graphs from the given object directory `dir`. The directory may
* be given as a relative path; it is canonicalized internally so that graphs
* loaded from the same directory compare equal regardless of how the caller
* spelled the path.
*/
struct commit_graph *load_commit_graph_one_fd_st(struct repository *repo,
const char *dir,
int fd, struct stat *st);
struct commit_graph *load_commit_graph_chain_fd_st(struct object_database *odb,
int fd, struct stat *st,
int *incomplete_chain);
struct commit_graph *read_commit_graph_one(struct odb_source *source);
struct commit_graph *read_commit_graph_one(struct repository *repo,
const char *dir);
struct repo_settings;
@@ -171,11 +180,17 @@ struct commit_graph_opts {
* and a negative value on failure. Note that if the repository
* is not compatible with the commit-graph feature, then the
* methods will return 0 without writing a commit-graph.
*
* The object directory `dir` may be given as a relative path; it is
* canonicalized internally so that it compares equal to the directory of
* graphs that have already been loaded.
*/
int write_commit_graph_reachable(struct odb_source *source,
int write_commit_graph_reachable(struct repository *repo,
const char *dir,
enum commit_graph_write_flags flags,
const struct commit_graph_opts *opts);
int write_commit_graph(struct odb_source *source,
int write_commit_graph(struct repository *r,
const char *dir,
const struct string_list *pack_indexes,
struct oidset *commits,
enum commit_graph_write_flags flags,
+4 -4
View File
@@ -59,13 +59,13 @@ static void dir_file_stats_objects(const char *full_path,
(uintmax_t)st.st_size);
}
static int dir_file_stats(struct odb_source *source, void *data)
static int dir_file_stats(struct odb_files_dir *source, void *data)
{
struct strbuf *buf = data;
strbuf_addf(buf, "Contents of %s:\n", source->path);
strbuf_addf(buf, "Contents of %s:\n", source->abspath);
for_each_file_in_pack_dir(source->path, dir_file_stats_objects,
for_each_file_in_pack_dir(source->abspath, dir_file_stats_objects,
data);
return 0;
@@ -228,7 +228,7 @@ int create_diagnostics_archive(struct repository *r,
strbuf_reset(&buf);
strbuf_addstr(&buf, "--add-virtual-file=packs-local.txt:");
dir_file_stats(r->objects->sources, &buf);
dir_file_stats(odb_source_files_downcast(r->objects->source)->dirs, &buf);
odb_for_each_alternate(r->objects, dir_file_stats, &buf);
strvec_push(&archiver_args, buf.buf);
+1 -1
View File
@@ -1075,7 +1075,7 @@ static int get_pack(struct fetch_pack_args *args,
die(_("fetch-pack: unable to fork off %s"), cmd_name);
if (do_keep && (pack_lockfiles || fsck_objects)) {
int is_well_formed;
char *pack_lockfile = index_pack_lockfile(the_repository->objects->sources,
char *pack_lockfile = index_pack_lockfile(the_repository->objects->source,
cmd.out,
&is_well_formed);
+2 -2
View File
@@ -540,9 +540,9 @@ static int fetch_object(struct walker *walker, const struct object_id *oid)
} else if (!oideq(&obj_req->oid, &req->real_oid)) {
ret = error("File %s has bad hash", hex);
} else if (req->rename < 0) {
struct odb_source_files *files = odb_source_files_downcast(the_repository->objects->sources);
struct odb_source_files *files = odb_source_files_downcast(the_repository->objects->source);
struct strbuf buf = STRBUF_INIT;
odb_loose_path(files->loose, &buf, &req->oid);
odb_loose_path(files->dirs->loose, &buf, &req->oid);
ret = error("unable to write sha1 filename %s", buf.buf);
strbuf_release(&buf);
}
+6 -6
View File
@@ -2757,9 +2757,9 @@ int finish_http_pack_request(struct http_pack_request *preq)
void http_install_packfile(struct packed_git *p,
struct packfile_list *list_to_remove_from)
{
struct odb_source_files *files = odb_source_files_downcast(the_repository->objects->sources);
struct odb_source_files *files = odb_source_files_downcast(the_repository->objects->source);
packfile_list_remove(list_to_remove_from, p);
packfile_store_add_pack(files->packed, p);
packfile_store_add_pack(files->dirs->packed, p);
}
struct http_pack_request *new_http_pack_request(
@@ -2885,7 +2885,7 @@ static size_t fwrite_sha1_file(char *ptr, size_t eltsize, size_t nmemb,
struct http_object_request *new_http_object_request(const char *base_url,
const struct object_id *oid)
{
struct odb_source_files *files = odb_source_files_downcast(the_repository->objects->sources);
struct odb_source_files *files = odb_source_files_downcast(the_repository->objects->source);
char *hex = oid_to_hex(oid);
struct strbuf filename = STRBUF_INIT;
struct strbuf prevfile = STRBUF_INIT;
@@ -2900,7 +2900,7 @@ struct http_object_request *new_http_object_request(const char *base_url,
oidcpy(&freq->oid, oid);
freq->localfile = -1;
odb_loose_path(files->loose, &filename, oid);
odb_loose_path(files->dirs->loose, &filename, oid);
strbuf_addf(&freq->tmpfile, "%s.temp", filename.buf);
strbuf_addf(&prevfile, "%s.prev", filename.buf);
@@ -3026,7 +3026,7 @@ void process_http_object_request(struct http_object_request *freq)
int finish_http_object_request(struct http_object_request *freq)
{
struct odb_source_files *files = odb_source_files_downcast(the_repository->objects->sources);
struct odb_source_files *files = odb_source_files_downcast(the_repository->objects->source);
struct stat st;
struct strbuf filename = STRBUF_INIT;
@@ -3053,7 +3053,7 @@ int finish_http_object_request(struct http_object_request *freq)
unlink_or_warn(freq->tmpfile.buf);
return -1;
}
odb_loose_path(files->loose, &filename, &freq->oid);
odb_loose_path(files->dirs->loose, &filename, &freq->oid);
freq->rename = finalize_object_file(the_repository, freq->tmpfile.buf, filename.buf);
strbuf_release(&filename);
+1 -2
View File
@@ -1043,10 +1043,9 @@ static int do_remerge_diff(struct rev_info *opt,
* into the alternative object store list as the primary.
*/
if (opt->remerge_diff && !opt->remerge_objdir) {
opt->remerge_objdir = tmp_objdir_create(the_repository, "remerge-diff");
opt->remerge_objdir = tmp_objdir_create(the_repository, "remerge-diff", 1);
if (!opt->remerge_objdir)
return error(_("unable to create temporary object directory"));
tmp_objdir_replace_primary_odb(opt->remerge_objdir, 1);
}
/* Setup merge options */
+8 -10
View File
@@ -113,11 +113,10 @@ err:
int repo_read_loose_object_map(struct repository *repo)
{
struct odb_source *source;
struct odb_source_files *files = odb_source_files_downcast(repo->objects->source);
for (source = repo->objects->sources; source; source = source->next) {
struct odb_source_files *files = odb_source_files_downcast(source);
if (loose_object_map_load(files->loose) < 0)
for (struct odb_files_dir *dir = files->dirs; dir; dir = dir->next) {
if (loose_object_map_load(dir->loose) < 0)
return -1;
}
@@ -126,8 +125,8 @@ int repo_read_loose_object_map(struct repository *repo)
int repo_write_loose_object_map(struct repository *repo)
{
struct odb_source_files *files = odb_source_files_downcast(repo->objects->sources);
kh_oid_map_t *map = files->loose->map->to_compat;
struct odb_source_files *files = odb_source_files_downcast(repo->objects->source);
kh_oid_map_t *map = files->dirs->loose->map->to_compat;
struct lock_file lock;
int fd;
khiter_t iter;
@@ -231,13 +230,12 @@ int repo_loose_object_map_oid(struct repository *repo,
const struct git_hash_algo *to,
struct object_id *dest)
{
struct odb_source *source;
struct odb_source_files *files = odb_source_files_downcast(repo->objects->source);
kh_oid_map_t *map;
khiter_t pos;
for (source = repo->objects->sources; source; source = source->next) {
struct odb_source_files *files = odb_source_files_downcast(source);
struct loose_object_map *loose_map = files->loose->map;
for (struct odb_files_dir *dir = files->dirs; dir; dir = dir->next) {
struct loose_object_map *loose_map = dir->loose->map;
if (!loose_map)
continue;
map = (to == repo->compat_hash_algo) ?
+17 -26
View File
@@ -835,28 +835,22 @@ void clear_incremental_midx_files_ext(struct odb_source_packed *source, const ch
void clear_midx_file(struct repository *r)
{
struct odb_source_files *files;
struct odb_source_files *files = odb_source_files_downcast(r->objects->source);
struct strbuf midx = STRBUF_INIT;
if (r->objects) {
struct odb_source *source;
for (source = r->objects->sources; source; source = source->next) {
files = odb_source_files_downcast(source);
if (files->packed->midx)
close_midx(files->packed->midx);
files->packed->midx = NULL;
}
for (struct odb_files_dir *dir = files->dirs; dir; dir = dir->next) {
if (dir->packed->midx)
close_midx(dir->packed->midx);
dir->packed->midx = NULL;
}
files = odb_source_files_downcast(r->objects->sources);
get_midx_filename(files->packed, &midx);
get_midx_filename(files->dirs->packed, &midx);
if (remove_path(midx.buf))
die(_("failed to clear multi-pack-index at %s"), midx.buf);
clear_midx_files_ext(files->packed, MIDX_EXT_BITMAP, NULL);
clear_midx_files_ext(files->packed, MIDX_EXT_REV, NULL);
clear_midx_files_ext(files->dirs->packed, MIDX_EXT_BITMAP, NULL);
clear_midx_files_ext(files->dirs->packed, MIDX_EXT_REV, NULL);
strbuf_release(&midx);
}
@@ -864,27 +858,24 @@ void clear_midx_file(struct repository *r)
void clear_incremental_midx_files(struct repository *r,
const struct strvec *keep_hashes)
{
struct odb_source_files *files;
struct odb_source *source;
struct odb_source_files *files = odb_source_files_downcast(r->objects->source);
struct strbuf chain = STRBUF_INIT;
for (source = r->objects->sources; source; source = source->next) {
files = odb_source_files_downcast(source);
if (files->packed->midx)
close_midx(files->packed->midx);
files->packed->midx = NULL;
for (struct odb_files_dir *dir = files->dirs; dir; dir = dir->next) {
if (dir->packed->midx)
close_midx(dir->packed->midx);
dir->packed->midx = NULL;
}
files = odb_source_files_downcast(r->objects->sources);
get_midx_chain_filename(files->packed, &chain);
get_midx_chain_filename(files->dirs->packed, &chain);
if (!keep_hashes && remove_path(chain.buf))
die(_("failed to clear multi-pack-index chain at %s"),
chain.buf);
clear_incremental_midx_files_ext(files->packed, MIDX_EXT_BITMAP, keep_hashes);
clear_incremental_midx_files_ext(files->packed, MIDX_EXT_REV, keep_hashes);
clear_incremental_midx_files_ext(files->packed, MIDX_EXT_MIDX, keep_hashes);
clear_incremental_midx_files_ext(files->dirs->packed, MIDX_EXT_BITMAP, keep_hashes);
clear_incremental_midx_files_ext(files->dirs->packed, MIDX_EXT_REV, keep_hashes);
clear_incremental_midx_files_ext(files->dirs->packed, MIDX_EXT_MIDX, keep_hashes);
strbuf_release(&chain);
}
+2 -6
View File
@@ -488,7 +488,6 @@ struct odb_transaction_files {
enum odb_transaction_flags flags;
struct tmp_objdir *objdir;
struct odb_source *quarantine;
struct transaction_packfile packfile;
const char *prefix;
@@ -511,12 +510,10 @@ int odb_transaction_files_prepare(struct odb_transaction *base)
if (!transaction || transaction->objdir)
return 0;
transaction->objdir = tmp_objdir_create(base->source->odb->repo, transaction->prefix);
transaction->objdir = tmp_objdir_create(base->source->odb->repo, transaction->prefix, 0);
if (!transaction->objdir)
return error(_("unable to create temporary object directory"));
transaction->quarantine = tmp_objdir_replace_primary_odb(transaction->objdir, 0);
return 0;
}
@@ -1447,8 +1444,7 @@ static int odb_transaction_files_write_pack(struct odb_transaction *base,
return -1;
}
odb_source_prepare(transaction->quarantine,
ODB_PREPARE_FLUSH_CACHES);
odb_source_prepare(base->source, ODB_PREPARE_FLUSH_CACHES);
}
return 0;
+47 -392
View File
@@ -13,10 +13,10 @@
#include "object-file.h"
#include "object-name.h"
#include "odb.h"
#include "odb/source-files.h"
#include "odb/source-inmemory.h"
#include "path.h"
#include "promisor-remote.h"
#include "quote.h"
#include "replace-object.h"
#include "run-command.h"
#include "setup.h"
@@ -27,48 +27,6 @@
#include "trace2.h"
#include "write-or-die.h"
/*
* NEEDSWORK: we're using "core.ignoreCase" to deduplicate alternates that
* _may_ be the same. This requires quite a bit of boilerplate for dubious
* benefit:
*
* - Duplicating alternates should really only lead to regressed performance.
*
* - We don't properly resolve symlinks or mointpoints, so we may still end
* up duplicating alternates.
*
* - The value may be lying, in which case we might deduplicate alternates
* that are in fact not mapping to the same directory.
*
* We should investigate whether we can remove this whole mechanism outright.
*/
static int odb_source_paths_cmp(struct object_database *o,
const char *a, const char *b)
{
if (o->source_paths_icase < 0) {
int icase = 0;
repo_config_get_bool(o->repo, "core.ignorecase", &icase);
o->source_paths_icase = icase;
}
return o->source_paths_icase ? strcasecmp(a, b) : strcmp(a, b);
}
static int odb_source_by_path_cmp(const void *cb_data,
const struct hashmap_entry *entry,
const struct hashmap_entry *entry_or_key,
const void *keydata)
{
struct object_database *o = (struct object_database *)cb_data;
const struct odb_source *source = container_of(entry, const struct odb_source, by_path_entry);
const char *path = keydata;
if (!path)
path = container_of(entry_or_key, const struct odb_source, by_path_entry)->path;
return odb_source_paths_cmp(o, source->path, path);
}
int odb_mkstemp(struct object_database *odb,
struct strbuf *temp_filename, const char *pattern)
{
@@ -90,199 +48,6 @@ int odb_mkstemp(struct object_database *odb,
return xmkstemp_mode(temp_filename->buf, mode);
}
/*
* Return non-zero iff the path is usable as an alternate object database.
*/
static bool odb_is_source_usable(struct object_database *o, const char *path)
{
struct strbuf normalized_objdir = STRBUF_INIT;
struct hashmap_entry key;
bool usable = false;
strbuf_realpath(&normalized_objdir, o->sources->path, 1);
/* Detect cases where alternate disappeared */
if (!is_directory(path)) {
error(_("object directory %s does not exist; "
"check .git/objects/info/alternates"),
path);
goto out;
}
/*
* Prevent the common mistake of listing the same
* thing twice, or object directory itself.
*/
if (!hashmap_get_size(&o->source_by_path)) {
assert(!o->sources->next);
hashmap_entry_init(&o->sources->by_path_entry,
strihash(o->sources->path));
hashmap_add(&o->source_by_path, &o->sources->by_path_entry);
}
if (!odb_source_paths_cmp(o, path, normalized_objdir.buf))
goto out;
hashmap_entry_init(&key, strihash(path));
if (hashmap_get(&o->source_by_path, &key, path))
goto out;
usable = true;
out:
strbuf_release(&normalized_objdir);
return usable;
}
void parse_alternates(const char *string,
int sep,
const char *relative_base,
struct strvec *out)
{
struct strbuf pathbuf = STRBUF_INIT;
struct strbuf buf = STRBUF_INIT;
if (!string || !*string)
return;
while (*string) {
const char *end;
strbuf_reset(&buf);
strbuf_reset(&pathbuf);
if (*string == '#') {
/* comment; consume up to next separator */
end = strchrnul(string, sep);
} else if (*string == '"' && !unquote_c_style(&buf, string, &end)) {
/*
* quoted path; unquote_c_style has copied the
* data for us and set "end". Broken quoting (e.g.,
* an entry that doesn't end with a quote) falls
* back to the unquoted case below.
*/
} else {
/* normal, unquoted path */
end = strchrnul(string, sep);
strbuf_add(&buf, string, end - string);
}
if (*end)
end++;
string = end;
if (!buf.len)
continue;
if (!is_absolute_path(buf.buf) && relative_base) {
strbuf_realpath(&pathbuf, relative_base, 1);
strbuf_addch(&pathbuf, '/');
}
strbuf_addbuf(&pathbuf, &buf);
strbuf_reset(&buf);
if (!strbuf_realpath(&buf, pathbuf.buf, 0)) {
error(_("unable to normalize alternate object path: %s"),
pathbuf.buf);
continue;
}
/*
* The trailing slash after the directory name is given by
* this function at the end. Remove duplicates.
*/
while (buf.len && buf.buf[buf.len - 1] == '/')
strbuf_setlen(&buf, buf.len - 1);
strvec_push(out, buf.buf);
}
strbuf_release(&pathbuf);
strbuf_release(&buf);
}
static struct odb_source *odb_add_alternate_recursively(struct object_database *odb,
const char *source,
int depth)
{
struct odb_source *alternate = NULL;
struct strvec sources = STRVEC_INIT;
if (!odb_is_source_usable(odb, source))
goto error;
alternate = odb_source_new(odb, source, false);
/* add the alternate entry */
*odb->sources_tail = alternate;
odb->sources_tail = &(alternate->next);
hashmap_entry_init(&alternate->by_path_entry, strihash(alternate->path));
if (hashmap_get(&odb->source_by_path, &alternate->by_path_entry,
alternate->path))
BUG("source must not yet exist");
hashmap_add(&odb->source_by_path, &alternate->by_path_entry);
/* recursively add alternates */
odb_source_read_alternates(alternate, &sources);
if (sources.nr && depth + 1 > 5) {
error(_("%s: ignoring alternate object stores, nesting too deep"),
source);
} else {
for (size_t i = 0; i < sources.nr; i++)
odb_add_alternate_recursively(odb, sources.v[i], depth + 1);
}
error:
strvec_clear(&sources);
return alternate;
}
struct odb_source *odb_set_temporary_primary_source(struct object_database *odb,
const char *dir, int will_destroy,
struct odb_source **prev_source)
{
struct odb_source *source;
/*
* Make a new primary odb and link the old primary ODB in as an
* alternate
*/
source = odb_source_new(odb, dir, false);
/*
* Disable ref updates while a temporary odb is active, since
* the objects in the database may roll back.
*/
odb->repo->disable_ref_updates = true;
source->will_destroy = will_destroy;
source->next = odb->sources;
odb->sources = source;
if (prev_source)
*prev_source = source->next;
return source;
}
void odb_restore_primary_source(struct object_database *odb,
struct odb_source *restore_source,
const char *old_path)
{
struct odb_source *cur_source = odb->sources;
if (strcmp(old_path, cur_source->path))
BUG("expected %s as primary object store; found %s",
old_path, cur_source->path);
if (cur_source->next != restore_source)
BUG("we expect the old primary object store to be the first alternate");
odb->repo->disable_ref_updates = false;
odb->sources = restore_source;
odb_source_free(cur_source);
}
char *compute_alternate_path(const char *path, struct strbuf *err)
{
char *ref_git = NULL;
@@ -347,32 +112,6 @@ out:
return ref_git;
}
struct odb_source *odb_find_source(struct object_database *odb, const char *obj_dir)
{
struct odb_source *source;
char *obj_dir_real = real_pathdup(obj_dir, 1);
struct strbuf odb_path_real = STRBUF_INIT;
for (source = odb->sources; source; source = source->next) {
strbuf_realpath(&odb_path_real, source->path, 1);
if (!strcmp(obj_dir_real, odb_path_real.buf))
break;
}
free(obj_dir_real);
strbuf_release(&odb_path_real);
return source;
}
struct odb_source *odb_find_source_or_die(struct object_database *odb, const char *obj_dir)
{
struct odb_source *source = odb_find_source(odb, obj_dir);
if (!source)
die(_("could not find object directory matching %s"), obj_dir);
return source;
}
static void fill_alternate_refs_command(struct repository *repo,
struct child_process *cmd,
const char *repo_path)
@@ -435,18 +174,19 @@ static void read_alternate_refs(struct repository *repo,
}
struct alternate_refs_data {
struct repository *repo;
odb_for_each_alternate_ref_fn *fn;
void *payload;
};
static int refs_from_alternate_cb(struct odb_source *alternate,
static int refs_from_alternate_cb(struct odb_files_dir *alternate,
void *payload)
{
struct strbuf path = STRBUF_INIT;
size_t base_len;
struct alternate_refs_data *cb = payload;
if (!strbuf_realpath(&path, alternate->path, 0))
if (!strbuf_realpath(&path, alternate->abspath, 0))
goto out;
if (!strbuf_strip_suffix(&path, "/objects"))
goto out;
@@ -458,7 +198,7 @@ static int refs_from_alternate_cb(struct odb_source *alternate,
goto out;
strbuf_setlen(&path, base_len);
read_alternate_refs(alternate->odb->repo, path.buf, cb->fn, cb->payload);
read_alternate_refs(cb->repo, path.buf, cb->fn, cb->payload);
out:
strbuf_release(&path);
@@ -468,43 +208,33 @@ out:
void odb_for_each_alternate_ref(struct object_database *odb,
odb_for_each_alternate_ref_fn cb, void *payload)
{
struct alternate_refs_data data;
data.fn = cb;
data.payload = payload;
struct alternate_refs_data data = {
.fn = cb,
.payload = payload,
.repo = odb->repo,
};
odb_for_each_alternate(odb, refs_from_alternate_cb, &data);
}
int odb_for_each_alternate(struct object_database *odb,
odb_for_each_alternate_fn cb, void *payload)
{
struct odb_source *alternate;
struct odb_source_files *files = odb_source_files_downcast(odb->source);
int r = 0;
for (alternate = odb->sources->next; alternate; alternate = alternate->next) {
r = cb(alternate, payload);
for (struct odb_files_dir *dir = files->dirs->next; dir; dir = dir->next) {
r = cb(dir, payload);
if (r)
break;
}
return r;
}
static void odb_prepare_alternates(struct object_database *odb,
const char *alternate_db)
{
struct strvec sources = STRVEC_INIT;
parse_alternates(alternate_db, PATH_SEP, NULL, &sources);
odb_source_read_alternates(odb->sources, &sources);
for (size_t i = 0; i < sources.nr; i++)
odb_add_alternate_recursively(odb, sources.v[i], 0);
strvec_clear(&sources);
}
int odb_has_alternates(struct object_database *odb)
{
return !!odb->sources->next;
if (odb->source->type != ODB_SOURCE_FILES)
return 0;
return !!odb_source_files_downcast(odb->source)->dirs->next;
}
int obj_read_use_lock = 0;
@@ -548,16 +278,12 @@ static enum odb_read_status do_oid_object_info_extended(struct object_database *
return 0;
while (1) {
struct odb_source *source;
for (source = odb->sources; source; source = source->next) {
ret = odb_source_read_object_info(source, real, oi, flags,
corrupt_err.len ? NULL : &corrupt_err);
if (!ret)
goto out;
if (ret != ODB_READ_NOT_FOUND)
corrupt = true;
}
ret = odb_source_read_object_info(odb->source, real, oi, flags,
corrupt_err.len ? NULL : &corrupt_err);
if (!ret)
goto out;
if (ret != ODB_READ_NOT_FOUND)
corrupt = true;
/*
* When the object hasn't been found we try a second read and
@@ -565,15 +291,13 @@ static enum odb_read_status do_oid_object_info_extended(struct object_database *
* caches or reload on-disk state.
*/
if (!(flags & OBJECT_INFO_QUICK)) {
for (source = odb->sources; source; source = source->next) {
ret = odb_source_read_object_info(source, real, oi,
flags | OBJECT_INFO_SECOND_READ,
corrupt_err.len ? NULL : &corrupt_err);
if (!ret)
goto out;
if (ret != ODB_READ_NOT_FOUND)
corrupt = true;
}
ret = odb_source_read_object_info(odb->source, real, oi,
flags | OBJECT_INFO_SECOND_READ,
corrupt_err.len ? NULL : &corrupt_err);
if (!ret)
goto out;
if (ret != ODB_READ_NOT_FOUND)
corrupt = true;
}
/* Check if it is a missing object */
@@ -815,11 +539,7 @@ int odb_has_object(struct object_database *odb, const struct object_id *oid,
int odb_freshen_object(struct object_database *odb,
const struct object_id *oid)
{
struct odb_source *source;
for (source = odb->sources; source; source = source->next)
if (odb_source_freshen_object(source, oid, NULL))
return 1;
return 0;
return odb_source_freshen_object(odb->source, oid, NULL);
}
int odb_for_each_object_ext(struct object_database *odb,
@@ -828,18 +548,7 @@ int odb_for_each_object_ext(struct object_database *odb,
void *cb_data,
const struct odb_for_each_object_options *opts)
{
int ret;
for (struct odb_source *source = odb->sources; source; source = source->next) {
if (opts->flags & ODB_FOR_EACH_OBJECT_LOCAL_ONLY && !source->local)
continue;
ret = odb_source_for_each_object(source, request, cb, cb_data, opts);
if (ret)
return ret;
}
return 0;
return odb_source_for_each_object(odb->source, request, cb, cb_data, opts);
}
int odb_for_each_object(struct object_database *odb,
@@ -858,7 +567,6 @@ int odb_count_objects(struct object_database *odb,
enum odb_count_objects_flags flags,
unsigned long *out)
{
struct odb_source *source;
unsigned long count = 0;
int ret;
@@ -867,15 +575,9 @@ int odb_count_objects(struct object_database *odb,
return 0;
}
for (source = odb->sources; source; source = source->next) {
unsigned long c;
ret = odb_source_count_objects(source, flags, &c);
if (ret < 0)
goto out;
count += c;
}
ret = odb_source_count_objects(odb->source, flags, &count);
if (ret < 0)
goto out;
odb->object_count = count;
odb->object_count_valid = 1;
@@ -946,13 +648,7 @@ int odb_find_abbrev_len(struct object_database *odb,
goto out;
}
for (struct odb_source *source = odb->sources; source; source = source->next) {
ret = odb_source_find_abbrev_len(source, oid, len, &len);
if (ret)
goto out;
}
ret = 0;
ret = odb_source_find_abbrev_len(odb->source, oid, len, &len);
*out = len;
out:
@@ -1008,7 +704,7 @@ int odb_write_object_ext(struct object_database *odb,
compat_oid_p = &compat_oid;
}
return odb_source_write_object(odb->sources, buf, len, type,
return odb_source_write_object(odb->source, buf, len, type,
oid, compat_oid_p, NULL, flags);
}
@@ -1016,19 +712,19 @@ int odb_write_object_stream(struct object_database *odb,
struct odb_stream *stream,
struct object_id *oid)
{
return odb_source_write_object_stream(odb->sources, stream, oid);
return odb_source_write_object_stream(odb->source, stream, oid);
}
int odb_optimize(struct object_database *odb,
const struct odb_optimize_options *opts)
{
return odb_source_optimize(odb->sources, opts);
return odb_source_optimize(odb->source, opts);
}
bool odb_optimize_required(struct object_database *odb,
const struct odb_optimize_options *opts)
{
return odb_source_optimize_required(odb->sources, opts);
return odb_source_optimize_required(odb->source, opts);
}
void odb_generate_pack_options_release(struct odb_generate_pack_options *opts)
@@ -1042,9 +738,9 @@ int odb_generate_pack(struct object_database *odb,
struct odb_pack_generator **out,
const struct odb_generate_pack_options *opts)
{
if (!odb->sources->generate_pack)
if (!odb->source->generate_pack)
return error(_("primary object source does not support generating packfiles"));
return odb_source_generate_pack(odb->sources, out, opts);
return odb_source_generate_pack(odb->source, out, opts);
}
int odb_pack_generator_finish(struct odb_pack_generator *generator)
@@ -1055,55 +751,29 @@ int odb_pack_generator_finish(struct odb_pack_generator *generator)
struct object_database *odb_new(struct repository *repo,
enum odb_new_flags flags)
{
char *primary_source = NULL, *secondary_sources = NULL;
struct object_database *o;
CALLOC_ARRAY(o, 1);
o->repo = repo;
pthread_mutex_init(&o->replace_mutex, NULL);
hashmap_init(&o->source_by_path, odb_source_by_path_cmp, o, 0);
o->source_paths_icase = -1;
if (flags & ODB_NEW_HONOR_ENV) {
primary_source = xstrdup_or_null(getenv(DB_ENVIRONMENT));
secondary_sources = xstrdup_or_null(getenv(ALTERNATE_DB_ENVIRONMENT));
}
if (!primary_source)
primary_source = xstrfmt("%s/objects", repo->commondir);
o->sources = odb_source_new(o, primary_source, true);
o->sources_tail = &o->sources->next;
o->source = odb_source_new(o, flags);
o->inmemory_objects = &odb_source_inmemory_new(o)->base;
odb_prepare_alternates(o, secondary_sources);
free(secondary_sources);
free(primary_source);
return o;
}
void odb_close(struct object_database *o)
{
struct odb_source *source;
for (source = o->sources; source; source = source->next)
odb_source_close(source);
odb_source_close(o->source);
close_commit_graph(o);
}
static void odb_free_sources(struct object_database *o)
{
while (o->sources) {
struct odb_source *next;
next = o->sources->next;
odb_source_free(o->sources);
o->sources = next;
}
odb_source_free(o->source);
odb_source_free(o->inmemory_objects);
o->inmemory_objects = NULL;
hashmap_clear(&o->source_by_path);
}
void odb_free(struct object_database *o)
@@ -1122,24 +792,12 @@ void odb_free(struct object_database *o)
void odb_prepare(struct object_database *o, enum odb_prepare_flags flags)
{
struct odb_source *source;
obj_read_lock();
/*
* Reprepare alt odbs, in case the alternates file was modified
* during the course of this process. This only _adds_ odbs to
* the linked list, so existing odbs will continue to exist for
* the lifetime of the process. Consequently, we don't have to
* reprocess GIT_ALTERNATE_OBJECT_DIRECTORIES here.
*/
if (flags & ODB_PREPARE_FLUSH_CACHES) {
odb_prepare_alternates(o, NULL);
if (flags & ODB_PREPARE_FLUSH_CACHES)
o->object_count_valid = 0;
}
for (source = o->sources; source; source = source->next)
odb_source_prepare(source, flags);
odb_source_prepare(o->source, flags);
obj_read_unlock();
}
@@ -1151,8 +809,5 @@ void odb_reprepare(struct object_database *o)
int odb_fsck(struct object_database *odb, struct odb_fsck_options *options)
{
int ret = 0;
for (struct odb_source *source = odb->sources; source; source = source->next)
ret |= odb_source_fsck(source, options);
return ret;
return odb_source_fsck(odb->source, options);
}
+7 -55
View File
@@ -12,6 +12,7 @@
struct cached_object_entry;
struct list_objects_filter_options;
struct odb_source_inmemory;
struct odb_files_dir;
struct packed_git;
struct repository;
struct strbuf;
@@ -27,13 +28,16 @@ char *compute_alternate_path(const char *path, struct strbuf *err);
/*
* The object database encapsulates access to objects in a repository. It
* manages one or more sources that store the actual objects which are
* configured via alternates.
* manages the object source as well as auxiliary data structures required to
* manage objects.
*/
struct object_database {
/* Repository that owns this database. */
struct repository *repo;
/* The source backing this object database. */
struct odb_source *source;
/*
* State of current object database transaction. Only one
* transaction may be pending at a time. Is NULL when no transaction is
@@ -41,27 +45,6 @@ struct object_database {
*/
struct odb_transaction *transaction;
/*
* Set of all object directories; the main directory is first (and
* cannot be NULL after initialization). Subsequent directories are
* alternates.
*/
struct odb_source *sources;
struct odb_source **sources_tail;
/*
* Map of object database sources, keyed by their respective paths.
* This map is used to detect the case where the same source is
* registered multiple times.
*/
struct hashmap source_by_path;
/*
* Whether source paths shall be compared case-insensitively, as
* determined by "core.ignoreCase".
*/
int source_paths_icase;
/*
* Objects that should be substituted by other objects
* (see git-replace(1)).
@@ -225,39 +208,13 @@ struct odb_fsck_options {
*/
int odb_fsck(struct object_database *odb, struct odb_fsck_options *opts);
/*
* Find source by its object directory path. Returns a `NULL` pointer in case
* the source could not be found.
*/
struct odb_source *odb_find_source(struct object_database *odb, const char *obj_dir);
/* Same as `odb_find_source()`, but dies in case the source doesn't exist. */
struct odb_source *odb_find_source_or_die(struct object_database *odb, const char *obj_dir);
/*
* Replace the current writable object directory with the specified temporary
* object directory and return the newly installed primary source. The former
* primary source is reported via `prev_source` when non-NULL.
*/
struct odb_source *odb_set_temporary_primary_source(struct object_database *odb,
const char *dir, int will_destroy,
struct odb_source **prev_source);
/*
* Restore the primary source that was previously replaced by
* `odb_set_temporary_primary_source()`.
*/
void odb_restore_primary_source(struct object_database *odb,
struct odb_source *restore_source,
const char *old_path);
/*
* Iterate through all alternates of the database and execute the provided
* callback function for each of them. Stop iterating once the callback
* function returns a non-zero value, in which case the value is bubbled up
* from the callback.
*/
typedef int odb_for_each_alternate_fn(struct odb_source *, void *);
typedef int odb_for_each_alternate_fn(struct odb_files_dir *, void *);
int odb_for_each_alternate(struct object_database *odb,
odb_for_each_alternate_fn cb, void *payload);
@@ -847,9 +804,4 @@ int odb_generate_pack(struct object_database *odb,
*/
int odb_pack_generator_finish(struct odb_pack_generator *generator);
void parse_alternates(const char *string,
int sep,
const char *relative_base,
struct strvec *out);
#endif /* ODB_H */
+394 -88
View File
@@ -15,6 +15,7 @@
#include "packfile.h"
#include "path.h"
#include "promisor-remote.h"
#include "quote.h"
#include "repack.h"
#include "run-command.h"
#include "strbuf.h"
@@ -24,6 +25,30 @@
#include "tree.h"
#include "write-or-die.h"
struct odb_files_dir *odb_files_dir_new(struct object_database *odb,
const char *path, bool local)
{
struct odb_files_dir *dir;
CALLOC_ARRAY(dir, 1);
dir->abspath = absolute_pathdup(path);
dir->local = local;
dir->loose = odb_source_loose_new(odb, path, local);
dir->packed = odb_source_packed_new(odb, path, local);
return dir;
}
void odb_files_dir_free(struct odb_files_dir *dir)
{
if (!dir)
return;
odb_source_free(&dir->loose->base);
odb_source_free(&dir->packed->base);
free(dir->abspath);
free(dir);
}
static void odb_source_files_reparent(const char *old_cwd,
const char *new_cwd,
void *cb_data)
@@ -31,6 +56,7 @@ static void odb_source_files_reparent(const char *old_cwd,
struct odb_source_files *files = cb_data;
char *path = reparent_relative_path(old_cwd, new_cwd,
files->base.path);
free(files->base.path);
files->base.path = path;
}
@@ -38,9 +64,16 @@ static void odb_source_files_reparent(const char *old_cwd,
static void odb_source_files_free(struct odb_source *source)
{
struct odb_source_files *files = odb_source_files_downcast(source);
chdir_notify_unregister(odb_source_files_reparent, files);
odb_source_free(&files->loose->base);
odb_source_free(&files->packed->base);
while (files->dirs) {
struct odb_files_dir *next = files->dirs->next;
odb_files_dir_free(files->dirs);
files->dirs = next;
}
hashmap_clear(&files->dirs_by_path);
odb_source_release(&files->base);
free(files);
}
@@ -48,8 +81,11 @@ static void odb_source_files_free(struct odb_source *source)
static void odb_source_files_close(struct odb_source *source)
{
struct odb_source_files *files = odb_source_files_downcast(source);
odb_source_close(&files->loose->base);
odb_source_close(&files->packed->base);
for (struct odb_files_dir *dir = files->dirs; dir; dir = dir->next) {
odb_source_close(&dir->loose->base);
odb_source_close(&dir->packed->base);
}
}
static int odb_source_files_create_on_disk(struct odb_source *source,
@@ -140,12 +176,246 @@ out:
return ret;
}
/*
* NEEDSWORK: we're using "core.ignoreCase" to deduplicate alternates that
* _may_ be the same. This requires quite a bit of boilerplate for dubious
* benefit:
*
* - Duplicating alternates should really only lead to regressed performance.
*
* - We don't properly resolve symlinks or mointpoints, so we may still end
* up duplicating alternates.
*
* - The value may be lying, in which case we might deduplicate alternates
* that are in fact not mapping to the same directory.
*
* We should investigate whether we can remove this whole mechanism outright.
*/
static int odb_files_dir_paths_cmp(struct odb_source_files *files,
const char *a, const char *b)
{
if (files->dirs_paths_icase < 0) {
int icase = 0;
repo_config_get_bool(files->base.odb->repo, "core.ignorecase", &icase);
files->dirs_paths_icase = icase;
}
return files->dirs_paths_icase ? strcasecmp(a, b) : strcmp(a, b);
}
static int odb_files_dir_by_path_cmp(const void *cb_data,
const struct hashmap_entry *entry,
const struct hashmap_entry *entry_or_key,
const void *keydata)
{
struct odb_source_files *files = (struct odb_source_files *)cb_data;
const struct odb_files_dir *dir = container_of(entry, const struct odb_files_dir, by_path_entry);
const char *path = keydata;
if (!path)
path = container_of(entry_or_key, const struct odb_files_dir, by_path_entry)->abspath;
return odb_files_dir_paths_cmp(files, dir->abspath, path);
}
/*
* Return non-zero iff the path is usable as an alternate object directory.
*/
static bool odb_files_dir_is_usable(struct odb_source_files *files,
const char *path)
{
struct strbuf normalized_objdir = STRBUF_INIT;
struct hashmap_entry key;
bool usable = false;
strbuf_realpath(&normalized_objdir, files->dirs->abspath, 1);
/* Detect cases where alternate disappeared */
if (!is_directory(path)) {
error(_("object directory %s does not exist; "
"check .git/objects/info/alternates"),
path);
goto out;
}
/*
* Prevent the common mistake of listing the same
* thing twice, or object directory itself.
*/
if (!hashmap_get_size(&files->dirs_by_path)) {
assert(!files->dirs->next);
hashmap_entry_init(&files->dirs->by_path_entry,
strihash(files->dirs->abspath));
hashmap_add(&files->dirs_by_path, &files->dirs->by_path_entry);
}
if (!odb_files_dir_paths_cmp(files, path, normalized_objdir.buf))
goto out;
hashmap_entry_init(&key, strihash(path));
if (hashmap_get(&files->dirs_by_path, &key, path))
goto out;
usable = true;
out:
strbuf_release(&normalized_objdir);
return usable;
}
static void parse_alternates(const char *string,
int sep,
const char *relative_base,
struct strvec *out)
{
struct strbuf pathbuf = STRBUF_INIT;
struct strbuf buf = STRBUF_INIT;
if (!string || !*string)
return;
while (*string) {
const char *end;
strbuf_reset(&buf);
strbuf_reset(&pathbuf);
if (*string == '#') {
/* comment; consume up to next separator */
end = strchrnul(string, sep);
} else if (*string == '"' && !unquote_c_style(&buf, string, &end)) {
/*
* quoted path; unquote_c_style has copied the
* data for us and set "end". Broken quoting (e.g.,
* an entry that doesn't end with a quote) falls
* back to the unquoted case below.
*/
} else {
/* normal, unquoted path */
end = strchrnul(string, sep);
strbuf_add(&buf, string, end - string);
}
if (*end)
end++;
string = end;
if (!buf.len)
continue;
if (!is_absolute_path(buf.buf) && relative_base) {
strbuf_realpath(&pathbuf, relative_base, 1);
strbuf_addch(&pathbuf, '/');
}
strbuf_addbuf(&pathbuf, &buf);
strbuf_reset(&buf);
if (!strbuf_realpath(&buf, pathbuf.buf, 0)) {
error(_("unable to normalize alternate object path: %s"),
pathbuf.buf);
continue;
}
/*
* The trailing slash after the directory name is given by
* this function at the end. Remove duplicates.
*/
while (buf.len && buf.buf[buf.len - 1] == '/')
strbuf_setlen(&buf, buf.len - 1);
strvec_push(out, buf.buf);
}
strbuf_release(&pathbuf);
strbuf_release(&buf);
}
static int read_alternates(const char *object_dir, struct strvec *out)
{
struct strbuf buf = STRBUF_INIT;
char *path;
path = xstrfmt("%s/info/alternates", object_dir);
if (strbuf_read_file(&buf, path, 1024) < 0) {
warn_on_fopen_errors(path);
free(path);
return 0;
}
parse_alternates(buf.buf, '\n', object_dir, out);
strbuf_release(&buf);
free(path);
return 0;
}
static void odb_add_alternate_recursively(struct odb_source_files *files,
const char *path,
int depth)
{
struct odb_files_dir *alternate;
struct strvec alternates = STRVEC_INIT;
if (!odb_files_dir_is_usable(files, path))
goto out;
alternate = odb_files_dir_new(files->base.odb, path, false);
/* add the alternate entry */
*files->dirs_tail = alternate;
files->dirs_tail = &(alternate->next);
hashmap_entry_init(&alternate->by_path_entry, strihash(alternate->abspath));
if (hashmap_get(&files->dirs_by_path, &alternate->by_path_entry,
alternate->abspath))
BUG("object directory must not yet exist");
hashmap_add(&files->dirs_by_path, &alternate->by_path_entry);
/* recursively add alternates */
read_alternates(alternate->abspath, &alternates);
if (alternates.nr && depth + 1 > 5) {
error(_("%s: ignoring alternate object stores, nesting too deep"),
path);
} else {
for (size_t i = 0; i < alternates.nr; i++)
odb_add_alternate_recursively(files, alternates.v[i], depth + 1);
}
out:
strvec_clear(&alternates);
}
static void odb_prepare_alternates(struct odb_source_files *files,
const char *alternate_db)
{
struct strvec alternates = STRVEC_INIT;
parse_alternates(alternate_db, PATH_SEP, NULL, &alternates);
read_alternates(files->dirs->abspath, &alternates);
for (size_t i = 0; i < alternates.nr; i++)
odb_add_alternate_recursively(files, alternates.v[i], 0);
strvec_clear(&alternates);
}
static void odb_source_files_prepare(struct odb_source *source,
enum odb_prepare_flags flags)
{
struct odb_source_files *files = odb_source_files_downcast(source);
odb_source_prepare(&files->loose->base, flags);
odb_source_prepare(&files->packed->base, flags);
/*
* Reprepare alternates, in case the alternates file was modified
* during the course of this process. This only _adds_ directories to
* the linked list, so existing directories will continue to exist
* for the lifetime of the process.
*/
if (flags & ODB_PREPARE_FLUSH_CACHES)
odb_prepare_alternates(files, NULL);
for (struct odb_files_dir *dir = files->dirs; dir; dir = dir->next) {
odb_source_prepare(&dir->loose->base, flags);
odb_source_prepare(&dir->packed->base, flags);
}
}
static enum odb_read_status odb_source_files_read_object_info(struct odb_source *source,
@@ -155,28 +425,33 @@ static enum odb_read_status odb_source_files_read_object_info(struct odb_source
struct strbuf *errmsg)
{
struct odb_source_files *files = odb_source_files_downcast(source);
enum odb_read_status ret_packed, ret_loose;
ret_packed = odb_source_read_object_info(&files->packed->base, oid, oi,
flags, errmsg);
if (!ret_packed)
return 0;
ret_loose = odb_source_read_object_info(&files->loose->base, oid, oi, flags,
ret_packed == ODB_READ_NOT_FOUND ? errmsg : NULL);
if (!ret_loose)
return 0;
enum odb_read_status status = ODB_READ_NOT_FOUND;
/*
* Reading the packed object may have failed even though the object
* exists, for example because it is corrupt. Report this failure to
* the caller in case neither of the sources was able to read the
* object, and prefer the error of the packed source in case both
* reads have failed.
* Reading an object may fail even though the object exists, for
* example because it is corrupt. Report this failure to the caller in
* case none of the directories was able to read the object, and
* prefer the first such error in case multiple reads have failed.
*/
if (ret_packed != ODB_READ_NOT_FOUND)
return ret_packed;
return ret_loose;
for (struct odb_files_dir *dir = files->dirs; dir; dir = dir->next) {
enum odb_read_status ret;
ret = odb_source_read_object_info(&dir->packed->base, oid, oi, flags,
status == ODB_READ_NOT_FOUND ? errmsg : NULL);
if (!ret)
return 0;
if (ret != ODB_READ_NOT_FOUND && status == ODB_READ_NOT_FOUND)
status = ret;
ret = odb_source_read_object_info(&dir->loose->base, oid, oi, flags,
status == ODB_READ_NOT_FOUND ? errmsg : NULL);
if (!ret)
return 0;
if (ret != ODB_READ_NOT_FOUND && status == ODB_READ_NOT_FOUND)
status = ret;
}
return status;
}
static int odb_source_files_read_object_stream(struct odb_stream **out,
@@ -184,9 +459,12 @@ static int odb_source_files_read_object_stream(struct odb_stream **out,
const struct object_id *oid)
{
struct odb_source_files *files = odb_source_files_downcast(source);
if (!odb_source_read_object_stream(out, &files->packed->base, oid) ||
!odb_source_read_object_stream(out, &files->loose->base, oid))
return 0;
for (struct odb_files_dir *dir = files->dirs; dir; dir = dir->next)
if (!odb_source_read_object_stream(out, &dir->packed->base, oid) ||
!odb_source_read_object_stream(out, &dir->loose->base, oid))
return 0;
return -1;
}
@@ -199,16 +477,21 @@ static int odb_source_files_for_each_object(struct odb_source *source,
struct odb_source_files *files = odb_source_files_downcast(source);
int ret;
if (!(opts->flags & ODB_FOR_EACH_OBJECT_PROMISOR_ONLY)) {
ret = odb_source_for_each_object(&files->loose->base, request, cb, cb_data, opts);
for (struct odb_files_dir *dir = files->dirs; dir; dir = dir->next) {
if (opts->flags & ODB_FOR_EACH_OBJECT_LOCAL_ONLY && !dir->local)
continue;
if (!(opts->flags & ODB_FOR_EACH_OBJECT_PROMISOR_ONLY)) {
ret = odb_source_for_each_object(&dir->loose->base, request, cb, cb_data, opts);
if (ret)
return ret;
}
ret = odb_source_for_each_object(&dir->packed->base, request, cb, cb_data, opts);
if (ret)
return ret;
}
ret = odb_source_for_each_object(&files->packed->base, request, cb, cb_data, opts);
if (ret)
return ret;
return 0;
}
@@ -217,21 +500,23 @@ static int odb_source_files_count_objects(struct odb_source *source,
unsigned long *out)
{
struct odb_source_files *files = odb_source_files_downcast(source);
unsigned long count;
unsigned long count = 0;
int ret;
ret = odb_source_count_objects(&files->packed->base, flags, &count);
if (ret < 0)
goto out;
for (struct odb_files_dir *dir = files->dirs; dir; dir = dir->next) {
unsigned long dir_count;
if (!(flags & ODB_COUNT_OBJECTS_APPROXIMATE)) {
unsigned long loose_count;
ret = odb_source_count_objects(&files->loose->base, flags, &loose_count);
ret = odb_source_count_objects(&dir->packed->base, flags, &dir_count);
if (ret < 0)
goto out;
count += dir_count;
count += loose_count;
if (!(flags & ODB_COUNT_OBJECTS_APPROXIMATE)) {
ret = odb_source_count_objects(&dir->loose->base, flags, &dir_count);
if (ret < 0)
goto out;
count += dir_count;
}
}
*out = count;
@@ -248,15 +533,17 @@ static int odb_source_files_find_abbrev_len(struct odb_source *source,
{
struct odb_source_files *files = odb_source_files_downcast(source);
unsigned len = min_len;
int ret;
int ret = 0;
ret = odb_source_find_abbrev_len(&files->packed->base, oid, len, &len);
if (ret < 0)
goto out;
for (struct odb_files_dir *dir = files->dirs; dir; dir = dir->next) {
ret = odb_source_find_abbrev_len(&dir->packed->base, oid, len, &len);
if (ret < 0)
goto out;
ret = odb_source_find_abbrev_len(&files->loose->base, oid, len, &len);
if (ret < 0)
goto out;
ret = odb_source_find_abbrev_len(&dir->loose->base, oid, len, &len);
if (ret < 0)
goto out;
}
*out = len;
ret = 0;
@@ -270,9 +557,12 @@ static int odb_source_files_freshen_object(struct odb_source *source,
const time_t *mtime)
{
struct odb_source_files *files = odb_source_files_downcast(source);
if (odb_source_freshen_object(&files->packed->base, oid, mtime) ||
odb_source_freshen_object(&files->loose->base, oid, mtime))
return 1;
for (struct odb_files_dir *dir = files->dirs; dir; dir = dir->next)
if (odb_source_freshen_object(&dir->packed->base, oid, mtime) ||
odb_source_freshen_object(&dir->loose->base, oid, mtime))
return 1;
return 0;
}
@@ -285,7 +575,7 @@ static int odb_source_files_write_object(struct odb_source *source,
enum odb_write_object_flags flags)
{
struct odb_source_files *files = odb_source_files_downcast(source);
return odb_source_write_object(&files->loose->base, buf, len, type,
return odb_source_write_object(&files->dirs->loose->base, buf, len, type,
oid, compat_oid, mtime, flags);
}
@@ -294,7 +584,7 @@ static int odb_source_files_write_object_stream(struct odb_source *source,
struct object_id *oid)
{
struct odb_source_files *files = odb_source_files_downcast(source);
return odb_source_write_object_stream(&files->loose->base, stream, oid);
return odb_source_write_object_stream(&files->dirs->loose->base, stream, oid);
}
static int odb_source_files_begin_transaction(struct odb_source *source,
@@ -304,25 +594,6 @@ static int odb_source_files_begin_transaction(struct odb_source *source,
return odb_transaction_files_begin(source, out, flags);
}
static int odb_source_files_read_alternates(struct odb_source *source,
struct strvec *out)
{
struct strbuf buf = STRBUF_INIT;
char *path;
path = xstrfmt("%s/info/alternates", source->path);
if (strbuf_read_file(&buf, path, 1024) < 0) {
warn_on_fopen_errors(path);
free(path);
return 0;
}
parse_alternates(buf.buf, '\n', source->path, out);
strbuf_release(&buf);
free(path);
return 0;
}
static int too_many_loose_objects(struct odb_source_files *files, int limit)
{
unsigned long loose_count;
@@ -330,7 +601,7 @@ static int too_many_loose_objects(struct odb_source_files *files, int limit)
if (limit <= 0)
return 0;
if (odb_source_count_objects(&files->loose->base, ODB_COUNT_OBJECTS_APPROXIMATE,
if (odb_source_count_objects(&files->dirs->loose->base, ODB_COUNT_OBJECTS_APPROXIMATE,
&loose_count) < 0)
return 0;
@@ -349,7 +620,7 @@ static struct packed_git *find_base_packs(struct odb_source_files *files,
struct packfile_list_entry *e;
struct packed_git *base = NULL;
for (e = packfile_store_get_packs(files->packed); e; e = e->next) {
for (e = packfile_store_get_packs(files->dirs->packed); e; e = e->next) {
if (e->pack->is_cruft)
continue;
if (limit) {
@@ -374,7 +645,7 @@ static int too_many_packs(struct odb_source_files *files, int gc_auto_pack_limit
if (gc_auto_pack_limit <= 0)
return 0;
for (e = packfile_store_get_packs(files->packed); e; e = e->next) {
for (e = packfile_store_get_packs(files->dirs->packed); e; e = e->next) {
if (e->pack->pack_keep)
continue;
/*
@@ -934,25 +1205,57 @@ static int odb_source_files_fsck(struct odb_source *source,
struct odb_source_files *files = odb_source_files_downcast(source);
int ret = 0;
if (!(opts->flags & ODB_FSCK_FULL) && !source->local)
return 0;
for (struct odb_files_dir *dir = files->dirs; dir; dir = dir->next) {
if (!(opts->flags & ODB_FSCK_FULL) && !dir->local)
continue;
ret |= odb_source_fsck(&files->loose->base, opts);
ret |= odb_source_fsck(&files->packed->base, opts);
ret |= odb_source_fsck(&dir->loose->base, opts);
ret |= odb_source_fsck(&dir->packed->base, opts);
}
return ret;
}
struct odb_files_dir *odb_source_files_find_dir(struct object_database *odb, const char *obj_dir)
{
struct odb_source_files *files = odb_source_files_downcast(odb->source);
char *obj_dir_real = real_pathdup(obj_dir, 1);
struct strbuf odb_path_real = STRBUF_INIT;
struct odb_files_dir *dir;
for (dir = files->dirs; dir; dir = dir->next) {
strbuf_realpath(&odb_path_real, dir->abspath, 1);
if (!strcmp(obj_dir_real, odb_path_real.buf))
break;
}
free(obj_dir_real);
strbuf_release(&odb_path_real);
return dir;
}
struct odb_source_files *odb_source_files_new(struct object_database *odb,
const char *path,
bool local)
enum odb_new_flags flags)
{
struct odb_source_files *files;
char *object_dir = NULL;
char *alternates = NULL;
if (flags & ODB_NEW_HONOR_ENV) {
object_dir = xstrdup_or_null(getenv(DB_ENVIRONMENT));
alternates = xstrdup_or_null(getenv(ALTERNATE_DB_ENVIRONMENT));
}
if (!object_dir)
object_dir = xstrfmt("%s/objects", odb->repo->commondir);
CALLOC_ARRAY(files, 1);
odb_source_init(&files->base, odb, ODB_SOURCE_FILES, path, local);
files->loose = odb_source_loose_new(odb, path, local);
files->packed = odb_source_packed_new(odb, path, local);
odb_source_init(&files->base, odb, ODB_SOURCE_FILES, object_dir, true);
hashmap_init(&files->dirs_by_path, odb_files_dir_by_path_cmp, files, 0);
files->dirs_paths_icase = -1;
files->dirs = odb_files_dir_new(odb, object_dir, true);
files->dirs_tail = &files->dirs->next;
files->base.free = odb_source_files_free;
files->base.close = odb_source_files_close;
@@ -968,7 +1271,6 @@ struct odb_source_files *odb_source_files_new(struct object_database *odb,
files->base.write_object = odb_source_files_write_object;
files->base.write_object_stream = odb_source_files_write_object_stream;
files->base.begin_transaction = odb_source_files_begin_transaction;
files->base.read_alternates = odb_source_files_read_alternates;
files->base.optimize = odb_source_files_optimize;
files->base.optimize_required = odb_source_files_optimize_required;
files->base.generate_pack = odb_source_files_generate_pack;
@@ -978,8 +1280,12 @@ struct odb_source_files *odb_source_files_new(struct object_database *odb,
* is not (yet) possible though because we access and assume relative
* paths in the primary ODB source in some user-facing functionality.
*/
if (!is_absolute_path(path))
if (!is_absolute_path(object_dir))
chdir_notify_register(odb_source_files_reparent, files);
odb_prepare_alternates(files, alternates);
free(object_dir);
free(alternates);
return files;
}
+61 -4
View File
@@ -6,20 +6,71 @@
struct odb_source_loose;
struct odb_source_packed;
/*
* A single object directory that encapsulates access to both the loose and
* packed backend. This can either be the primary or an alternate object
* directory.
*/
struct odb_files_dir {
/* Absolute path to the object directory. */
char *abspath;
/* List of alternate object directories. */
struct odb_files_dir *next;
/*
* Entry in the files source's map of directories, keyed by this
* directory's path.
*/
struct hashmap_entry by_path_entry;
/* The two sources derived from this object directory. */
struct odb_source_loose *loose;
struct odb_source_packed *packed;
/*
* Whether this is the local object directory of the owning
* repository. Directories added via alternates are not local.
*/
bool local;
};
struct odb_files_dir *odb_files_dir_new(struct object_database *odb,
const char *path, bool local);
void odb_files_dir_free(struct odb_files_dir *dir);
/*
* The files object database source uses a combination of loose objects and
* packfiles. It is the default backend used by Git to store objects.
*/
struct odb_source_files {
struct odb_source base;
struct odb_source_loose *loose;
struct odb_source_packed *packed;
/*
* List of all object directories; the main directory is first (and
* cannot be NULL after initialization). Subsequent directories are
* alternates.
*/
struct odb_files_dir *dirs;
struct odb_files_dir **dirs_tail;
/*
* Map of object directories, keyed by their respective paths. This
* map is used to detect the case where the same directory is
* registered multiple times.
*/
struct hashmap dirs_by_path;
/*
* Whether directory paths shall be compared case-insensitively, as
* determined by "core.ignoreCase".
*/
int dirs_paths_icase;
};
/* Allocate and initialize a new object source. */
struct odb_source_files *odb_source_files_new(struct object_database *odb,
const char *path,
bool local);
enum odb_new_flags flags);
/*
* Optimize the files object database source by repacking loose objects and
@@ -49,4 +100,10 @@ static inline struct odb_source_files *odb_source_files_downcast(struct odb_sour
return container_of(source, struct odb_source_files, base);
}
/*
* Find "files" directory by its object directory path. Returns a `NULL`
* pointer in case the object directory could not be found.
*/
struct odb_files_dir *odb_source_files_find_dir(struct object_database *odb, const char *obj_dir);
#endif
-7
View File
@@ -322,12 +322,6 @@ static int odb_source_inmemory_begin_transaction(struct odb_source *source UNUSE
return error("in-memory source does not support transactions");
}
static int odb_source_inmemory_read_alternates(struct odb_source *source UNUSED,
struct strvec *out UNUSED)
{
return 0;
}
static void odb_source_inmemory_close(struct odb_source *source UNUSED)
{
}
@@ -390,7 +384,6 @@ struct odb_source_inmemory *odb_source_inmemory_new(struct object_database *odb)
source->base.write_object_stream = odb_source_inmemory_write_object_stream;
source->base.freshen_object = odb_source_inmemory_freshen_object;
source->base.begin_transaction = odb_source_inmemory_begin_transaction;
source->base.read_alternates = odb_source_inmemory_read_alternates;
return source;
}
+1 -8
View File
@@ -599,7 +599,7 @@ static int odb_source_loose_freshen_object(struct odb_source *source,
static void close_loose_object(struct odb_source_loose *loose,
int fd, const char *filename)
{
if (loose->base.will_destroy)
if (loose->will_destroy)
goto out;
if (batch_fsync_enabled(FSYNC_COMPONENT_LOOSE_OBJECT))
@@ -985,12 +985,6 @@ static int odb_source_loose_begin_transaction(struct odb_source *source UNUSED,
return error("loose source does not support transactions");
}
static int odb_source_loose_read_alternates(struct odb_source *source UNUSED,
struct strvec *out UNUSED)
{
return 0;
}
static void odb_source_loose_clear_cache(struct odb_source_loose *loose)
{
oidtree_clear(loose->cache);
@@ -1145,7 +1139,6 @@ struct odb_source_loose *odb_source_loose_new(struct object_database *odb,
loose->base.write_object = odb_source_loose_write_object;
loose->base.write_object_stream = odb_source_loose_write_object_stream;
loose->base.begin_transaction = odb_source_loose_begin_transaction;
loose->base.read_alternates = odb_source_loose_read_alternates;
if (!is_absolute_path(loose->base.path))
chdir_notify_register(odb_source_loose_reparent, loose);
+3
View File
@@ -28,6 +28,9 @@ struct odb_source_loose {
/* Map between object IDs for loose objects. */
struct loose_object_map *map;
/* Whether this is a source that will never be committed to disk. */
int will_destroy;
};
struct odb_source_loose *odb_source_loose_new(struct object_database *odb,
-7
View File
@@ -687,12 +687,6 @@ static int odb_source_packed_begin_transaction(struct odb_source *source UNUSED,
return error("packed backend cannot begin transactions");
}
static int odb_source_packed_read_alternates(struct odb_source *source UNUSED,
struct strvec *out UNUSED)
{
return 0;
}
void (*report_garbage)(unsigned seen_bits, const char *path);
static void report_helper(const struct string_list *list,
@@ -1019,7 +1013,6 @@ struct odb_source_packed *odb_source_packed_new(struct object_database *odb,
packed->base.write_object = odb_source_packed_write_object;
packed->base.write_object_stream = odb_source_packed_write_object_stream;
packed->base.begin_transaction = odb_source_packed_begin_transaction;
packed->base.read_alternates = odb_source_packed_read_alternates;
if (!is_absolute_path(path))
chdir_notify_register(odb_source_packed_reparent, packed);
+2 -3
View File
@@ -24,10 +24,9 @@ const char *odb_source_type_to_name(enum odb_source_type type)
}
struct odb_source *odb_source_new(struct object_database *odb,
const char *path,
bool local)
enum odb_new_flags flags)
{
return &odb_source_files_new(odb, path, local)->base;
return &odb_source_files_new(odb, flags)->base;
}
void odb_source_init(struct odb_source *source,
+4 -53
View File
@@ -49,24 +49,9 @@ struct odb_create_on_disk_options {
/*
* The source is the part of the object database that stores the actual
* objects. It thus encapsulates the logic to read and write the specific
* on-disk format. An object database can have multiple sources:
*
* - The primary source, which is typically located in "$GIT_DIR/objects".
* This is where new objects are usually written to.
*
* - Alternate sources, which are configured via "objects/info/alternates" or
* via the GIT_ALTERNATE_OBJECT_DIRECTORIES environment variable. These
* alternate sources are only used to read objects.
* on-disk format.
*/
struct odb_source {
struct odb_source *next;
/*
* Entry in the object database's map of sources, keyed by this
* source's path.
*/
struct hashmap_entry by_path_entry;
/* Object database that owns this object source. */
struct object_database *odb;
@@ -81,11 +66,6 @@ struct odb_source {
*/
bool local;
/*
* This object store is ephemeral, so there is no need to fsync.
*/
int will_destroy;
/*
* Path to the source. If this is a relative path, it is relative to
* the current working directory.
@@ -278,19 +258,6 @@ struct odb_source {
struct odb_transaction **out,
enum odb_transaction_flags flags);
/*
* This callback is expected to read the list of alternate object
* database sources connected to it and write them into the `strvec`.
*
* The result is expected to be paths to the alternates. All paths must
* be resolved to absolute paths.
*
* The callback is expected to return 0 on success, a negative error
* code otherwise.
*/
int (*read_alternates)(struct odb_source *source,
struct strvec *out);
/*
* This callback is expected to optimize the object database source.
* Returns 0 on success, a negative error code otherwise.
@@ -336,13 +303,11 @@ struct odb_source {
};
/*
* Allocate and initialize a new source for the given object database located
* at `path`. `local` indicates whether or not the source is the local and thus
* primary object source of the object database.
* Allocate and initialize a new source for the given object database. The path
* of the source is derived from repository paths.
*/
struct odb_source *odb_source_new(struct object_database *odb,
const char *path,
bool local);
enum odb_new_flags flags);
/*
* Initialize the source for the given object database located at `path`.
@@ -529,20 +494,6 @@ static inline int odb_source_write_object_stream(struct odb_source *source,
return source->write_object_stream(source, stream, oid);
}
/*
* Read the list of alternative object database sources from the given backend
* and populate the `strvec` with them. The listing is not recursive -- that
* is, if any of the yielded alternate sources has alternates itself, those
* will not be yielded as part of this function call.
*
* Return 0 on success, a negative error code otherwise.
*/
static inline int odb_source_read_alternates(struct odb_source *source,
struct strvec *out)
{
return source->read_alternates(source, out);
}
/*
* Create a new transaction that can be used to write objects into a temporary
* staging area. The objects will only be persisted when the transaction is
+2 -6
View File
@@ -182,12 +182,8 @@ static int istream_source(struct odb_stream **out,
struct object_database *odb,
const struct object_id *oid)
{
struct odb_source *source;
for (source = odb->sources; source; source = source->next)
if (!odb_source_read_object_stream(out, source, oid))
return 0;
if (!odb_source_read_object_stream(out, odb->source, oid))
return 0;
return open_istream_incore(out, odb, oid);
}
+1 -1
View File
@@ -12,7 +12,7 @@ int odb_transaction_begin(struct object_database *odb,
if (odb->transaction)
return error(_("object database transaction already pending"));
ret = odb_source_begin_transaction(odb->sources, out, flags);
ret = odb_source_begin_transaction(odb->source, out, flags);
if (!ret)
odb->transaction = *out;
+3 -5
View File
@@ -712,15 +712,13 @@ static int open_bitmap_for_source(struct odb_source_packed *source,
static int open_bitmap(struct repository *r,
struct bitmap_index *bitmap_git)
{
struct odb_source *source;
struct odb_source_files *files = odb_source_files_downcast(r->objects->source);
bool found = false;
assert(!bitmap_git->map);
for (source = r->objects->sources; source; source = source->next) {
struct odb_source_files *files = odb_source_files_downcast(source);
if (!open_bitmap_for_source(files->packed, bitmap_git))
for (struct odb_files_dir *dir = files->dirs; dir; dir = dir->next) {
if (!open_bitmap_for_source(dir->packed, bitmap_git))
found = true;
/*
+12 -16
View File
@@ -273,14 +273,13 @@ static void scan_windows(struct packed_git *p,
static int unuse_one_window(struct object_database *odb)
{
struct odb_source *source;
struct odb_source_files *files = odb_source_files_downcast(odb->source);
struct packfile_list_entry *e;
struct packed_git *lru_p = NULL;
struct pack_window *lru_w = NULL, *lru_l = NULL;
for (source = odb->sources; source; source = source->next) {
struct odb_source_files *files = odb_source_files_downcast(source);
for (e = files->packed->packs.head; e; e = e->next)
for (struct odb_files_dir *dir = files->dirs; dir; dir = dir->next) {
for (e = dir->packed->packs.head; e; e = e->next)
scan_windows(e->pack, &lru_p, &lru_w, &lru_l);
}
@@ -450,15 +449,14 @@ static void find_lru_pack(struct packed_git *p, struct packed_git **lru_p, struc
static int close_one_pack(struct repository *r)
{
struct odb_source *source;
struct odb_source_files *files = odb_source_files_downcast(r->objects->source);
struct packfile_list_entry *e;
struct packed_git *lru_p = NULL;
struct pack_window *mru_w = NULL;
int accept_windows_inuse = 1;
for (source = r->objects->sources; source; source = source->next) {
struct odb_source_files *files = odb_source_files_downcast(source);
for (e = files->packed->packs.head; e; e = e->next) {
for (struct odb_files_dir *dir = files->dirs; dir; dir = dir->next) {
for (e = dir->packed->packs.head; e; e = e->next) {
if (e->pack->pack_fd == -1)
continue;
find_lru_pack(e->pack, &lru_p, &mru_w, &accept_windows_inuse);
@@ -1921,11 +1919,10 @@ struct packed_git **packfile_store_get_kept_pack_cache(struct odb_source_packed
int has_object_pack(struct repository *r, const struct object_id *oid)
{
struct odb_source *source;
struct odb_source_files *files = odb_source_files_downcast(r->objects->source);
for (source = r->objects->sources; source; source = source->next) {
struct odb_source_files *files = odb_source_files_downcast(source);
if (!odb_source_read_object_info(&files->packed->base, oid, NULL, 0, NULL))
for (struct odb_files_dir *dir = files->dirs; dir; dir = dir->next) {
if (!odb_source_read_object_info(&dir->packed->base, oid, NULL, 0, NULL))
return 1;
}
@@ -1935,14 +1932,13 @@ int has_object_pack(struct repository *r, const struct object_id *oid)
int has_object_kept_pack(struct repository *r, const struct object_id *oid,
unsigned flags)
{
struct odb_source *source;
struct odb_source_files *files = odb_source_files_downcast(r->objects->source);
struct pack_entry e;
for (source = r->objects->sources; source; source = source->next) {
struct odb_source_files *files = odb_source_files_downcast(source);
for (struct odb_files_dir *dir = files->dirs; dir; dir = dir->next) {
struct packed_git **cache;
cache = packfile_store_get_kept_pack_cache(files->packed, flags);
cache = packfile_store_get_kept_pack_cache(dir->packed, flags);
for (; *cache; cache++) {
struct packed_git *p = *cache;
+10 -11
View File
@@ -69,20 +69,20 @@ void packfile_store_add_pack(struct odb_source_packed *store,
struct packfile_list_entry *packfile_store_get_packs(struct odb_source_packed *store);
struct repo_for_each_pack_data {
struct odb_source *source;
struct odb_files_dir *dir;
struct packfile_list_entry *entry;
};
static inline struct repo_for_each_pack_data repo_for_eack_pack_data_init(struct repository *repo)
{
struct repo_for_each_pack_data data = { 0 };
struct odb_source_files *files = odb_source_files_downcast(repo->objects->source);
for (struct odb_source *source = repo->objects->sources; source; source = source->next) {
struct odb_source_files *files = odb_source_files_downcast(source);
struct packfile_list_entry *entry = packfile_store_get_packs(files->packed);
for (struct odb_files_dir *dir = files->dirs; dir; dir = dir->next) {
struct packfile_list_entry *entry = packfile_store_get_packs(dir->packed);
if (!entry)
continue;
data.source = source;
data.dir = dir;
data.entry = entry;
break;
}
@@ -92,23 +92,22 @@ static inline struct repo_for_each_pack_data repo_for_eack_pack_data_init(struct
static inline void repo_for_each_pack_data_next(struct repo_for_each_pack_data *data)
{
struct odb_source *source;
struct odb_files_dir *dir;
data->entry = data->entry->next;
if (data->entry)
return;
for (source = data->source->next; source; source = source->next) {
struct odb_source_files *files = odb_source_files_downcast(source);
struct packfile_list_entry *entry = packfile_store_get_packs(files->packed);
for (dir = data->dir->next; dir; dir = dir->next) {
struct packfile_list_entry *entry = packfile_store_get_packs(dir->packed);
if (!entry)
continue;
data->source = source;
data->dir = dir;
data->entry = entry;
return;
}
data->source = NULL;
data->dir = NULL;
data->entry = NULL;
}
+1 -1
View File
@@ -396,7 +396,7 @@ static void adjust_git_path(struct repository *repo,
strbuf_splice(buf, 0, buf->len,
repo->index_file, strlen(repo->index_file));
else if (dir_prefix(base, "objects"))
replace_dir(buf, git_dir_len + 7, repo->objects->sources->path);
replace_dir(buf, git_dir_len + 7, repo->objects->source->path);
else if (repo_settings_get_hooks_path(repo) && dir_prefix(base, "hooks"))
replace_dir(buf, git_dir_len + 5, repo_settings_get_hooks_path(repo));
else if (repo->different_commondir)
+1 -1
View File
@@ -40,7 +40,7 @@ void prune_packed_objects(int opts)
progress = start_delayed_progress(the_repository,
_("Removing duplicate objects"), 256);
for_each_loose_file_in_source(the_repository->objects->sources,
for_each_loose_file_in_source(the_repository->objects->source,
prune_object, NULL, prune_subdir, &opts);
/* Ensure we show 100% before finishing progress */
+1 -1
View File
@@ -33,7 +33,7 @@ void pack_geometry_init(struct pack_geometry *geometry,
struct packed_git *p;
struct strbuf buf = STRBUF_INIT;
struct odb_source_files *files = odb_source_files_downcast(existing->source);
struct multi_pack_index *m = get_multi_pack_index(files->packed);
struct multi_pack_index *m = get_multi_pack_index(files->dirs->packed);
repo_for_each_pack(existing->repo, p) {
if (geometry->midx_layer_threshold_set && m &&
+3 -3
View File
@@ -564,7 +564,7 @@ static void repack_make_midx_append_plan(struct repack_write_midx_opts *opts,
size_t steps_nr = 0, steps_alloc = 0;
odb_reprepare(opts->existing->repo->objects);
m = get_multi_pack_index(files->packed);
m = get_multi_pack_index(files->dirs->packed);
if (opts->names->nr) {
struct strbuf buf = STRBUF_INIT;
@@ -620,7 +620,7 @@ static int repack_make_midx_compaction_plan(struct repack_write_midx_opts *opts,
opts->existing->repo);
odb_reprepare(opts->existing->repo->objects);
m = get_multi_pack_index(files->packed);
m = get_multi_pack_index(files->dirs->packed);
for (i = 0; m && i < m->num_packs + m->num_packs_in_base; i++) {
if (prepare_midx_pack(m, i)) {
@@ -949,7 +949,7 @@ static int write_midx_incremental(struct repack_write_midx_opts *opts)
size_t i;
int ret = 0;
get_midx_chain_filename(files->packed, &lock_name);
get_midx_chain_filename(files->dirs->packed, &lock_name);
if (safe_create_leading_directories(opts->existing->repo,
lock_name.buf))
die_errno(_("unable to create leading directories of %s"),
+3 -3
View File
@@ -59,8 +59,8 @@ void repack_remove_redundant_pack(struct repository *repo, const char *dir_name,
bool wrote_incremental_midx)
{
struct strbuf buf = STRBUF_INIT;
struct odb_source_files *files = odb_source_files_downcast(repo->objects->sources);
struct multi_pack_index *m = get_multi_pack_index(files->packed);
struct odb_source_files *files = odb_source_files_downcast(repo->objects->source);
struct multi_pack_index *m = get_multi_pack_index(files->dirs->packed);
strbuf_addf(&buf, "%s.pack", base_name);
if (m && files->base.local && midx_contains_pack(m, buf.buf)) {
clear_midx_file(repo);
@@ -158,7 +158,7 @@ void existing_packs_collect(struct existing_packs *existing,
string_list_append(&existing->non_kept_packs, buf.buf);
}
existing->source = existing->repo->objects->sources;
existing->source = existing->repo->objects->source;
string_list_sort(&existing->kept_packs);
string_list_sort(&existing->non_kept_packs);
+2 -2
View File
@@ -126,9 +126,9 @@ const char *repo_get_common_dir(struct repository *repo)
const char *repo_get_object_directory(struct repository *repo)
{
if (!repo->objects->sources)
if (!repo->objects->source)
BUG("repository hasn't been set up");
return repo->objects->sources->path;
return repo->objects->source->path;
}
const char *repo_get_index_file(struct repository *repo)
+1 -1
View File
@@ -2669,7 +2669,7 @@ void create_object_database(struct repository *repo,
repo->objects = odb_new(repo, ODB_NEW_HONOR_ENV);
if (odb_source_create_on_disk(repo->objects->sources, &opts) < 0)
if (odb_source_create_on_disk(repo->objects->source, &opts) < 0)
die(_("failed creating object database"));
}
+3 -2
View File
@@ -4,6 +4,7 @@
#include "commit-graph.h"
#include "repository.h"
#include "odb.h"
#include "odb/source.h"
#include "bloom.h"
#include "setup.h"
@@ -77,11 +78,11 @@ int cmd__read_graph(int argc, const char **argv)
int ret = 0;
setup_git_directory(the_repository);
source = the_repository->objects->sources;
source = the_repository->objects->source;
prepare_repo_settings(the_repository);
graph = read_commit_graph_one(source);
graph = read_commit_graph_one(the_repository, source->path);
if (!graph) {
ret = 1;
goto done;
+4 -4
View File
@@ -16,13 +16,13 @@ static struct multi_pack_index *setup_midx(const char *object_dir,
struct odb_source_packed **out)
{
struct odb_source_packed *packed;
struct odb_source *source;
struct odb_files_dir *dir;
setup_git_directory(the_repository);
source = odb_find_source(the_repository->objects, object_dir);
if (source) {
packed = odb_source_files_downcast(source)->packed;
dir = odb_source_files_find_dir(the_repository->objects, object_dir);
if (dir) {
packed = dir->packed;
} else {
packed = odb_source_packed_new(the_repository->objects,
object_dir, false);
+2 -2
View File
@@ -755,7 +755,7 @@ test_expect_success PERL_TEST_HELPERS 'Bloom reader notices too-small data chunk
test_expect_success PERL_TEST_HELPERS 'Bloom reader notices out-of-bounds filter offsets' '
check_corrupt_graph BIDX 12 FFFFFFFF &&
# use grep to avoid depending on exact chunk size
test_grep "warning: ignoring out-of-range offset (4294967295) for changed-path filter at pos 3 of .git/objects/info/commit-graph" err
test_grep "warning: ignoring out-of-range offset (4294967295) for changed-path filter at pos 3 of $(pwd)/.git/objects/info/commit-graph" err
'
test_expect_success PERL_TEST_HELPERS 'Bloom reader notices too-small index chunk' '
@@ -773,7 +773,7 @@ test_expect_success PERL_TEST_HELPERS 'Bloom reader notices out-of-order index o
# actually reading from the bogus offsets anyway.
corrupt_graph BIDX 4 0000000c00000005 &&
echo "warning: ignoring decreasing changed-path index offsets" \
"(12 > 5) for positions 1 and 2 of .git/objects/info/commit-graph" >expect.err &&
"(12 > 5) for positions 1 and 2 of $(pwd)/.git/objects/info/commit-graph" >expect.err &&
git -c core.commitGraph=false log -- A/B/file2 >expect.out &&
git -c core.commitGraph=true log -- A/B/file2 >out 2>err &&
test_cmp expect.out out &&
+48 -19
View File
@@ -12,13 +12,16 @@
#include "quote.h"
#include "odb.h"
#include "odb/source.h"
#include "odb/source-files.h"
#include "odb/source-loose.h"
#include "repository.h"
struct tmp_objdir {
struct repository *repo;
struct strbuf path;
struct strvec env;
struct odb_source *prev_source;
struct odb_files_dir *temp_dir;
struct odb_files_dir *orig_dir;
int will_destroy;
};
@@ -51,6 +54,27 @@ static void tmp_objdir_reparent(const char *old_cwd,
free(path);
}
/*
* Restore the primary source that was previously replaced by
* `tmp_objdir_create()`.
*/
static void tmp_objdir_restore_source(struct tmp_objdir *t)
{
struct odb_source_files *files = odb_source_files_downcast(t->repo->objects->source);
struct odb_files_dir *cur_dir = files->dirs;
if (t->temp_dir != files->dirs)
BUG("expected %s as primary object store; found %s",
t->temp_dir->abspath, cur_dir->abspath);
if (t->temp_dir->next != t->orig_dir)
BUG("we expect the old primary object store to be the first alternate");
t->repo->disable_ref_updates = false;
files->dirs = t->orig_dir;
odb_files_dir_free(cur_dir);
}
int tmp_objdir_destroy(struct tmp_objdir *t)
{
int err;
@@ -61,8 +85,8 @@ int tmp_objdir_destroy(struct tmp_objdir *t)
if (t == the_tmp_objdir)
the_tmp_objdir = NULL;
if (t->prev_source)
odb_restore_primary_source(t->repo->objects, t->prev_source, t->path.buf);
if (t->orig_dir)
tmp_objdir_restore_source(t);
err = remove_dir_recursively(&t->path, 0);
@@ -132,8 +156,10 @@ static int setup_tmp_objdir(const char *root)
}
struct tmp_objdir *tmp_objdir_create(struct repository *r,
const char *prefix)
const char *prefix,
int will_destroy)
{
struct odb_source_files *files = odb_source_files_downcast(r->objects->source);
static int installed_handlers;
struct tmp_objdir *t;
@@ -142,6 +168,7 @@ struct tmp_objdir *tmp_objdir_create(struct repository *r,
t = xcalloc(1, sizeof(*t));
t->repo = r;
t->will_destroy = will_destroy;
strbuf_init(&t->path, 0);
strvec_init(&t->env);
@@ -179,6 +206,19 @@ struct tmp_objdir *tmp_objdir_create(struct repository *r,
env_replace(&t->env, GIT_QUARANTINE_ENVIRONMENT,
absolute_path(t->path.buf));
/*
* Make a new primary source and link the old primary source in as an
* alternate. Disable ref updates while a temporary source is active,
* since the objects in the database may roll back.
*/
t->temp_dir = odb_files_dir_new(t->repo->objects, t->path.buf, false);
t->temp_dir->loose->will_destroy = will_destroy;
t->temp_dir->next = files->dirs;
t->orig_dir = files->dirs;
files->dirs = t->temp_dir;
t->repo->disable_ref_updates = true;
return t;
}
@@ -295,11 +335,11 @@ int tmp_objdir_migrate(struct tmp_objdir *t)
if (!t)
return 0;
if (t->prev_source) {
if (t->repo->objects->sources->will_destroy)
if (t->orig_dir) {
if (t->will_destroy)
BUG("migrating an ODB that was marked for destruction");
odb_restore_primary_source(t->repo->objects, t->prev_source, t->path.buf);
t->prev_source = NULL;
tmp_objdir_restore_source(t);
t->orig_dir = NULL;
}
strbuf_addbuf(&src, &t->path);
@@ -320,14 +360,3 @@ const char **tmp_objdir_env(const struct tmp_objdir *t)
return NULL;
return t->env.v;
}
struct odb_source *tmp_objdir_replace_primary_odb(struct tmp_objdir *t,
int will_destroy)
{
if (t->prev_source)
BUG("the primary object database is already replaced");
t->will_destroy = will_destroy;
return odb_set_temporary_primary_source(t->repo->objects, t->path.buf,
will_destroy, &t->prev_source);
}
+5 -13
View File
@@ -11,7 +11,7 @@
* Example:
*
* struct child_process child = CHILD_PROCESS_INIT;
* struct tmp_objdir *t = tmp_objdir_create(repo, "incoming");
* struct tmp_objdir *t = tmp_objdir_create(repo, "incoming", 0);
* strvec_push(&child.args, cmd);
* strvec_pushv(&child.env, tmp_objdir_env(t));
* if (!run_command(&child)) && !tmp_objdir_migrate(t))
@@ -25,10 +25,11 @@ struct repository;
struct tmp_objdir;
/*
* Create a new temporary object directory with the specified prefix;
* returns NULL on failure.
* Create a new temporary object directory with the specified prefix and
* install the directory as the primary write target; returns NULL on failure.
*/
struct tmp_objdir *tmp_objdir_create(struct repository *r, const char *prefix);
struct tmp_objdir *tmp_objdir_create(struct repository *r, const char *prefix,
int will_destroy);
/*
* Return a list of environment strings, suitable for use with
@@ -55,13 +56,4 @@ int tmp_objdir_destroy(struct tmp_objdir *);
*/
void tmp_objdir_discard_objects(struct tmp_objdir *);
/*
* Replaces the writable object store in the current process with the temporary
* object directory and makes the former main object store an alternate.
* If will_destroy is nonzero, the object directory may not be migrated. Returns
* the newly installed primary source.
*/
struct odb_source *tmp_objdir_replace_primary_odb(struct tmp_objdir *,
int will_destroy);
#endif /* TMP_OBJDIR_H */