Merge branch 'ps/odb-files-alternates'
The odb_source API has been refactored to make alternates an implementation detail of the files backend instead of managing them at the core object database layer. * 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:
commit
583e98cd09
52 files changed
+885
-955
No files matched your search
+29
-12
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
+5
-2
@@ -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"
|
||||
@@ -2944,12 +2945,14 @@ int cmd_fetch(int argc,
|
||||
the_repository);
|
||||
if (graph_write_mode == GRAPH_WRITE_TIPS)
|
||||
write_commit_graph(
|
||||
the_repository->objects->sources,
|
||||
the_repository,
|
||||
the_repository->objects->source->path,
|
||||
NULL, &updated_tips,
|
||||
commit_graph_flags, NULL);
|
||||
else
|
||||
write_commit_graph_reachable(
|
||||
the_repository->objects->sources,
|
||||
the_repository,
|
||||
the_repository->objects->source->path,
|
||||
commit_graph_flags, NULL);
|
||||
trace2_region_leave("fetch", "write-commit-graph",
|
||||
the_repository);
|
||||
|
||||
+3
-3
@@ -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
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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:
|
||||
|
||||
@@ -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'"),
|
||||
|
||||
@@ -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
@@ -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)
|
||||
*/
|
||||
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 @@ 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
@@ -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);
|
||||
struct commit_graph *prepare_commit_graph(struct repository *r);
|
||||
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,
|
||||
@@ -86,12 +86,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;
|
||||
@@ -115,12 +116,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;
|
||||
|
||||
@@ -172,11 +181,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
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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 */
|
||||
|
||||
@@ -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) ?
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -440,15 +439,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);
|
||||
@@ -1934,11 +1932,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;
|
||||
}
|
||||
|
||||
@@ -1948,14 +1945,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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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"),
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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"));
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "object-name.h"
|
||||
#include "repository.h"
|
||||
#include "odb.h"
|
||||
#include "odb/source.h"
|
||||
#include "bloom.h"
|
||||
#include "setup.h"
|
||||
|
||||
@@ -80,11 +81,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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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 */
|
||||
Reference in new issue
Block a user