From a1e2581a1e9ca2a85ae0a018ba5fb8fe5db3c322 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Tue, 1 Jul 2025 14:22:14 +0200 Subject: object-store: rename `object_directory` to `odb_source` The `object_directory` structure is used as an access point for a single object directory like ".git/objects". While the structure isn't yet fully self-contained, the intent is for it to eventually contain all information required to access objects in one specific location. While the name "object directory" is a good fit for now, this will change over time as we continue with the agenda to make pluggable object databases a thing. Eventually, objects may not be accessed via any kind of directory at all anymore, but they could instead be backed by any kind of durable storage mechanism. While it seems quite far-fetched for now, it is thinkable that eventually this might even be some form of a database, for example. As such, the current name of this structure will become worse over time as we evolve into the direction of pluggable ODBs. Immediate next steps will start to carve out proper self-contained object directories, which requires us to pass in these object directories as parameters. Based on our modern naming schema this means that those functions should then be named after their subsystem, which means that we would start to bake the current name into the codebase more and more. Let's preempt this by renaming the structure. There have been a couple alternatives that were discussed: - `odb_backend` was discarded because it led to the association that one object database has a single backend, but the model is that one alternate has one backend. Furthermore, "backend" is more about the actual backing implementation and less about the high-level concept. - `odb_alternate` was discarded because it is a bit of a stretch to also call the main object directory an "alternate". Instead, pick `odb_source` as the new name. It makes it sufficiently clear that there can be multiple sources and does not cause confusion when mixed with the already-existing "alternate" terminology. In the future, this change allows us to easily introduce for example a `odb_files_source` and other format-specific implementations. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- builtin/commit-graph.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'builtin/commit-graph.c') diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c index a783a86e79..98a8431534 100644 --- a/builtin/commit-graph.c +++ b/builtin/commit-graph.c @@ -66,7 +66,7 @@ static int graph_verify(int argc, const char **argv, const char *prefix, struct repository *repo UNUSED) { struct commit_graph *graph = NULL; - struct object_directory *odb = NULL; + struct odb_source *source = NULL; char *graph_name; char *chain_name; enum { OPENED_NONE, OPENED_GRAPH, OPENED_CHAIN } opened = OPENED_NONE; @@ -101,9 +101,9 @@ static int graph_verify(int argc, const char **argv, const char *prefix, if (opts.progress) flags |= COMMIT_GRAPH_WRITE_PROGRESS; - odb = find_odb(the_repository, opts.obj_dir); - graph_name = get_commit_graph_filename(odb); - chain_name = get_commit_graph_chain_filename(odb); + source = find_odb(the_repository, opts.obj_dir); + graph_name = get_commit_graph_filename(source); + chain_name = get_commit_graph_chain_filename(source); if (open_commit_graph(graph_name, &fd, &st)) opened = OPENED_GRAPH; else if (errno != ENOENT) @@ -120,7 +120,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(the_repository, fd, &st, odb); + graph = load_commit_graph_one_fd_st(the_repository, fd, &st, source); else graph = load_commit_graph_chain_fd_st(the_repository, fd, &st, &incomplete_chain); @@ -221,7 +221,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 object_directory *odb = NULL; + struct odb_source *source = NULL; int result = 0; enum commit_graph_write_flags flags = 0; struct progress *progress = NULL; @@ -289,10 +289,10 @@ 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; - odb = find_odb(the_repository, opts.obj_dir); + source = find_odb(the_repository, opts.obj_dir); if (opts.reachable) { - if (write_commit_graph_reachable(odb, flags, &write_opts)) + if (write_commit_graph_reachable(source, flags, &write_opts)) result = 1; goto cleanup; } @@ -318,7 +318,7 @@ static int graph_write(int argc, const char **argv, const char *prefix, stop_progress(&progress); } - if (write_commit_graph(odb, + if (write_commit_graph(source, opts.stdin_packs ? &pack_indexes : NULL, opts.stdin_commits ? &commits : NULL, flags, -- cgit v1.2.3 From 8f49151763cb81adf4bcec53c1ae67057081b02d Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Tue, 1 Jul 2025 14:22:15 +0200 Subject: object-store: rename files to "odb.{c,h}" In the preceding commits we have renamed the structures contained in "object-store.h" to `struct object_database` and `struct odb_backend`. As such, the code files "object-store.{c,h}" are confusingly named now. Rename them to "odb.{c,h}" accordingly. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- Makefile | 2 +- apply.c | 2 +- archive-tar.c | 2 +- archive-zip.c | 2 +- archive.c | 2 +- attr.c | 2 +- bisect.c | 2 +- blame.c | 2 +- builtin/backfill.c | 2 +- builtin/blame.c | 2 +- builtin/cat-file.c | 2 +- builtin/checkout.c | 2 +- builtin/clone.c | 2 +- builtin/commit-graph.c | 2 +- builtin/commit-tree.c | 2 +- builtin/describe.c | 2 +- builtin/difftool.c | 2 +- builtin/fast-export.c | 2 +- builtin/fast-import.c | 2 +- builtin/fetch.c | 2 +- builtin/fsck.c | 2 +- builtin/grep.c | 2 +- builtin/hash-object.c | 2 +- builtin/index-pack.c | 2 +- builtin/log.c | 2 +- builtin/ls-files.c | 2 +- builtin/ls-tree.c | 2 +- builtin/merge-file.c | 2 +- builtin/merge-tree.c | 2 +- builtin/mktag.c | 2 +- builtin/mktree.c | 2 +- builtin/multi-pack-index.c | 2 +- builtin/notes.c | 2 +- builtin/pack-objects.c | 2 +- builtin/pack-redundant.c | 2 +- builtin/prune.c | 2 +- builtin/receive-pack.c | 2 +- builtin/remote.c | 2 +- builtin/repack.c | 2 +- builtin/replace.c | 2 +- builtin/rev-list.c | 2 +- builtin/show-ref.c | 2 +- builtin/submodule--helper.c | 2 +- builtin/tag.c | 2 +- builtin/unpack-file.c | 2 +- builtin/unpack-objects.c | 2 +- bulk-checkin.c | 2 +- bundle-uri.c | 2 +- bundle.c | 2 +- cache-tree.c | 2 +- combine-diff.c | 2 +- commit-graph.c | 2 +- commit-graph.h | 2 +- commit.c | 2 +- config.c | 2 +- connected.c | 2 +- contrib/coccinelle/the_repository.cocci | 2 +- diagnose.c | 2 +- diff.c | 2 +- entry.c | 2 +- fetch-pack.c | 2 +- fmt-merge-msg.c | 2 +- fsck.c | 2 +- grep.c | 2 +- http-backend.c | 2 +- http-push.c | 2 +- http-walker.c | 2 +- http.c | 2 +- list-objects-filter.c | 2 +- list-objects.c | 2 +- loose.c | 2 +- mailmap.c | 2 +- match-trees.c | 2 +- merge-blobs.c | 2 +- merge-ort.c | 2 +- meson.build | 2 +- notes-cache.c | 2 +- notes-merge.c | 2 +- notes.c | 2 +- object-file.c | 2 +- object-file.h | 2 +- object-store.c | 1010 ------------------------------- object-store.h | 355 ----------- odb.c | 1010 +++++++++++++++++++++++++++++++ odb.h | 355 +++++++++++ oss-fuzz/fuzz-pack-idx.c | 2 +- pack-bitmap-write.c | 2 +- pack-bitmap.c | 2 +- pack-check.c | 2 +- pack-mtimes.c | 2 +- pack-objects.h | 2 +- pack-revindex.c | 2 +- packfile.c | 2 +- packfile.h | 4 +- path.c | 2 +- promisor-remote.c | 2 +- protocol-caps.c | 2 +- read-cache.c | 2 +- ref-filter.c | 2 +- reflog.c | 2 +- refs.c | 2 +- remote.c | 2 +- replace-object.c | 2 +- replace-object.h | 2 +- repository.c | 2 +- rerere.c | 2 +- revision.c | 2 +- send-pack.c | 2 +- sequencer.c | 2 +- server-info.c | 2 +- shallow.c | 2 +- streaming.c | 2 +- submodule-config.c | 2 +- submodule.c | 2 +- t/helper/test-find-pack.c | 2 +- t/helper/test-pack-mtimes.c | 2 +- t/helper/test-partial-clone.c | 2 +- t/helper/test-read-graph.c | 2 +- t/helper/test-read-midx.c | 2 +- t/helper/test-ref-store.c | 2 +- tag.c | 2 +- tmp-objdir.c | 2 +- tree-walk.c | 2 +- tree.c | 2 +- unpack-trees.c | 2 +- upload-pack.c | 2 +- walker.c | 2 +- xdiff-interface.c | 2 +- 128 files changed, 1490 insertions(+), 1490 deletions(-) delete mode 100644 object-store.c delete mode 100644 object-store.h create mode 100644 odb.c create mode 100644 odb.h (limited to 'builtin/commit-graph.c') diff --git a/Makefile b/Makefile index 70d1543b6b..4b1bf89779 100644 --- a/Makefile +++ b/Makefile @@ -1085,8 +1085,8 @@ LIB_OBJS += notes.o LIB_OBJS += object-file-convert.o LIB_OBJS += object-file.o LIB_OBJS += object-name.o -LIB_OBJS += object-store.o LIB_OBJS += object.o +LIB_OBJS += odb.o LIB_OBJS += oid-array.o LIB_OBJS += oidmap.o LIB_OBJS += oidset.o diff --git a/apply.c b/apply.c index 8bbe6ed224..e778b4e911 100644 --- a/apply.c +++ b/apply.c @@ -14,7 +14,7 @@ #include "abspath.h" #include "base85.h" #include "config.h" -#include "object-store.h" +#include "odb.h" #include "delta.h" #include "diff.h" #include "dir.h" diff --git a/archive-tar.c b/archive-tar.c index 282b48196f..249164ea77 100644 --- a/archive-tar.c +++ b/archive-tar.c @@ -11,7 +11,7 @@ #include "hex.h" #include "tar.h" #include "archive.h" -#include "object-store.h" +#include "odb.h" #include "strbuf.h" #include "streaming.h" #include "run-command.h" diff --git a/archive-zip.c b/archive-zip.c index 405da6f3d8..df8866d5ba 100644 --- a/archive-zip.c +++ b/archive-zip.c @@ -12,7 +12,7 @@ #include "hex.h" #include "streaming.h" #include "utf8.h" -#include "object-store.h" +#include "odb.h" #include "strbuf.h" #include "userdiff.h" #include "write-or-die.h" diff --git a/archive.c b/archive.c index 8309ea213e..7fa2cc2596 100644 --- a/archive.c +++ b/archive.c @@ -14,7 +14,7 @@ #include "pretty.h" #include "setup.h" #include "refs.h" -#include "object-store.h" +#include "odb.h" #include "commit.h" #include "tree.h" #include "tree-walk.h" diff --git a/attr.c b/attr.c index 86b6109fc4..e5680db7f6 100644 --- a/attr.c +++ b/attr.c @@ -22,7 +22,7 @@ #include "read-cache-ll.h" #include "refs.h" #include "revision.h" -#include "object-store.h" +#include "odb.h" #include "setup.h" #include "thread-utils.h" #include "tree-walk.h" diff --git a/bisect.c b/bisect.c index a327468c75..a7939216d0 100644 --- a/bisect.c +++ b/bisect.c @@ -20,7 +20,7 @@ #include "commit-slab.h" #include "commit-reach.h" #include "object-name.h" -#include "object-store.h" +#include "odb.h" #include "path.h" #include "dir.h" diff --git a/blame.c b/blame.c index 57daa45e89..0ceea080a8 100644 --- a/blame.c +++ b/blame.c @@ -3,7 +3,7 @@ #include "git-compat-util.h" #include "refs.h" -#include "object-store.h" +#include "odb.h" #include "cache-tree.h" #include "mergesort.h" #include "commit.h" diff --git a/builtin/backfill.c b/builtin/backfill.c index fa82ad2f6f..0b49baa39f 100644 --- a/builtin/backfill.c +++ b/builtin/backfill.c @@ -13,7 +13,7 @@ #include "tree.h" #include "tree-walk.h" #include "object.h" -#include "object-store.h" +#include "odb.h" #include "oid-array.h" #include "oidset.h" #include "promisor-remote.h" diff --git a/builtin/blame.c b/builtin/blame.c index 944952e30e..15eda60af9 100644 --- a/builtin/blame.c +++ b/builtin/blame.c @@ -28,7 +28,7 @@ #include "line-log.h" #include "progress.h" #include "object-name.h" -#include "object-store.h" +#include "odb.h" #include "pager.h" #include "blame.h" #include "refs.h" diff --git a/builtin/cat-file.c b/builtin/cat-file.c index 67a5ff2b9e..f3a925a818 100644 --- a/builtin/cat-file.c +++ b/builtin/cat-file.c @@ -24,7 +24,7 @@ #include "pack-bitmap.h" #include "object-file.h" #include "object-name.h" -#include "object-store.h" +#include "odb.h" #include "replace-object.h" #include "promisor-remote.h" #include "mailmap.h" diff --git a/builtin/checkout.c b/builtin/checkout.c index d185982f3a..e7dd66173d 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -20,7 +20,7 @@ #include "merge-ort-wrappers.h" #include "object-file.h" #include "object-name.h" -#include "object-store.h" +#include "odb.h" #include "parse-options.h" #include "path.h" #include "preload-index.h" diff --git a/builtin/clone.c b/builtin/clone.c index 91b9cd0d16..1eafeefb48 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -25,7 +25,7 @@ #include "refs.h" #include "refspec.h" #include "object-file.h" -#include "object-store.h" +#include "odb.h" #include "tree.h" #include "tree-walk.h" #include "unpack-trees.h" diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c index 98a8431534..f04eaba525 100644 --- a/builtin/commit-graph.c +++ b/builtin/commit-graph.c @@ -6,7 +6,7 @@ #include "hex.h" #include "parse-options.h" #include "commit-graph.h" -#include "object-store.h" +#include "odb.h" #include "progress.h" #include "replace-object.h" #include "strbuf.h" diff --git a/builtin/commit-tree.c b/builtin/commit-tree.c index ad6b2c9320..546069f868 100644 --- a/builtin/commit-tree.c +++ b/builtin/commit-tree.c @@ -9,7 +9,7 @@ #include "gettext.h" #include "hex.h" #include "object-name.h" -#include "object-store.h" +#include "odb.h" #include "commit.h" #include "parse-options.h" diff --git a/builtin/describe.c b/builtin/describe.c index 2d50883b72..96cb68e5e5 100644 --- a/builtin/describe.c +++ b/builtin/describe.c @@ -19,7 +19,7 @@ #include "setup.h" #include "strvec.h" #include "run-command.h" -#include "object-store.h" +#include "odb.h" #include "list-objects.h" #include "commit-slab.h" #include "wildmatch.h" diff --git a/builtin/difftool.c b/builtin/difftool.c index a3b64ce694..fac613e3bc 100644 --- a/builtin/difftool.c +++ b/builtin/difftool.c @@ -30,7 +30,7 @@ #include "strbuf.h" #include "lockfile.h" #include "object-file.h" -#include "object-store.h" +#include "odb.h" #include "dir.h" #include "entry.h" #include "setup.h" diff --git a/builtin/fast-export.c b/builtin/fast-export.c index 37c01d6c6f..0505f289a9 100644 --- a/builtin/fast-export.c +++ b/builtin/fast-export.c @@ -14,7 +14,7 @@ #include "refs.h" #include "refspec.h" #include "object-file.h" -#include "object-store.h" +#include "odb.h" #include "commit.h" #include "object.h" #include "tag.h" diff --git a/builtin/fast-import.c b/builtin/fast-import.c index b2839c5f43..52c792488e 100644 --- a/builtin/fast-import.c +++ b/builtin/fast-import.c @@ -24,7 +24,7 @@ #include "packfile.h" #include "object-file.h" #include "object-name.h" -#include "object-store.h" +#include "odb.h" #include "mem-pool.h" #include "commit-reach.h" #include "khash.h" diff --git a/builtin/fetch.c b/builtin/fetch.c index a890e2864d..b842bc9c51 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -14,7 +14,7 @@ #include "refs.h" #include "refspec.h" #include "object-name.h" -#include "object-store.h" +#include "odb.h" #include "oidset.h" #include "oid-array.h" #include "commit.h" diff --git a/builtin/fsck.c b/builtin/fsck.c index 6e1474f63d..9abd7b2558 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -17,7 +17,7 @@ #include "packfile.h" #include "object-file.h" #include "object-name.h" -#include "object-store.h" +#include "odb.h" #include "path.h" #include "read-cache-ll.h" #include "replace-object.h" diff --git a/builtin/grep.c b/builtin/grep.c index 76b1938bba..a1d7ee7af3 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -26,7 +26,7 @@ #include "submodule-config.h" #include "object-file.h" #include "object-name.h" -#include "object-store.h" +#include "odb.h" #include "packfile.h" #include "pager.h" #include "path.h" diff --git a/builtin/hash-object.c b/builtin/hash-object.c index 6a99ec250d..e28f000221 100644 --- a/builtin/hash-object.c +++ b/builtin/hash-object.c @@ -11,7 +11,7 @@ #include "gettext.h" #include "hex.h" #include "object-file.h" -#include "object-store.h" +#include "odb.h" #include "blob.h" #include "quote.h" #include "parse-options.h" diff --git a/builtin/index-pack.c b/builtin/index-pack.c index bb7925bd29..1aabe6b8ee 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -21,7 +21,7 @@ #include "packfile.h" #include "pack-revindex.h" #include "object-file.h" -#include "object-store.h" +#include "odb.h" #include "oid-array.h" #include "oidset.h" #include "path.h" diff --git a/builtin/log.c b/builtin/log.c index b450cd3bde..fe9cc5ebec 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -15,7 +15,7 @@ #include "hex.h" #include "refs.h" #include "object-name.h" -#include "object-store.h" +#include "odb.h" #include "pager.h" #include "color.h" #include "commit.h" diff --git a/builtin/ls-files.c b/builtin/ls-files.c index be74f0a03b..821339b07d 100644 --- a/builtin/ls-files.c +++ b/builtin/ls-files.c @@ -25,7 +25,7 @@ #include "setup.h" #include "sparse-index.h" #include "submodule.h" -#include "object-store.h" +#include "odb.h" #include "hex.h" diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c index 8aafc30ca4..62b6fd58c1 100644 --- a/builtin/ls-tree.c +++ b/builtin/ls-tree.c @@ -10,7 +10,7 @@ #include "gettext.h" #include "hex.h" #include "object-name.h" -#include "object-store.h" +#include "odb.h" #include "tree.h" #include "path.h" #include "quote.h" diff --git a/builtin/merge-file.c b/builtin/merge-file.c index 2b16b10d2c..9464f27562 100644 --- a/builtin/merge-file.c +++ b/builtin/merge-file.c @@ -7,7 +7,7 @@ #include "hex.h" #include "object-file.h" #include "object-name.h" -#include "object-store.h" +#include "odb.h" #include "config.h" #include "gettext.h" #include "setup.h" diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index 7f41665dfd..b1a17787bc 100644 --- a/builtin/merge-tree.c +++ b/builtin/merge-tree.c @@ -10,7 +10,7 @@ #include "commit-reach.h" #include "merge-ort.h" #include "object-name.h" -#include "object-store.h" +#include "odb.h" #include "parse-options.h" #include "blob.h" #include "merge-blobs.h" diff --git a/builtin/mktag.c b/builtin/mktag.c index 7ac11c46d5..1809b38f93 100644 --- a/builtin/mktag.c +++ b/builtin/mktag.c @@ -6,7 +6,7 @@ #include "strbuf.h" #include "replace-object.h" #include "object-file.h" -#include "object-store.h" +#include "odb.h" #include "fsck.h" #include "config.h" diff --git a/builtin/mktree.c b/builtin/mktree.c index 4b47803467..016b0e5b22 100644 --- a/builtin/mktree.c +++ b/builtin/mktree.c @@ -12,7 +12,7 @@ #include "tree.h" #include "parse-options.h" #include "object-file.h" -#include "object-store.h" +#include "odb.h" static struct treeent { unsigned mode; diff --git a/builtin/multi-pack-index.c b/builtin/multi-pack-index.c index f55bf53da8..aa25b06f9d 100644 --- a/builtin/multi-pack-index.c +++ b/builtin/multi-pack-index.c @@ -7,7 +7,7 @@ #include "midx.h" #include "strbuf.h" #include "trace2.h" -#include "object-store.h" +#include "odb.h" #include "replace-object.h" #include "repository.h" diff --git a/builtin/notes.c b/builtin/notes.c index a3f433ca4c..783d4932ca 100644 --- a/builtin/notes.c +++ b/builtin/notes.c @@ -16,7 +16,7 @@ #include "notes.h" #include "object-file.h" #include "object-name.h" -#include "object-store.h" +#include "odb.h" #include "path.h" #include "pretty.h" diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 8b33edc2ff..99b63cb098 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -32,7 +32,7 @@ #include "list.h" #include "packfile.h" #include "object-file.h" -#include "object-store.h" +#include "odb.h" #include "replace-object.h" #include "dir.h" #include "midx.h" diff --git a/builtin/pack-redundant.c b/builtin/pack-redundant.c index 5d1fc78176..3134cb8c68 100644 --- a/builtin/pack-redundant.c +++ b/builtin/pack-redundant.c @@ -13,7 +13,7 @@ #include "hex.h" #include "packfile.h" -#include "object-store.h" +#include "odb.h" #include "strbuf.h" #define BLKSIZE 512 diff --git a/builtin/prune.c b/builtin/prune.c index e930caa0c0..7bbfb14c2b 100644 --- a/builtin/prune.c +++ b/builtin/prune.c @@ -17,7 +17,7 @@ #include "replace-object.h" #include "object-file.h" #include "object-name.h" -#include "object-store.h" +#include "odb.h" #include "shallow.h" static const char * const prune_usage[] = { diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index a317d6c278..0f5958c4a6 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -33,7 +33,7 @@ #include "packfile.h" #include "object-file.h" #include "object-name.h" -#include "object-store.h" +#include "odb.h" #include "path.h" #include "protocol.h" #include "commit-reach.h" diff --git a/builtin/remote.c b/builtin/remote.c index 0d6755bcb7..ac5b8d2a1a 100644 --- a/builtin/remote.c +++ b/builtin/remote.c @@ -14,7 +14,7 @@ #include "rebase.h" #include "refs.h" #include "refspec.h" -#include "object-store.h" +#include "odb.h" #include "strvec.h" #include "commit-reach.h" #include "progress.h" diff --git a/builtin/repack.c b/builtin/repack.c index 59214dbdfd..1678232005 100644 --- a/builtin/repack.c +++ b/builtin/repack.c @@ -17,7 +17,7 @@ #include "midx.h" #include "packfile.h" #include "prune-packed.h" -#include "object-store.h" +#include "odb.h" #include "promisor-remote.h" #include "shallow.h" #include "pack.h" diff --git a/builtin/replace.c b/builtin/replace.c index 48c7c6a2d5..11c7e2d4c0 100644 --- a/builtin/replace.c +++ b/builtin/replace.c @@ -19,7 +19,7 @@ #include "run-command.h" #include "object-file.h" #include "object-name.h" -#include "object-store.h" +#include "odb.h" #include "replace-object.h" #include "tag.h" #include "wildmatch.h" diff --git a/builtin/rev-list.c b/builtin/rev-list.c index 0984b607bf..0ee37a32cb 100644 --- a/builtin/rev-list.c +++ b/builtin/rev-list.c @@ -14,7 +14,7 @@ #include "object.h" #include "object-name.h" #include "object-file.h" -#include "object-store.h" +#include "odb.h" #include "pack-bitmap.h" #include "parse-options.h" #include "log-tree.h" diff --git a/builtin/show-ref.c b/builtin/show-ref.c index 623a52a45f..90ec1de78f 100644 --- a/builtin/show-ref.c +++ b/builtin/show-ref.c @@ -5,7 +5,7 @@ #include "hex.h" #include "refs/refs-internal.h" #include "object-name.h" -#include "object-store.h" +#include "odb.h" #include "object.h" #include "string-list.h" #include "parse-options.h" diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index 758bc6d0f2..84f7fa5342 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -28,7 +28,7 @@ #include "diff.h" #include "object-file.h" #include "object-name.h" -#include "object-store.h" +#include "odb.h" #include "advice.h" #include "branch.h" #include "list-objects-filter-options.h" diff --git a/builtin/tag.c b/builtin/tag.c index 4742b27d16..cf2ea4b499 100644 --- a/builtin/tag.c +++ b/builtin/tag.c @@ -19,7 +19,7 @@ #include "refs.h" #include "object-file.h" #include "object-name.h" -#include "object-store.h" +#include "odb.h" #include "path.h" #include "tag.h" #include "parse-options.h" diff --git a/builtin/unpack-file.c b/builtin/unpack-file.c index e33acfc4ee..b92fd4710a 100644 --- a/builtin/unpack-file.c +++ b/builtin/unpack-file.c @@ -4,7 +4,7 @@ #include "hex.h" #include "object-file.h" #include "object-name.h" -#include "object-store.h" +#include "odb.h" static char *create_temp_file(struct object_id *oid) { diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c index e905d5f4e1..7bf395eec8 100644 --- a/builtin/unpack-objects.c +++ b/builtin/unpack-objects.c @@ -9,7 +9,7 @@ #include "git-zlib.h" #include "hex.h" #include "object-file.h" -#include "object-store.h" +#include "odb.h" #include "object.h" #include "delta.h" #include "pack.h" diff --git a/bulk-checkin.c b/bulk-checkin.c index 678e2ecc2c..55406a539e 100644 --- a/bulk-checkin.c +++ b/bulk-checkin.c @@ -17,7 +17,7 @@ #include "tmp-objdir.h" #include "packfile.h" #include "object-file.h" -#include "object-store.h" +#include "odb.h" static int odb_transaction_nesting; diff --git a/bundle-uri.c b/bundle-uri.c index 9accf157b4..2e623f8627 100644 --- a/bundle-uri.c +++ b/bundle-uri.c @@ -14,7 +14,7 @@ #include "fetch-pack.h" #include "remote.h" #include "trace2.h" -#include "object-store.h" +#include "odb.h" static struct { enum bundle_list_heuristic heuristic; diff --git a/bundle.c b/bundle.c index 2ce7525f90..e09e3c2f58 100644 --- a/bundle.c +++ b/bundle.c @@ -7,7 +7,7 @@ #include "environment.h" #include "gettext.h" #include "hex.h" -#include "object-store.h" +#include "odb.h" #include "repository.h" #include "object.h" #include "commit.h" diff --git a/cache-tree.c b/cache-tree.c index fa3858e282..9786b32b3a 100644 --- a/cache-tree.c +++ b/cache-tree.c @@ -10,7 +10,7 @@ #include "cache-tree.h" #include "bulk-checkin.h" #include "object-file.h" -#include "object-store.h" +#include "odb.h" #include "read-cache-ll.h" #include "replace-object.h" #include "repository.h" diff --git a/combine-diff.c b/combine-diff.c index dfae9f7995..cf23a75340 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -2,7 +2,7 @@ #define DISABLE_SIGN_COMPARE_WARNINGS #include "git-compat-util.h" -#include "object-store.h" +#include "odb.h" #include "commit.h" #include "convert.h" #include "diff.h" diff --git a/commit-graph.c b/commit-graph.c index 12d32cdad1..6ced5b366e 100644 --- a/commit-graph.c +++ b/commit-graph.c @@ -13,7 +13,7 @@ #include "refs.h" #include "hash-lookup.h" #include "commit-graph.h" -#include "object-store.h" +#include "odb.h" #include "oid-array.h" #include "path.h" #include "alloc.h" diff --git a/commit-graph.h b/commit-graph.h index 0e661db1b5..78ab7b875b 100644 --- a/commit-graph.h +++ b/commit-graph.h @@ -1,7 +1,7 @@ #ifndef COMMIT_GRAPH_H #define COMMIT_GRAPH_H -#include "object-store.h" +#include "odb.h" #include "oidset.h" #define GIT_TEST_COMMIT_GRAPH "GIT_TEST_COMMIT_GRAPH" diff --git a/commit.c b/commit.c index e915b2b9a1..1d30f8ce15 100644 --- a/commit.c +++ b/commit.c @@ -9,7 +9,7 @@ #include "hex.h" #include "repository.h" #include "object-name.h" -#include "object-store.h" +#include "odb.h" #include "utf8.h" #include "diff.h" #include "revision.h" diff --git a/config.c b/config.c index b18b5617fc..883dd06682 100644 --- a/config.c +++ b/config.c @@ -31,7 +31,7 @@ #include "hashmap.h" #include "string-list.h" #include "object-name.h" -#include "object-store.h" +#include "odb.h" #include "pager.h" #include "path.h" #include "utf8.h" diff --git a/connected.c b/connected.c index 4415388beb..18c13245d8 100644 --- a/connected.c +++ b/connected.c @@ -3,7 +3,7 @@ #include "git-compat-util.h" #include "gettext.h" #include "hex.h" -#include "object-store.h" +#include "odb.h" #include "run-command.h" #include "sigchain.h" #include "connected.h" diff --git a/contrib/coccinelle/the_repository.cocci b/contrib/coccinelle/the_repository.cocci index 765ad68967..ea7fe1c8db 100644 --- a/contrib/coccinelle/the_repository.cocci +++ b/contrib/coccinelle/the_repository.cocci @@ -77,7 +77,7 @@ | - diff_setup + repo_diff_setup -// object-store.h +// odb.h | - read_object_file + repo_read_object_file diff --git a/diagnose.c b/diagnose.c index d08d5643aa..ad0d5c1246 100644 --- a/diagnose.c +++ b/diagnose.c @@ -7,7 +7,7 @@ #include "gettext.h" #include "hex.h" #include "strvec.h" -#include "object-store.h" +#include "odb.h" #include "packfile.h" #include "parse-options.h" #include "repository.h" diff --git a/diff.c b/diff.c index 90e8003dd1..3af108115b 100644 --- a/diff.c +++ b/diff.c @@ -23,7 +23,7 @@ #include "color.h" #include "run-command.h" #include "utf8.h" -#include "object-store.h" +#include "odb.h" #include "userdiff.h" #include "submodule.h" #include "hashmap.h" diff --git a/entry.c b/entry.c index f36ec5ad24..75d55038d7 100644 --- a/entry.c +++ b/entry.c @@ -1,7 +1,7 @@ #define USE_THE_REPOSITORY_VARIABLE #include "git-compat-util.h" -#include "object-store.h" +#include "odb.h" #include "dir.h" #include "environment.h" #include "gettext.h" diff --git a/fetch-pack.c b/fetch-pack.c index fa4231fee7..cf157f5d7e 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -24,7 +24,7 @@ #include "oid-array.h" #include "oidset.h" #include "packfile.h" -#include "object-store.h" +#include "odb.h" #include "path.h" #include "connected.h" #include "fetch-negotiator.h" diff --git a/fmt-merge-msg.c b/fmt-merge-msg.c index 501b5acdd4..1a8c972adf 100644 --- a/fmt-merge-msg.c +++ b/fmt-merge-msg.c @@ -6,7 +6,7 @@ #include "environment.h" #include "refs.h" #include "object-name.h" -#include "object-store.h" +#include "odb.h" #include "diff.h" #include "diff-merges.h" #include "hex.h" diff --git a/fsck.c b/fsck.c index 8dc8472ceb..e69baab3af 100644 --- a/fsck.c +++ b/fsck.c @@ -4,7 +4,7 @@ #include "date.h" #include "dir.h" #include "hex.h" -#include "object-store.h" +#include "odb.h" #include "path.h" #include "repository.h" #include "object.h" diff --git a/grep.c b/grep.c index f8d535182c..dc77e6c463 100644 --- a/grep.c +++ b/grep.c @@ -5,7 +5,7 @@ #include "gettext.h" #include "grep.h" #include "hex.h" -#include "object-store.h" +#include "odb.h" #include "pretty.h" #include "userdiff.h" #include "xdiff-interface.h" diff --git a/http-backend.c b/http-backend.c index 0c575aa88a..ad8c403749 100644 --- a/http-backend.c +++ b/http-backend.c @@ -18,7 +18,7 @@ #include "url.h" #include "strvec.h" #include "packfile.h" -#include "object-store.h" +#include "odb.h" #include "protocol.h" #include "date.h" #include "write-or-die.h" diff --git a/http-push.c b/http-push.c index f9e67cabd4..d1b1bb2371 100644 --- a/http-push.c +++ b/http-push.c @@ -20,7 +20,7 @@ #include "url.h" #include "packfile.h" #include "object-file.h" -#include "object-store.h" +#include "odb.h" #include "commit-reach.h" #ifdef EXPAT_NEEDS_XMLPARSE_H diff --git a/http-walker.c b/http-walker.c index c374e6b205..05fb9ce714 100644 --- a/http-walker.c +++ b/http-walker.c @@ -10,7 +10,7 @@ #include "transport.h" #include "packfile.h" #include "object-file.h" -#include "object-store.h" +#include "odb.h" struct alt_base { char *base; diff --git a/http.c b/http.c index 5e15bbab3f..8f4f701a81 100644 --- a/http.c +++ b/http.c @@ -19,7 +19,7 @@ #include "packfile.h" #include "string-list.h" #include "object-file.h" -#include "object-store.h" +#include "odb.h" #include "tempfile.h" static struct trace_key trace_curl = TRACE_KEY_INIT(CURL); diff --git a/list-objects-filter.c b/list-objects-filter.c index 78b397bc19..80fe48a52c 100644 --- a/list-objects-filter.c +++ b/list-objects-filter.c @@ -12,7 +12,7 @@ #include "oidmap.h" #include "oidset.h" #include "object-name.h" -#include "object-store.h" +#include "odb.h" /* Remember to update object flag allocation in object.h */ /* diff --git a/list-objects.c b/list-objects.c index 597114281f..c50b957858 100644 --- a/list-objects.c +++ b/list-objects.c @@ -14,7 +14,7 @@ #include "list-objects-filter.h" #include "list-objects-filter-options.h" #include "packfile.h" -#include "object-store.h" +#include "odb.h" #include "trace.h" #include "environment.h" diff --git a/loose.c b/loose.c index fe65d5b9b0..fab4041c03 100644 --- a/loose.c +++ b/loose.c @@ -1,7 +1,7 @@ #include "git-compat-util.h" #include "hash.h" #include "path.h" -#include "object-store.h" +#include "odb.h" #include "hex.h" #include "repository.h" #include "wrapper.h" diff --git a/mailmap.c b/mailmap.c index 9e2642a043..b18e74c211 100644 --- a/mailmap.c +++ b/mailmap.c @@ -6,7 +6,7 @@ #include "string-list.h" #include "mailmap.h" #include "object-name.h" -#include "object-store.h" +#include "odb.h" #include "setup.h" char *git_mailmap_file; diff --git a/match-trees.c b/match-trees.c index 72922d5d64..4704f95c34 100644 --- a/match-trees.c +++ b/match-trees.c @@ -7,7 +7,7 @@ #include "tree.h" #include "tree-walk.h" #include "object-file.h" -#include "object-store.h" +#include "odb.h" #include "repository.h" static int score_missing(unsigned mode) diff --git a/merge-blobs.c b/merge-blobs.c index 53f36dbc17..ba8a3fdfd8 100644 --- a/merge-blobs.c +++ b/merge-blobs.c @@ -4,7 +4,7 @@ #include "merge-ll.h" #include "blob.h" #include "merge-blobs.h" -#include "object-store.h" +#include "odb.h" static int fill_mmfile_blob(mmfile_t *f, struct blob *obj) { diff --git a/merge-ort.c b/merge-ort.c index 47b3d1730e..9f693ab1d3 100644 --- a/merge-ort.c +++ b/merge-ort.c @@ -39,7 +39,7 @@ #include "mem-pool.h" #include "object-file.h" #include "object-name.h" -#include "object-store.h" +#include "odb.h" #include "oid-array.h" #include "path.h" #include "promisor-remote.h" diff --git a/meson.build b/meson.build index 596f5ac711..3fad0e3998 100644 --- a/meson.build +++ b/meson.build @@ -396,8 +396,8 @@ libgit_sources = [ 'object-file-convert.c', 'object-file.c', 'object-name.c', - 'object-store.c', 'object.c', + 'odb.c', 'oid-array.c', 'oidmap.c', 'oidset.c', diff --git a/notes-cache.c b/notes-cache.c index 150241b15e..344f67762b 100644 --- a/notes-cache.c +++ b/notes-cache.c @@ -3,7 +3,7 @@ #include "git-compat-util.h" #include "notes-cache.h" #include "object-file.h" -#include "object-store.h" +#include "odb.h" #include "pretty.h" #include "repository.h" #include "commit.h" diff --git a/notes-merge.c b/notes-merge.c index dae8e6a281..de6a52e2e7 100644 --- a/notes-merge.c +++ b/notes-merge.c @@ -8,7 +8,7 @@ #include "refs.h" #include "object-file.h" #include "object-name.h" -#include "object-store.h" +#include "odb.h" #include "path.h" #include "repository.h" #include "diff.h" diff --git a/notes.c b/notes.c index 0a128f1de9..fc000e501d 100644 --- a/notes.c +++ b/notes.c @@ -8,7 +8,7 @@ #include "notes.h" #include "object-file.h" #include "object-name.h" -#include "object-store.h" +#include "odb.h" #include "utf8.h" #include "strbuf.h" #include "tree-walk.h" diff --git a/object-file.c b/object-file.c index 6bad1d3dd1..2d3af8a77c 100644 --- a/object-file.c +++ b/object-file.c @@ -21,7 +21,7 @@ #include "loose.h" #include "object-file-convert.h" #include "object-file.h" -#include "object-store.h" +#include "odb.h" #include "oidtree.h" #include "pack.h" #include "packfile.h" diff --git a/object-file.h b/object-file.h index 9a18859b2e..5066638f8e 100644 --- a/object-file.h +++ b/object-file.h @@ -3,7 +3,7 @@ #include "git-zlib.h" #include "object.h" -#include "object-store.h" +#include "odb.h" struct index_state; diff --git a/object-store.c b/object-store.c deleted file mode 100644 index 5c04a1018f..0000000000 --- a/object-store.c +++ /dev/null @@ -1,1010 +0,0 @@ -#define USE_THE_REPOSITORY_VARIABLE - -#include "git-compat-util.h" -#include "abspath.h" -#include "commit-graph.h" -#include "config.h" -#include "dir.h" -#include "environment.h" -#include "gettext.h" -#include "hex.h" -#include "khash.h" -#include "lockfile.h" -#include "loose.h" -#include "object-file-convert.h" -#include "object-file.h" -#include "object-store.h" -#include "packfile.h" -#include "path.h" -#include "promisor-remote.h" -#include "quote.h" -#include "replace-object.h" -#include "run-command.h" -#include "setup.h" -#include "strbuf.h" -#include "strvec.h" -#include "submodule.h" -#include "write-or-die.h" - -KHASH_INIT(odb_path_map, const char * /* key: odb_path */, - struct odb_source *, 1, fspathhash, fspatheq) - -/* - * This is meant to hold a *small* number of objects that you would - * want repo_read_object_file() to be able to return, but yet you do not want - * to write them into the object store (e.g. a browse-only - * application). - */ -struct cached_object_entry { - struct object_id oid; - struct cached_object { - enum object_type type; - const void *buf; - unsigned long size; - } value; -}; - -static const struct cached_object *find_cached_object(struct object_database *object_store, - const struct object_id *oid) -{ - static const struct cached_object empty_tree = { - .type = OBJ_TREE, - .buf = "", - }; - const struct cached_object_entry *co = object_store->cached_objects; - - for (size_t i = 0; i < object_store->cached_object_nr; i++, co++) - if (oideq(&co->oid, oid)) - return &co->value; - - if (oid->algo && oideq(oid, hash_algos[oid->algo].empty_tree)) - return &empty_tree; - - return NULL; -} - -int odb_mkstemp(struct strbuf *temp_filename, const char *pattern) -{ - int fd; - /* - * we let the umask do its job, don't try to be more - * restrictive except to remove write permission. - */ - int mode = 0444; - repo_git_path_replace(the_repository, temp_filename, "objects/%s", pattern); - fd = git_mkstemp_mode(temp_filename->buf, mode); - if (0 <= fd) - return fd; - - /* slow path */ - /* some mkstemp implementations erase temp_filename on failure */ - repo_git_path_replace(the_repository, temp_filename, "objects/%s", pattern); - safe_create_leading_directories(the_repository, temp_filename->buf); - return xmkstemp_mode(temp_filename->buf, mode); -} - -/* - * Return non-zero iff the path is usable as an alternate object database. - */ -static int alt_odb_usable(struct object_database *o, - struct strbuf *path, - const char *normalized_objdir, khiter_t *pos) -{ - int r; - - /* Detect cases where alternate disappeared */ - if (!is_directory(path->buf)) { - error(_("object directory %s does not exist; " - "check .git/objects/info/alternates"), - path->buf); - return 0; - } - - /* - * Prevent the common mistake of listing the same - * thing twice, or object directory itself. - */ - if (!o->source_by_path) { - khiter_t p; - - o->source_by_path = kh_init_odb_path_map(); - assert(!o->sources->next); - p = kh_put_odb_path_map(o->source_by_path, o->sources->path, &r); - assert(r == 1); /* never used */ - kh_value(o->source_by_path, p) = o->sources; - } - if (fspatheq(path->buf, normalized_objdir)) - return 0; - *pos = kh_put_odb_path_map(o->source_by_path, path->buf, &r); - /* r: 0 = exists, 1 = never used, 2 = deleted */ - return r == 0 ? 0 : 1; -} - -/* - * Prepare alternate object database registry. - * - * The variable alt_odb_list points at the list of struct - * odb_source. The elements on this list come from - * non-empty elements from colon separated ALTERNATE_DB_ENVIRONMENT - * environment variable, and $GIT_OBJECT_DIRECTORY/info/alternates, - * whose contents is similar to that environment variable but can be - * LF separated. Its base points at a statically allocated buffer that - * contains "/the/directory/corresponding/to/.git/objects/...", while - * its name points just after the slash at the end of ".git/objects/" - * in the example above, and has enough space to hold all hex characters - * of the object ID, an extra slash for the first level indirection, and - * the terminating NUL. - */ -static void read_info_alternates(struct repository *r, - const char *relative_base, - int depth); -static int link_alt_odb_entry(struct repository *r, const struct strbuf *entry, - const char *relative_base, int depth, const char *normalized_objdir) -{ - struct odb_source *alternate; - struct strbuf pathbuf = STRBUF_INIT; - struct strbuf tmp = STRBUF_INIT; - khiter_t pos; - int ret = -1; - - if (!is_absolute_path(entry->buf) && relative_base) { - strbuf_realpath(&pathbuf, relative_base, 1); - strbuf_addch(&pathbuf, '/'); - } - strbuf_addbuf(&pathbuf, entry); - - if (!strbuf_realpath(&tmp, pathbuf.buf, 0)) { - error(_("unable to normalize alternate object path: %s"), - pathbuf.buf); - goto error; - } - strbuf_swap(&pathbuf, &tmp); - - /* - * The trailing slash after the directory name is given by - * this function at the end. Remove duplicates. - */ - while (pathbuf.len && pathbuf.buf[pathbuf.len - 1] == '/') - strbuf_setlen(&pathbuf, pathbuf.len - 1); - - if (!alt_odb_usable(r->objects, &pathbuf, normalized_objdir, &pos)) - goto error; - - CALLOC_ARRAY(alternate, 1); - /* pathbuf.buf is already in r->objects->source_by_path */ - alternate->path = strbuf_detach(&pathbuf, NULL); - - /* add the alternate entry */ - *r->objects->sources_tail = alternate; - r->objects->sources_tail = &(alternate->next); - alternate->next = NULL; - assert(r->objects->source_by_path); - kh_value(r->objects->source_by_path, pos) = alternate; - - /* recursively add alternates */ - read_info_alternates(r, alternate->path, depth + 1); - ret = 0; - error: - strbuf_release(&tmp); - strbuf_release(&pathbuf); - return ret; -} - -static const char *parse_alt_odb_entry(const char *string, - int sep, - struct strbuf *out) -{ - const char *end; - - strbuf_reset(out); - - if (*string == '#') { - /* comment; consume up to next separator */ - end = strchrnul(string, sep); - } else if (*string == '"' && !unquote_c_style(out, 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(out, string, end - string); - } - - if (*end) - end++; - return end; -} - -static void link_alt_odb_entries(struct repository *r, const char *alt, - int sep, const char *relative_base, int depth) -{ - struct strbuf objdirbuf = STRBUF_INIT; - struct strbuf entry = STRBUF_INIT; - - if (!alt || !*alt) - return; - - if (depth > 5) { - error(_("%s: ignoring alternate object stores, nesting too deep"), - relative_base); - return; - } - - strbuf_realpath(&objdirbuf, r->objects->sources->path, 1); - - while (*alt) { - alt = parse_alt_odb_entry(alt, sep, &entry); - if (!entry.len) - continue; - link_alt_odb_entry(r, &entry, - relative_base, depth, objdirbuf.buf); - } - strbuf_release(&entry); - strbuf_release(&objdirbuf); -} - -static void read_info_alternates(struct repository *r, - const char *relative_base, - int depth) -{ - char *path; - struct strbuf buf = STRBUF_INIT; - - path = xstrfmt("%s/info/alternates", relative_base); - if (strbuf_read_file(&buf, path, 1024) < 0) { - warn_on_fopen_errors(path); - free(path); - return; - } - - link_alt_odb_entries(r, buf.buf, '\n', relative_base, depth); - strbuf_release(&buf); - free(path); -} - -void add_to_alternates_file(const char *reference) -{ - struct lock_file lock = LOCK_INIT; - char *alts = repo_git_path(the_repository, "objects/info/alternates"); - FILE *in, *out; - int found = 0; - - hold_lock_file_for_update(&lock, alts, LOCK_DIE_ON_ERROR); - out = fdopen_lock_file(&lock, "w"); - if (!out) - die_errno(_("unable to fdopen alternates lockfile")); - - in = fopen(alts, "r"); - if (in) { - struct strbuf line = STRBUF_INIT; - - while (strbuf_getline(&line, in) != EOF) { - if (!strcmp(reference, line.buf)) { - found = 1; - break; - } - fprintf_or_die(out, "%s\n", line.buf); - } - - strbuf_release(&line); - fclose(in); - } - else if (errno != ENOENT) - die_errno(_("unable to read alternates file")); - - if (found) { - rollback_lock_file(&lock); - } else { - fprintf_or_die(out, "%s\n", reference); - if (commit_lock_file(&lock)) - die_errno(_("unable to move new alternates file into place")); - if (the_repository->objects->loaded_alternates) - link_alt_odb_entries(the_repository, reference, - '\n', NULL, 0); - } - free(alts); -} - -void add_to_alternates_memory(const char *reference) -{ - /* - * Make sure alternates are initialized, or else our entry may be - * overwritten when they are. - */ - prepare_alt_odb(the_repository); - - link_alt_odb_entries(the_repository, reference, - '\n', NULL, 0); -} - -struct odb_source *set_temporary_primary_odb(const char *dir, int will_destroy) -{ - struct odb_source *source; - - /* - * Make sure alternates are initialized, or else our entry may be - * overwritten when they are. - */ - prepare_alt_odb(the_repository); - - /* - * Make a new primary odb and link the old primary ODB in as an - * alternate - */ - source = xcalloc(1, sizeof(*source)); - source->path = xstrdup(dir); - - /* - * Disable ref updates while a temporary odb is active, since - * the objects in the database may roll back. - */ - source->disable_ref_updates = 1; - source->will_destroy = will_destroy; - source->next = the_repository->objects->sources; - the_repository->objects->sources = source; - return source->next; -} - -static void free_object_directory(struct odb_source *source) -{ - free(source->path); - odb_clear_loose_cache(source); - loose_object_map_clear(&source->loose_map); - free(source); -} - -void restore_primary_odb(struct odb_source *restore_alt, const char *old_path) -{ - struct odb_source *cur_alt = the_repository->objects->sources; - - if (strcmp(old_path, cur_alt->path)) - BUG("expected %s as primary object store; found %s", - old_path, cur_alt->path); - - if (cur_alt->next != restore_alt) - BUG("we expect the old primary object store to be the first alternate"); - - the_repository->objects->sources = restore_alt; - free_object_directory(cur_alt); -} - -/* - * Compute the exact path an alternate is at and returns it. In case of - * error NULL is returned and the human readable error is added to `err` - * `path` may be relative and should point to $GIT_DIR. - * `err` must not be null. - */ -char *compute_alternate_path(const char *path, struct strbuf *err) -{ - char *ref_git = NULL; - const char *repo; - int seen_error = 0; - - ref_git = real_pathdup(path, 0); - if (!ref_git) { - seen_error = 1; - strbuf_addf(err, _("path '%s' does not exist"), path); - goto out; - } - - repo = read_gitfile(ref_git); - if (!repo) - repo = read_gitfile(mkpath("%s/.git", ref_git)); - if (repo) { - free(ref_git); - ref_git = xstrdup(repo); - } - - if (!repo && is_directory(mkpath("%s/.git/objects", ref_git))) { - char *ref_git_git = mkpathdup("%s/.git", ref_git); - free(ref_git); - ref_git = ref_git_git; - } else if (!is_directory(mkpath("%s/objects", ref_git))) { - struct strbuf sb = STRBUF_INIT; - seen_error = 1; - if (get_common_dir(&sb, ref_git)) { - strbuf_addf(err, - _("reference repository '%s' as a linked " - "checkout is not supported yet."), - path); - goto out; - } - - strbuf_addf(err, _("reference repository '%s' is not a " - "local repository."), path); - goto out; - } - - if (!access(mkpath("%s/shallow", ref_git), F_OK)) { - strbuf_addf(err, _("reference repository '%s' is shallow"), - path); - seen_error = 1; - goto out; - } - - if (!access(mkpath("%s/info/grafts", ref_git), F_OK)) { - strbuf_addf(err, - _("reference repository '%s' is grafted"), - path); - seen_error = 1; - goto out; - } - -out: - if (seen_error) { - FREE_AND_NULL(ref_git); - } - - return ref_git; -} - -struct odb_source *find_odb(struct repository *r, const char *obj_dir) -{ - struct odb_source *source; - char *obj_dir_real = real_pathdup(obj_dir, 1); - struct strbuf odb_path_real = STRBUF_INIT; - - prepare_alt_odb(r); - for (source = r->objects->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); - - if (!source) - die(_("could not find object directory matching %s"), obj_dir); - return source; -} - -static void fill_alternate_refs_command(struct child_process *cmd, - const char *repo_path) -{ - const char *value; - - if (!git_config_get_value("core.alternateRefsCommand", &value)) { - cmd->use_shell = 1; - - strvec_push(&cmd->args, value); - strvec_push(&cmd->args, repo_path); - } else { - cmd->git_cmd = 1; - - strvec_pushf(&cmd->args, "--git-dir=%s", repo_path); - strvec_push(&cmd->args, "for-each-ref"); - strvec_push(&cmd->args, "--format=%(objectname)"); - - if (!git_config_get_value("core.alternateRefsPrefixes", &value)) { - strvec_push(&cmd->args, "--"); - strvec_split(&cmd->args, value); - } - } - - strvec_pushv(&cmd->env, (const char **)local_repo_env); - cmd->out = -1; -} - -static void read_alternate_refs(const char *path, - alternate_ref_fn *cb, - void *data) -{ - struct child_process cmd = CHILD_PROCESS_INIT; - struct strbuf line = STRBUF_INIT; - FILE *fh; - - fill_alternate_refs_command(&cmd, path); - - if (start_command(&cmd)) - return; - - fh = xfdopen(cmd.out, "r"); - while (strbuf_getline_lf(&line, fh) != EOF) { - struct object_id oid; - const char *p; - - if (parse_oid_hex(line.buf, &oid, &p) || *p) { - warning(_("invalid line while parsing alternate refs: %s"), - line.buf); - break; - } - - cb(&oid, data); - } - - fclose(fh); - finish_command(&cmd); - strbuf_release(&line); -} - -struct alternate_refs_data { - alternate_ref_fn *fn; - void *data; -}; - -static int refs_from_alternate_cb(struct odb_source *alternate, - void *data) -{ - struct strbuf path = STRBUF_INIT; - size_t base_len; - struct alternate_refs_data *cb = data; - - if (!strbuf_realpath(&path, alternate->path, 0)) - goto out; - if (!strbuf_strip_suffix(&path, "/objects")) - goto out; - base_len = path.len; - - /* Is this a git repository with refs? */ - strbuf_addstr(&path, "/refs"); - if (!is_directory(path.buf)) - goto out; - strbuf_setlen(&path, base_len); - - read_alternate_refs(path.buf, cb->fn, cb->data); - -out: - strbuf_release(&path); - return 0; -} - -void for_each_alternate_ref(alternate_ref_fn fn, void *data) -{ - struct alternate_refs_data cb; - cb.fn = fn; - cb.data = data; - foreach_alt_odb(refs_from_alternate_cb, &cb); -} - -int foreach_alt_odb(alt_odb_fn fn, void *cb) -{ - struct odb_source *alternate; - int r = 0; - - prepare_alt_odb(the_repository); - for (alternate = the_repository->objects->sources->next; alternate; alternate = alternate->next) { - r = fn(alternate, cb); - if (r) - break; - } - return r; -} - -void prepare_alt_odb(struct repository *r) -{ - if (r->objects->loaded_alternates) - return; - - link_alt_odb_entries(r, r->objects->alternate_db, PATH_SEP, NULL, 0); - - read_info_alternates(r, r->objects->sources->path, 0); - r->objects->loaded_alternates = 1; -} - -int has_alt_odb(struct repository *r) -{ - prepare_alt_odb(r); - return !!r->objects->sources->next; -} - -int obj_read_use_lock = 0; -pthread_mutex_t obj_read_mutex; - -void enable_obj_read_lock(void) -{ - if (obj_read_use_lock) - return; - - obj_read_use_lock = 1; - init_recursive_mutex(&obj_read_mutex); -} - -void disable_obj_read_lock(void) -{ - if (!obj_read_use_lock) - return; - - obj_read_use_lock = 0; - pthread_mutex_destroy(&obj_read_mutex); -} - -int fetch_if_missing = 1; - -static int do_oid_object_info_extended(struct repository *r, - const struct object_id *oid, - struct object_info *oi, unsigned flags) -{ - static struct object_info blank_oi = OBJECT_INFO_INIT; - const struct cached_object *co; - struct pack_entry e; - int rtype; - const struct object_id *real = oid; - int already_retried = 0; - - - if (flags & OBJECT_INFO_LOOKUP_REPLACE) - real = lookup_replace_object(r, oid); - - if (is_null_oid(real)) - return -1; - - if (!oi) - oi = &blank_oi; - - co = find_cached_object(r->objects, real); - if (co) { - if (oi->typep) - *(oi->typep) = co->type; - if (oi->sizep) - *(oi->sizep) = co->size; - if (oi->disk_sizep) - *(oi->disk_sizep) = 0; - if (oi->delta_base_oid) - oidclr(oi->delta_base_oid, the_repository->hash_algo); - if (oi->contentp) - *oi->contentp = xmemdupz(co->buf, co->size); - oi->whence = OI_CACHED; - return 0; - } - - while (1) { - if (find_pack_entry(r, real, &e)) - break; - - /* Most likely it's a loose object. */ - if (!loose_object_info(r, real, oi, flags)) - return 0; - - /* Not a loose object; someone else may have just packed it. */ - if (!(flags & OBJECT_INFO_QUICK)) { - reprepare_packed_git(r); - if (find_pack_entry(r, real, &e)) - break; - } - - /* - * If r is the_repository, this might be an attempt at - * accessing a submodule object as if it were in the_repository - * (having called add_submodule_odb() on that submodule's ODB). - * If any such ODBs exist, register them and try again. - */ - if (r == the_repository && - register_all_submodule_odb_as_alternates()) - /* We added some alternates; retry */ - continue; - - /* Check if it is a missing object */ - if (fetch_if_missing && repo_has_promisor_remote(r) && - !already_retried && - !(flags & OBJECT_INFO_SKIP_FETCH_OBJECT)) { - promisor_remote_get_direct(r, real, 1); - already_retried = 1; - continue; - } - - if (flags & OBJECT_INFO_DIE_IF_CORRUPT) { - const struct packed_git *p; - if ((flags & OBJECT_INFO_LOOKUP_REPLACE) && !oideq(real, oid)) - die(_("replacement %s not found for %s"), - oid_to_hex(real), oid_to_hex(oid)); - if ((p = has_packed_and_bad(r, real))) - die(_("packed object %s (stored in %s) is corrupt"), - oid_to_hex(real), p->pack_name); - } - return -1; - } - - if (oi == &blank_oi) - /* - * We know that the caller doesn't actually need the - * information below, so return early. - */ - return 0; - rtype = packed_object_info(r, e.p, e.offset, oi); - if (rtype < 0) { - mark_bad_packed_object(e.p, real); - return do_oid_object_info_extended(r, real, oi, 0); - } else if (oi->whence == OI_PACKED) { - oi->u.packed.offset = e.offset; - oi->u.packed.pack = e.p; - oi->u.packed.is_delta = (rtype == OBJ_REF_DELTA || - rtype == OBJ_OFS_DELTA); - } - - return 0; -} - -static int oid_object_info_convert(struct repository *r, - const struct object_id *input_oid, - struct object_info *input_oi, unsigned flags) -{ - const struct git_hash_algo *input_algo = &hash_algos[input_oid->algo]; - int do_die = flags & OBJECT_INFO_DIE_IF_CORRUPT; - enum object_type type; - struct object_id oid, delta_base_oid; - struct object_info new_oi, *oi; - unsigned long size; - void *content; - int ret; - - if (repo_oid_to_algop(r, input_oid, the_hash_algo, &oid)) { - if (do_die) - die(_("missing mapping of %s to %s"), - oid_to_hex(input_oid), the_hash_algo->name); - return -1; - } - - /* Is new_oi needed? */ - oi = input_oi; - if (input_oi && (input_oi->delta_base_oid || input_oi->sizep || - input_oi->contentp)) { - new_oi = *input_oi; - /* Does delta_base_oid need to be converted? */ - if (input_oi->delta_base_oid) - new_oi.delta_base_oid = &delta_base_oid; - /* Will the attributes differ when converted? */ - if (input_oi->sizep || input_oi->contentp) { - new_oi.contentp = &content; - new_oi.sizep = &size; - new_oi.typep = &type; - } - oi = &new_oi; - } - - ret = oid_object_info_extended(r, &oid, oi, flags); - if (ret) - return -1; - if (oi == input_oi) - return ret; - - if (new_oi.contentp) { - struct strbuf outbuf = STRBUF_INIT; - - if (type != OBJ_BLOB) { - ret = convert_object_file(the_repository, &outbuf, - the_hash_algo, input_algo, - content, size, type, !do_die); - free(content); - if (ret == -1) - return -1; - size = outbuf.len; - content = strbuf_detach(&outbuf, NULL); - } - if (input_oi->sizep) - *input_oi->sizep = size; - if (input_oi->contentp) - *input_oi->contentp = content; - else - free(content); - if (input_oi->typep) - *input_oi->typep = type; - } - if (new_oi.delta_base_oid == &delta_base_oid) { - if (repo_oid_to_algop(r, &delta_base_oid, input_algo, - input_oi->delta_base_oid)) { - if (do_die) - die(_("missing mapping of %s to %s"), - oid_to_hex(&delta_base_oid), - input_algo->name); - return -1; - } - } - input_oi->whence = new_oi.whence; - input_oi->u = new_oi.u; - return ret; -} - -int oid_object_info_extended(struct repository *r, const struct object_id *oid, - struct object_info *oi, unsigned flags) -{ - int ret; - - if (oid->algo && (hash_algo_by_ptr(r->hash_algo) != oid->algo)) - return oid_object_info_convert(r, oid, oi, flags); - - obj_read_lock(); - ret = do_oid_object_info_extended(r, oid, oi, flags); - obj_read_unlock(); - return ret; -} - - -/* returns enum object_type or negative */ -int oid_object_info(struct repository *r, - const struct object_id *oid, - unsigned long *sizep) -{ - enum object_type type; - struct object_info oi = OBJECT_INFO_INIT; - - oi.typep = &type; - oi.sizep = sizep; - if (oid_object_info_extended(r, oid, &oi, - OBJECT_INFO_LOOKUP_REPLACE) < 0) - return -1; - return type; -} - -int pretend_object_file(struct repository *repo, - void *buf, unsigned long len, enum object_type type, - struct object_id *oid) -{ - struct cached_object_entry *co; - char *co_buf; - - hash_object_file(repo->hash_algo, buf, len, type, oid); - if (has_object(repo, oid, 0) || - find_cached_object(repo->objects, oid)) - return 0; - - ALLOC_GROW(repo->objects->cached_objects, - repo->objects->cached_object_nr + 1, repo->objects->cached_object_alloc); - co = &repo->objects->cached_objects[repo->objects->cached_object_nr++]; - co->value.size = len; - co->value.type = type; - co_buf = xmalloc(len); - memcpy(co_buf, buf, len); - co->value.buf = co_buf; - oidcpy(&co->oid, oid); - return 0; -} - -/* - * This function dies on corrupt objects; the callers who want to - * deal with them should arrange to call oid_object_info_extended() and give - * error messages themselves. - */ -void *repo_read_object_file(struct repository *r, - const struct object_id *oid, - enum object_type *type, - unsigned long *size) -{ - struct object_info oi = OBJECT_INFO_INIT; - unsigned flags = OBJECT_INFO_DIE_IF_CORRUPT | OBJECT_INFO_LOOKUP_REPLACE; - void *data; - - oi.typep = type; - oi.sizep = size; - oi.contentp = &data; - if (oid_object_info_extended(r, oid, &oi, flags)) - return NULL; - - return data; -} - -void *read_object_with_reference(struct repository *r, - const struct object_id *oid, - enum object_type required_type, - unsigned long *size, - struct object_id *actual_oid_return) -{ - enum object_type type; - void *buffer; - unsigned long isize; - struct object_id actual_oid; - - oidcpy(&actual_oid, oid); - while (1) { - int ref_length = -1; - const char *ref_type = NULL; - - buffer = repo_read_object_file(r, &actual_oid, &type, &isize); - if (!buffer) - return NULL; - if (type == required_type) { - *size = isize; - if (actual_oid_return) - oidcpy(actual_oid_return, &actual_oid); - return buffer; - } - /* Handle references */ - else if (type == OBJ_COMMIT) - ref_type = "tree "; - else if (type == OBJ_TAG) - ref_type = "object "; - else { - free(buffer); - return NULL; - } - ref_length = strlen(ref_type); - - if (ref_length + the_hash_algo->hexsz > isize || - memcmp(buffer, ref_type, ref_length) || - get_oid_hex((char *) buffer + ref_length, &actual_oid)) { - free(buffer); - return NULL; - } - free(buffer); - /* Now we have the ID of the referred-to object in - * actual_oid. Check again. */ - } -} - -int has_object(struct repository *r, const struct object_id *oid, - unsigned flags) -{ - unsigned object_info_flags = 0; - - if (!startup_info->have_repository) - return 0; - if (!(flags & HAS_OBJECT_RECHECK_PACKED)) - object_info_flags |= OBJECT_INFO_QUICK; - if (!(flags & HAS_OBJECT_FETCH_PROMISOR)) - object_info_flags |= OBJECT_INFO_SKIP_FETCH_OBJECT; - - return oid_object_info_extended(r, oid, NULL, object_info_flags) >= 0; -} - -void assert_oid_type(const struct object_id *oid, enum object_type expect) -{ - enum object_type type = oid_object_info(the_repository, oid, NULL); - if (type < 0) - die(_("%s is not a valid object"), oid_to_hex(oid)); - if (type != expect) - die(_("%s is not a valid '%s' object"), oid_to_hex(oid), - type_name(expect)); -} - -struct object_database *odb_new(void) -{ - struct object_database *o = xmalloc(sizeof(*o)); - - memset(o, 0, sizeof(*o)); - INIT_LIST_HEAD(&o->packed_git_mru); - hashmap_init(&o->pack_map, pack_map_entry_cmp, NULL, 0); - pthread_mutex_init(&o->replace_mutex, NULL); - return o; -} - -static void free_object_directories(struct object_database *o) -{ - while (o->sources) { - struct odb_source *next; - - next = o->sources->next; - free_object_directory(o->sources); - o->sources = next; - } - kh_destroy_odb_path_map(o->source_by_path); - o->source_by_path = NULL; -} - -void odb_clear(struct object_database *o) -{ - FREE_AND_NULL(o->alternate_db); - - oidmap_clear(&o->replace_map, 1); - pthread_mutex_destroy(&o->replace_mutex); - - free_commit_graph(o->commit_graph); - o->commit_graph = NULL; - o->commit_graph_attempted = 0; - - free_object_directories(o); - o->sources_tail = NULL; - o->loaded_alternates = 0; - - for (size_t i = 0; i < o->cached_object_nr; i++) - free((char *) o->cached_objects[i].value.buf); - FREE_AND_NULL(o->cached_objects); - - INIT_LIST_HEAD(&o->packed_git_mru); - close_object_store(o); - - /* - * `close_object_store()` only closes the packfiles, but doesn't free - * them. We thus have to do this manually. - */ - for (struct packed_git *p = o->packed_git, *next; p; p = next) { - next = p->next; - free(p); - } - o->packed_git = NULL; - - hashmap_clear(&o->pack_map); -} diff --git a/object-store.h b/object-store.h deleted file mode 100644 index d199d757d7..0000000000 --- a/object-store.h +++ /dev/null @@ -1,355 +0,0 @@ -#ifndef OBJECT_STORE_H -#define OBJECT_STORE_H - -#include "hashmap.h" -#include "object.h" -#include "list.h" -#include "oidset.h" -#include "oidmap.h" -#include "thread-utils.h" - -struct oidmap; -struct oidtree; -struct strbuf; -struct repository; - -/* - * 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. - */ -struct odb_source { - struct odb_source *next; - - /* - * Used to store the results of readdir(3) calls when we are OK - * sacrificing accuracy due to races for speed. That includes - * object existence with OBJECT_INFO_QUICK, as well as - * our search for unique abbreviated hashes. Don't use it for tasks - * requiring greater accuracy! - * - * Be sure to call odb_load_loose_cache() before using. - */ - uint32_t loose_objects_subdir_seen[8]; /* 256 bits */ - struct oidtree *loose_objects_cache; - - /* Map between object IDs for loose objects. */ - struct loose_object_map *loose_map; - - /* - * This is a temporary object store created by the tmp_objdir - * facility. Disable ref updates since the objects in the store - * might be discarded on rollback. - */ - int disable_ref_updates; - - /* - * 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. - */ - char *path; -}; - -void prepare_alt_odb(struct repository *r); -int has_alt_odb(struct repository *r); -char *compute_alternate_path(const char *path, struct strbuf *err); -struct odb_source *find_odb(struct repository *r, const char *obj_dir); -typedef int alt_odb_fn(struct odb_source *, void *); -int foreach_alt_odb(alt_odb_fn, void*); -typedef void alternate_ref_fn(const struct object_id *oid, void *); -void for_each_alternate_ref(alternate_ref_fn, void *); - -/* - * Add the directory to the on-disk alternates file; the new entry will also - * take effect in the current process. - */ -void add_to_alternates_file(const char *dir); - -/* - * Add the directory to the in-memory list of alternates (along with any - * recursive alternates it points to), but do not modify the on-disk alternates - * file. - */ -void add_to_alternates_memory(const char *dir); - -/* - * Replace the current writable object directory with the specified temporary - * object directory; returns the former primary object directory. - */ -struct odb_source *set_temporary_primary_odb(const char *dir, int will_destroy); - -/* - * Restore a previous ODB replaced by set_temporary_main_odb. - */ -void restore_primary_odb(struct odb_source *restore_alternate, const char *old_path); - -struct packed_git; -struct multi_pack_index; -struct cached_object_entry; - -/* - * 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. - */ -struct object_database { - /* - * 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; - struct kh_odb_path_map *source_by_path; - - int loaded_alternates; - - /* - * A list of alternate object directories loaded from the environment; - * this should not generally need to be accessed directly, but will - * populate the "sources" list when prepare_alt_odb() is run. - */ - char *alternate_db; - - /* - * Objects that should be substituted by other objects - * (see git-replace(1)). - */ - struct oidmap replace_map; - unsigned replace_map_initialized : 1; - pthread_mutex_t replace_mutex; /* protect object replace functions */ - - struct commit_graph *commit_graph; - unsigned commit_graph_attempted : 1; /* if loading has been attempted */ - - /* - * private data - * - * should only be accessed directly by packfile.c and midx.c - */ - struct multi_pack_index *multi_pack_index; - - /* - * private data - * - * should only be accessed directly by packfile.c - */ - - struct packed_git *packed_git; - /* A most-recently-used ordered version of the packed_git list. */ - struct list_head packed_git_mru; - - struct { - struct packed_git **packs; - unsigned flags; - } kept_pack_cache; - - /* - * This is meant to hold a *small* number of objects that you would - * want repo_read_object_file() to be able to return, but yet you do not want - * to write them into the object store (e.g. a browse-only - * application). - */ - struct cached_object_entry *cached_objects; - size_t cached_object_nr, cached_object_alloc; - - /* - * A map of packfiles to packed_git structs for tracking which - * packs have been loaded already. - */ - struct hashmap pack_map; - - /* - * A fast, rough count of the number of objects in the repository. - * These two fields are not meant for direct access. Use - * repo_approximate_object_count() instead. - */ - unsigned long approximate_object_count; - unsigned approximate_object_count_valid : 1; - - /* - * Whether packed_git has already been populated with this repository's - * packs. - */ - unsigned packed_git_initialized : 1; -}; - -struct object_database *odb_new(void); -void odb_clear(struct object_database *o); - -/* - * Create a temporary file rooted in the object database directory, or - * die on failure. The filename is taken from "pattern", which should have the - * usual "XXXXXX" trailer, and the resulting filename is written into the - * "template" buffer. Returns the open descriptor. - */ -int odb_mkstemp(struct strbuf *temp_filename, const char *pattern); - -void *repo_read_object_file(struct repository *r, - const struct object_id *oid, - enum object_type *type, - unsigned long *size); - -/* Read and unpack an object file into memory, write memory to an object file */ -int oid_object_info(struct repository *r, const struct object_id *, unsigned long *); - -/* - * Add an object file to the in-memory object store, without writing it - * to disk. - * - * Callers are responsible for calling write_object_file to record the - * object in persistent storage before writing any other new objects - * that reference it. - */ -int pretend_object_file(struct repository *repo, - void *buf, unsigned long len, enum object_type type, - struct object_id *oid); - -struct object_info { - /* Request */ - enum object_type *typep; - unsigned long *sizep; - off_t *disk_sizep; - struct object_id *delta_base_oid; - void **contentp; - - /* Response */ - enum { - OI_CACHED, - OI_LOOSE, - OI_PACKED, - OI_DBCACHED - } whence; - union { - /* - * struct { - * ... Nothing to expose in this case - * } cached; - * struct { - * ... Nothing to expose in this case - * } loose; - */ - struct { - struct packed_git *pack; - off_t offset; - unsigned int is_delta; - } packed; - } u; -}; - -/* - * Initializer for a "struct object_info" that wants no items. You may - * also memset() the memory to all-zeroes. - */ -#define OBJECT_INFO_INIT { 0 } - -/* Invoke lookup_replace_object() on the given hash */ -#define OBJECT_INFO_LOOKUP_REPLACE 1 -/* Do not retry packed storage after checking packed and loose storage */ -#define OBJECT_INFO_QUICK 8 -/* - * Do not attempt to fetch the object if missing (even if fetch_is_missing is - * nonzero). - */ -#define OBJECT_INFO_SKIP_FETCH_OBJECT 16 -/* - * This is meant for bulk prefetching of missing blobs in a partial - * clone. Implies OBJECT_INFO_SKIP_FETCH_OBJECT and OBJECT_INFO_QUICK - */ -#define OBJECT_INFO_FOR_PREFETCH (OBJECT_INFO_SKIP_FETCH_OBJECT | OBJECT_INFO_QUICK) - -/* Die if object corruption (not just an object being missing) was detected. */ -#define OBJECT_INFO_DIE_IF_CORRUPT 32 - -int oid_object_info_extended(struct repository *r, - const struct object_id *, - struct object_info *, unsigned flags); - -enum { - /* Retry packed storage after checking packed and loose storage */ - HAS_OBJECT_RECHECK_PACKED = (1 << 0), - /* Allow fetching the object in case the repository has a promisor remote. */ - HAS_OBJECT_FETCH_PROMISOR = (1 << 1), -}; - -/* - * Returns 1 if the object exists. This function will not lazily fetch objects - * in a partial clone by default. - */ -int has_object(struct repository *r, const struct object_id *oid, - unsigned flags); - -void assert_oid_type(const struct object_id *oid, enum object_type expect); - -/* - * Enabling the object read lock allows multiple threads to safely call the - * following functions in parallel: repo_read_object_file(), - * read_object_with_reference(), oid_object_info() and oid_object_info_extended(). - * - * obj_read_lock() and obj_read_unlock() may also be used to protect other - * section which cannot execute in parallel with object reading. Since the used - * lock is a recursive mutex, these sections can even contain calls to object - * reading functions. However, beware that in these cases zlib inflation won't - * be performed in parallel, losing performance. - * - * TODO: oid_object_info_extended()'s call stack has a recursive behavior. If - * any of its callees end up calling it, this recursive call won't benefit from - * parallel inflation. - */ -void enable_obj_read_lock(void); -void disable_obj_read_lock(void); - -extern int obj_read_use_lock; -extern pthread_mutex_t obj_read_mutex; - -static inline void obj_read_lock(void) -{ - if(obj_read_use_lock) - pthread_mutex_lock(&obj_read_mutex); -} - -static inline void obj_read_unlock(void) -{ - if(obj_read_use_lock) - pthread_mutex_unlock(&obj_read_mutex); -} -/* Flags for for_each_*_object(). */ -enum for_each_object_flags { - /* Iterate only over local objects, not alternates. */ - FOR_EACH_OBJECT_LOCAL_ONLY = (1<<0), - - /* Only iterate over packs obtained from the promisor remote. */ - FOR_EACH_OBJECT_PROMISOR_ONLY = (1<<1), - - /* - * Visit objects within a pack in packfile order rather than .idx order - */ - FOR_EACH_OBJECT_PACK_ORDER = (1<<2), - - /* Only iterate over packs that are not marked as kept in-core. */ - FOR_EACH_OBJECT_SKIP_IN_CORE_KEPT_PACKS = (1<<3), - - /* Only iterate over packs that do not have .keep files. */ - FOR_EACH_OBJECT_SKIP_ON_DISK_KEPT_PACKS = (1<<4), -}; - - -void *read_object_with_reference(struct repository *r, - const struct object_id *oid, - enum object_type required_type, - unsigned long *size, - struct object_id *oid_ret); - -#endif /* OBJECT_STORE_H */ diff --git a/odb.c b/odb.c new file mode 100644 index 0000000000..d1025ac182 --- /dev/null +++ b/odb.c @@ -0,0 +1,1010 @@ +#define USE_THE_REPOSITORY_VARIABLE + +#include "git-compat-util.h" +#include "abspath.h" +#include "commit-graph.h" +#include "config.h" +#include "dir.h" +#include "environment.h" +#include "gettext.h" +#include "hex.h" +#include "khash.h" +#include "lockfile.h" +#include "loose.h" +#include "object-file-convert.h" +#include "object-file.h" +#include "odb.h" +#include "packfile.h" +#include "path.h" +#include "promisor-remote.h" +#include "quote.h" +#include "replace-object.h" +#include "run-command.h" +#include "setup.h" +#include "strbuf.h" +#include "strvec.h" +#include "submodule.h" +#include "write-or-die.h" + +KHASH_INIT(odb_path_map, const char * /* key: odb_path */, + struct odb_source *, 1, fspathhash, fspatheq) + +/* + * This is meant to hold a *small* number of objects that you would + * want repo_read_object_file() to be able to return, but yet you do not want + * to write them into the object store (e.g. a browse-only + * application). + */ +struct cached_object_entry { + struct object_id oid; + struct cached_object { + enum object_type type; + const void *buf; + unsigned long size; + } value; +}; + +static const struct cached_object *find_cached_object(struct object_database *object_store, + const struct object_id *oid) +{ + static const struct cached_object empty_tree = { + .type = OBJ_TREE, + .buf = "", + }; + const struct cached_object_entry *co = object_store->cached_objects; + + for (size_t i = 0; i < object_store->cached_object_nr; i++, co++) + if (oideq(&co->oid, oid)) + return &co->value; + + if (oid->algo && oideq(oid, hash_algos[oid->algo].empty_tree)) + return &empty_tree; + + return NULL; +} + +int odb_mkstemp(struct strbuf *temp_filename, const char *pattern) +{ + int fd; + /* + * we let the umask do its job, don't try to be more + * restrictive except to remove write permission. + */ + int mode = 0444; + repo_git_path_replace(the_repository, temp_filename, "objects/%s", pattern); + fd = git_mkstemp_mode(temp_filename->buf, mode); + if (0 <= fd) + return fd; + + /* slow path */ + /* some mkstemp implementations erase temp_filename on failure */ + repo_git_path_replace(the_repository, temp_filename, "objects/%s", pattern); + safe_create_leading_directories(the_repository, temp_filename->buf); + return xmkstemp_mode(temp_filename->buf, mode); +} + +/* + * Return non-zero iff the path is usable as an alternate object database. + */ +static int alt_odb_usable(struct object_database *o, + struct strbuf *path, + const char *normalized_objdir, khiter_t *pos) +{ + int r; + + /* Detect cases where alternate disappeared */ + if (!is_directory(path->buf)) { + error(_("object directory %s does not exist; " + "check .git/objects/info/alternates"), + path->buf); + return 0; + } + + /* + * Prevent the common mistake of listing the same + * thing twice, or object directory itself. + */ + if (!o->source_by_path) { + khiter_t p; + + o->source_by_path = kh_init_odb_path_map(); + assert(!o->sources->next); + p = kh_put_odb_path_map(o->source_by_path, o->sources->path, &r); + assert(r == 1); /* never used */ + kh_value(o->source_by_path, p) = o->sources; + } + if (fspatheq(path->buf, normalized_objdir)) + return 0; + *pos = kh_put_odb_path_map(o->source_by_path, path->buf, &r); + /* r: 0 = exists, 1 = never used, 2 = deleted */ + return r == 0 ? 0 : 1; +} + +/* + * Prepare alternate object database registry. + * + * The variable alt_odb_list points at the list of struct + * odb_source. The elements on this list come from + * non-empty elements from colon separated ALTERNATE_DB_ENVIRONMENT + * environment variable, and $GIT_OBJECT_DIRECTORY/info/alternates, + * whose contents is similar to that environment variable but can be + * LF separated. Its base points at a statically allocated buffer that + * contains "/the/directory/corresponding/to/.git/objects/...", while + * its name points just after the slash at the end of ".git/objects/" + * in the example above, and has enough space to hold all hex characters + * of the object ID, an extra slash for the first level indirection, and + * the terminating NUL. + */ +static void read_info_alternates(struct repository *r, + const char *relative_base, + int depth); +static int link_alt_odb_entry(struct repository *r, const struct strbuf *entry, + const char *relative_base, int depth, const char *normalized_objdir) +{ + struct odb_source *alternate; + struct strbuf pathbuf = STRBUF_INIT; + struct strbuf tmp = STRBUF_INIT; + khiter_t pos; + int ret = -1; + + if (!is_absolute_path(entry->buf) && relative_base) { + strbuf_realpath(&pathbuf, relative_base, 1); + strbuf_addch(&pathbuf, '/'); + } + strbuf_addbuf(&pathbuf, entry); + + if (!strbuf_realpath(&tmp, pathbuf.buf, 0)) { + error(_("unable to normalize alternate object path: %s"), + pathbuf.buf); + goto error; + } + strbuf_swap(&pathbuf, &tmp); + + /* + * The trailing slash after the directory name is given by + * this function at the end. Remove duplicates. + */ + while (pathbuf.len && pathbuf.buf[pathbuf.len - 1] == '/') + strbuf_setlen(&pathbuf, pathbuf.len - 1); + + if (!alt_odb_usable(r->objects, &pathbuf, normalized_objdir, &pos)) + goto error; + + CALLOC_ARRAY(alternate, 1); + /* pathbuf.buf is already in r->objects->source_by_path */ + alternate->path = strbuf_detach(&pathbuf, NULL); + + /* add the alternate entry */ + *r->objects->sources_tail = alternate; + r->objects->sources_tail = &(alternate->next); + alternate->next = NULL; + assert(r->objects->source_by_path); + kh_value(r->objects->source_by_path, pos) = alternate; + + /* recursively add alternates */ + read_info_alternates(r, alternate->path, depth + 1); + ret = 0; + error: + strbuf_release(&tmp); + strbuf_release(&pathbuf); + return ret; +} + +static const char *parse_alt_odb_entry(const char *string, + int sep, + struct strbuf *out) +{ + const char *end; + + strbuf_reset(out); + + if (*string == '#') { + /* comment; consume up to next separator */ + end = strchrnul(string, sep); + } else if (*string == '"' && !unquote_c_style(out, 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(out, string, end - string); + } + + if (*end) + end++; + return end; +} + +static void link_alt_odb_entries(struct repository *r, const char *alt, + int sep, const char *relative_base, int depth) +{ + struct strbuf objdirbuf = STRBUF_INIT; + struct strbuf entry = STRBUF_INIT; + + if (!alt || !*alt) + return; + + if (depth > 5) { + error(_("%s: ignoring alternate object stores, nesting too deep"), + relative_base); + return; + } + + strbuf_realpath(&objdirbuf, r->objects->sources->path, 1); + + while (*alt) { + alt = parse_alt_odb_entry(alt, sep, &entry); + if (!entry.len) + continue; + link_alt_odb_entry(r, &entry, + relative_base, depth, objdirbuf.buf); + } + strbuf_release(&entry); + strbuf_release(&objdirbuf); +} + +static void read_info_alternates(struct repository *r, + const char *relative_base, + int depth) +{ + char *path; + struct strbuf buf = STRBUF_INIT; + + path = xstrfmt("%s/info/alternates", relative_base); + if (strbuf_read_file(&buf, path, 1024) < 0) { + warn_on_fopen_errors(path); + free(path); + return; + } + + link_alt_odb_entries(r, buf.buf, '\n', relative_base, depth); + strbuf_release(&buf); + free(path); +} + +void add_to_alternates_file(const char *reference) +{ + struct lock_file lock = LOCK_INIT; + char *alts = repo_git_path(the_repository, "objects/info/alternates"); + FILE *in, *out; + int found = 0; + + hold_lock_file_for_update(&lock, alts, LOCK_DIE_ON_ERROR); + out = fdopen_lock_file(&lock, "w"); + if (!out) + die_errno(_("unable to fdopen alternates lockfile")); + + in = fopen(alts, "r"); + if (in) { + struct strbuf line = STRBUF_INIT; + + while (strbuf_getline(&line, in) != EOF) { + if (!strcmp(reference, line.buf)) { + found = 1; + break; + } + fprintf_or_die(out, "%s\n", line.buf); + } + + strbuf_release(&line); + fclose(in); + } + else if (errno != ENOENT) + die_errno(_("unable to read alternates file")); + + if (found) { + rollback_lock_file(&lock); + } else { + fprintf_or_die(out, "%s\n", reference); + if (commit_lock_file(&lock)) + die_errno(_("unable to move new alternates file into place")); + if (the_repository->objects->loaded_alternates) + link_alt_odb_entries(the_repository, reference, + '\n', NULL, 0); + } + free(alts); +} + +void add_to_alternates_memory(const char *reference) +{ + /* + * Make sure alternates are initialized, or else our entry may be + * overwritten when they are. + */ + prepare_alt_odb(the_repository); + + link_alt_odb_entries(the_repository, reference, + '\n', NULL, 0); +} + +struct odb_source *set_temporary_primary_odb(const char *dir, int will_destroy) +{ + struct odb_source *source; + + /* + * Make sure alternates are initialized, or else our entry may be + * overwritten when they are. + */ + prepare_alt_odb(the_repository); + + /* + * Make a new primary odb and link the old primary ODB in as an + * alternate + */ + source = xcalloc(1, sizeof(*source)); + source->path = xstrdup(dir); + + /* + * Disable ref updates while a temporary odb is active, since + * the objects in the database may roll back. + */ + source->disable_ref_updates = 1; + source->will_destroy = will_destroy; + source->next = the_repository->objects->sources; + the_repository->objects->sources = source; + return source->next; +} + +static void free_object_directory(struct odb_source *source) +{ + free(source->path); + odb_clear_loose_cache(source); + loose_object_map_clear(&source->loose_map); + free(source); +} + +void restore_primary_odb(struct odb_source *restore_alt, const char *old_path) +{ + struct odb_source *cur_alt = the_repository->objects->sources; + + if (strcmp(old_path, cur_alt->path)) + BUG("expected %s as primary object store; found %s", + old_path, cur_alt->path); + + if (cur_alt->next != restore_alt) + BUG("we expect the old primary object store to be the first alternate"); + + the_repository->objects->sources = restore_alt; + free_object_directory(cur_alt); +} + +/* + * Compute the exact path an alternate is at and returns it. In case of + * error NULL is returned and the human readable error is added to `err` + * `path` may be relative and should point to $GIT_DIR. + * `err` must not be null. + */ +char *compute_alternate_path(const char *path, struct strbuf *err) +{ + char *ref_git = NULL; + const char *repo; + int seen_error = 0; + + ref_git = real_pathdup(path, 0); + if (!ref_git) { + seen_error = 1; + strbuf_addf(err, _("path '%s' does not exist"), path); + goto out; + } + + repo = read_gitfile(ref_git); + if (!repo) + repo = read_gitfile(mkpath("%s/.git", ref_git)); + if (repo) { + free(ref_git); + ref_git = xstrdup(repo); + } + + if (!repo && is_directory(mkpath("%s/.git/objects", ref_git))) { + char *ref_git_git = mkpathdup("%s/.git", ref_git); + free(ref_git); + ref_git = ref_git_git; + } else if (!is_directory(mkpath("%s/objects", ref_git))) { + struct strbuf sb = STRBUF_INIT; + seen_error = 1; + if (get_common_dir(&sb, ref_git)) { + strbuf_addf(err, + _("reference repository '%s' as a linked " + "checkout is not supported yet."), + path); + goto out; + } + + strbuf_addf(err, _("reference repository '%s' is not a " + "local repository."), path); + goto out; + } + + if (!access(mkpath("%s/shallow", ref_git), F_OK)) { + strbuf_addf(err, _("reference repository '%s' is shallow"), + path); + seen_error = 1; + goto out; + } + + if (!access(mkpath("%s/info/grafts", ref_git), F_OK)) { + strbuf_addf(err, + _("reference repository '%s' is grafted"), + path); + seen_error = 1; + goto out; + } + +out: + if (seen_error) { + FREE_AND_NULL(ref_git); + } + + return ref_git; +} + +struct odb_source *find_odb(struct repository *r, const char *obj_dir) +{ + struct odb_source *source; + char *obj_dir_real = real_pathdup(obj_dir, 1); + struct strbuf odb_path_real = STRBUF_INIT; + + prepare_alt_odb(r); + for (source = r->objects->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); + + if (!source) + die(_("could not find object directory matching %s"), obj_dir); + return source; +} + +static void fill_alternate_refs_command(struct child_process *cmd, + const char *repo_path) +{ + const char *value; + + if (!git_config_get_value("core.alternateRefsCommand", &value)) { + cmd->use_shell = 1; + + strvec_push(&cmd->args, value); + strvec_push(&cmd->args, repo_path); + } else { + cmd->git_cmd = 1; + + strvec_pushf(&cmd->args, "--git-dir=%s", repo_path); + strvec_push(&cmd->args, "for-each-ref"); + strvec_push(&cmd->args, "--format=%(objectname)"); + + if (!git_config_get_value("core.alternateRefsPrefixes", &value)) { + strvec_push(&cmd->args, "--"); + strvec_split(&cmd->args, value); + } + } + + strvec_pushv(&cmd->env, (const char **)local_repo_env); + cmd->out = -1; +} + +static void read_alternate_refs(const char *path, + alternate_ref_fn *cb, + void *data) +{ + struct child_process cmd = CHILD_PROCESS_INIT; + struct strbuf line = STRBUF_INIT; + FILE *fh; + + fill_alternate_refs_command(&cmd, path); + + if (start_command(&cmd)) + return; + + fh = xfdopen(cmd.out, "r"); + while (strbuf_getline_lf(&line, fh) != EOF) { + struct object_id oid; + const char *p; + + if (parse_oid_hex(line.buf, &oid, &p) || *p) { + warning(_("invalid line while parsing alternate refs: %s"), + line.buf); + break; + } + + cb(&oid, data); + } + + fclose(fh); + finish_command(&cmd); + strbuf_release(&line); +} + +struct alternate_refs_data { + alternate_ref_fn *fn; + void *data; +}; + +static int refs_from_alternate_cb(struct odb_source *alternate, + void *data) +{ + struct strbuf path = STRBUF_INIT; + size_t base_len; + struct alternate_refs_data *cb = data; + + if (!strbuf_realpath(&path, alternate->path, 0)) + goto out; + if (!strbuf_strip_suffix(&path, "/objects")) + goto out; + base_len = path.len; + + /* Is this a git repository with refs? */ + strbuf_addstr(&path, "/refs"); + if (!is_directory(path.buf)) + goto out; + strbuf_setlen(&path, base_len); + + read_alternate_refs(path.buf, cb->fn, cb->data); + +out: + strbuf_release(&path); + return 0; +} + +void for_each_alternate_ref(alternate_ref_fn fn, void *data) +{ + struct alternate_refs_data cb; + cb.fn = fn; + cb.data = data; + foreach_alt_odb(refs_from_alternate_cb, &cb); +} + +int foreach_alt_odb(alt_odb_fn fn, void *cb) +{ + struct odb_source *alternate; + int r = 0; + + prepare_alt_odb(the_repository); + for (alternate = the_repository->objects->sources->next; alternate; alternate = alternate->next) { + r = fn(alternate, cb); + if (r) + break; + } + return r; +} + +void prepare_alt_odb(struct repository *r) +{ + if (r->objects->loaded_alternates) + return; + + link_alt_odb_entries(r, r->objects->alternate_db, PATH_SEP, NULL, 0); + + read_info_alternates(r, r->objects->sources->path, 0); + r->objects->loaded_alternates = 1; +} + +int has_alt_odb(struct repository *r) +{ + prepare_alt_odb(r); + return !!r->objects->sources->next; +} + +int obj_read_use_lock = 0; +pthread_mutex_t obj_read_mutex; + +void enable_obj_read_lock(void) +{ + if (obj_read_use_lock) + return; + + obj_read_use_lock = 1; + init_recursive_mutex(&obj_read_mutex); +} + +void disable_obj_read_lock(void) +{ + if (!obj_read_use_lock) + return; + + obj_read_use_lock = 0; + pthread_mutex_destroy(&obj_read_mutex); +} + +int fetch_if_missing = 1; + +static int do_oid_object_info_extended(struct repository *r, + const struct object_id *oid, + struct object_info *oi, unsigned flags) +{ + static struct object_info blank_oi = OBJECT_INFO_INIT; + const struct cached_object *co; + struct pack_entry e; + int rtype; + const struct object_id *real = oid; + int already_retried = 0; + + + if (flags & OBJECT_INFO_LOOKUP_REPLACE) + real = lookup_replace_object(r, oid); + + if (is_null_oid(real)) + return -1; + + if (!oi) + oi = &blank_oi; + + co = find_cached_object(r->objects, real); + if (co) { + if (oi->typep) + *(oi->typep) = co->type; + if (oi->sizep) + *(oi->sizep) = co->size; + if (oi->disk_sizep) + *(oi->disk_sizep) = 0; + if (oi->delta_base_oid) + oidclr(oi->delta_base_oid, the_repository->hash_algo); + if (oi->contentp) + *oi->contentp = xmemdupz(co->buf, co->size); + oi->whence = OI_CACHED; + return 0; + } + + while (1) { + if (find_pack_entry(r, real, &e)) + break; + + /* Most likely it's a loose object. */ + if (!loose_object_info(r, real, oi, flags)) + return 0; + + /* Not a loose object; someone else may have just packed it. */ + if (!(flags & OBJECT_INFO_QUICK)) { + reprepare_packed_git(r); + if (find_pack_entry(r, real, &e)) + break; + } + + /* + * If r is the_repository, this might be an attempt at + * accessing a submodule object as if it were in the_repository + * (having called add_submodule_odb() on that submodule's ODB). + * If any such ODBs exist, register them and try again. + */ + if (r == the_repository && + register_all_submodule_odb_as_alternates()) + /* We added some alternates; retry */ + continue; + + /* Check if it is a missing object */ + if (fetch_if_missing && repo_has_promisor_remote(r) && + !already_retried && + !(flags & OBJECT_INFO_SKIP_FETCH_OBJECT)) { + promisor_remote_get_direct(r, real, 1); + already_retried = 1; + continue; + } + + if (flags & OBJECT_INFO_DIE_IF_CORRUPT) { + const struct packed_git *p; + if ((flags & OBJECT_INFO_LOOKUP_REPLACE) && !oideq(real, oid)) + die(_("replacement %s not found for %s"), + oid_to_hex(real), oid_to_hex(oid)); + if ((p = has_packed_and_bad(r, real))) + die(_("packed object %s (stored in %s) is corrupt"), + oid_to_hex(real), p->pack_name); + } + return -1; + } + + if (oi == &blank_oi) + /* + * We know that the caller doesn't actually need the + * information below, so return early. + */ + return 0; + rtype = packed_object_info(r, e.p, e.offset, oi); + if (rtype < 0) { + mark_bad_packed_object(e.p, real); + return do_oid_object_info_extended(r, real, oi, 0); + } else if (oi->whence == OI_PACKED) { + oi->u.packed.offset = e.offset; + oi->u.packed.pack = e.p; + oi->u.packed.is_delta = (rtype == OBJ_REF_DELTA || + rtype == OBJ_OFS_DELTA); + } + + return 0; +} + +static int oid_object_info_convert(struct repository *r, + const struct object_id *input_oid, + struct object_info *input_oi, unsigned flags) +{ + const struct git_hash_algo *input_algo = &hash_algos[input_oid->algo]; + int do_die = flags & OBJECT_INFO_DIE_IF_CORRUPT; + enum object_type type; + struct object_id oid, delta_base_oid; + struct object_info new_oi, *oi; + unsigned long size; + void *content; + int ret; + + if (repo_oid_to_algop(r, input_oid, the_hash_algo, &oid)) { + if (do_die) + die(_("missing mapping of %s to %s"), + oid_to_hex(input_oid), the_hash_algo->name); + return -1; + } + + /* Is new_oi needed? */ + oi = input_oi; + if (input_oi && (input_oi->delta_base_oid || input_oi->sizep || + input_oi->contentp)) { + new_oi = *input_oi; + /* Does delta_base_oid need to be converted? */ + if (input_oi->delta_base_oid) + new_oi.delta_base_oid = &delta_base_oid; + /* Will the attributes differ when converted? */ + if (input_oi->sizep || input_oi->contentp) { + new_oi.contentp = &content; + new_oi.sizep = &size; + new_oi.typep = &type; + } + oi = &new_oi; + } + + ret = oid_object_info_extended(r, &oid, oi, flags); + if (ret) + return -1; + if (oi == input_oi) + return ret; + + if (new_oi.contentp) { + struct strbuf outbuf = STRBUF_INIT; + + if (type != OBJ_BLOB) { + ret = convert_object_file(the_repository, &outbuf, + the_hash_algo, input_algo, + content, size, type, !do_die); + free(content); + if (ret == -1) + return -1; + size = outbuf.len; + content = strbuf_detach(&outbuf, NULL); + } + if (input_oi->sizep) + *input_oi->sizep = size; + if (input_oi->contentp) + *input_oi->contentp = content; + else + free(content); + if (input_oi->typep) + *input_oi->typep = type; + } + if (new_oi.delta_base_oid == &delta_base_oid) { + if (repo_oid_to_algop(r, &delta_base_oid, input_algo, + input_oi->delta_base_oid)) { + if (do_die) + die(_("missing mapping of %s to %s"), + oid_to_hex(&delta_base_oid), + input_algo->name); + return -1; + } + } + input_oi->whence = new_oi.whence; + input_oi->u = new_oi.u; + return ret; +} + +int oid_object_info_extended(struct repository *r, const struct object_id *oid, + struct object_info *oi, unsigned flags) +{ + int ret; + + if (oid->algo && (hash_algo_by_ptr(r->hash_algo) != oid->algo)) + return oid_object_info_convert(r, oid, oi, flags); + + obj_read_lock(); + ret = do_oid_object_info_extended(r, oid, oi, flags); + obj_read_unlock(); + return ret; +} + + +/* returns enum object_type or negative */ +int oid_object_info(struct repository *r, + const struct object_id *oid, + unsigned long *sizep) +{ + enum object_type type; + struct object_info oi = OBJECT_INFO_INIT; + + oi.typep = &type; + oi.sizep = sizep; + if (oid_object_info_extended(r, oid, &oi, + OBJECT_INFO_LOOKUP_REPLACE) < 0) + return -1; + return type; +} + +int pretend_object_file(struct repository *repo, + void *buf, unsigned long len, enum object_type type, + struct object_id *oid) +{ + struct cached_object_entry *co; + char *co_buf; + + hash_object_file(repo->hash_algo, buf, len, type, oid); + if (has_object(repo, oid, 0) || + find_cached_object(repo->objects, oid)) + return 0; + + ALLOC_GROW(repo->objects->cached_objects, + repo->objects->cached_object_nr + 1, repo->objects->cached_object_alloc); + co = &repo->objects->cached_objects[repo->objects->cached_object_nr++]; + co->value.size = len; + co->value.type = type; + co_buf = xmalloc(len); + memcpy(co_buf, buf, len); + co->value.buf = co_buf; + oidcpy(&co->oid, oid); + return 0; +} + +/* + * This function dies on corrupt objects; the callers who want to + * deal with them should arrange to call oid_object_info_extended() and give + * error messages themselves. + */ +void *repo_read_object_file(struct repository *r, + const struct object_id *oid, + enum object_type *type, + unsigned long *size) +{ + struct object_info oi = OBJECT_INFO_INIT; + unsigned flags = OBJECT_INFO_DIE_IF_CORRUPT | OBJECT_INFO_LOOKUP_REPLACE; + void *data; + + oi.typep = type; + oi.sizep = size; + oi.contentp = &data; + if (oid_object_info_extended(r, oid, &oi, flags)) + return NULL; + + return data; +} + +void *read_object_with_reference(struct repository *r, + const struct object_id *oid, + enum object_type required_type, + unsigned long *size, + struct object_id *actual_oid_return) +{ + enum object_type type; + void *buffer; + unsigned long isize; + struct object_id actual_oid; + + oidcpy(&actual_oid, oid); + while (1) { + int ref_length = -1; + const char *ref_type = NULL; + + buffer = repo_read_object_file(r, &actual_oid, &type, &isize); + if (!buffer) + return NULL; + if (type == required_type) { + *size = isize; + if (actual_oid_return) + oidcpy(actual_oid_return, &actual_oid); + return buffer; + } + /* Handle references */ + else if (type == OBJ_COMMIT) + ref_type = "tree "; + else if (type == OBJ_TAG) + ref_type = "object "; + else { + free(buffer); + return NULL; + } + ref_length = strlen(ref_type); + + if (ref_length + the_hash_algo->hexsz > isize || + memcmp(buffer, ref_type, ref_length) || + get_oid_hex((char *) buffer + ref_length, &actual_oid)) { + free(buffer); + return NULL; + } + free(buffer); + /* Now we have the ID of the referred-to object in + * actual_oid. Check again. */ + } +} + +int has_object(struct repository *r, const struct object_id *oid, + unsigned flags) +{ + unsigned object_info_flags = 0; + + if (!startup_info->have_repository) + return 0; + if (!(flags & HAS_OBJECT_RECHECK_PACKED)) + object_info_flags |= OBJECT_INFO_QUICK; + if (!(flags & HAS_OBJECT_FETCH_PROMISOR)) + object_info_flags |= OBJECT_INFO_SKIP_FETCH_OBJECT; + + return oid_object_info_extended(r, oid, NULL, object_info_flags) >= 0; +} + +void assert_oid_type(const struct object_id *oid, enum object_type expect) +{ + enum object_type type = oid_object_info(the_repository, oid, NULL); + if (type < 0) + die(_("%s is not a valid object"), oid_to_hex(oid)); + if (type != expect) + die(_("%s is not a valid '%s' object"), oid_to_hex(oid), + type_name(expect)); +} + +struct object_database *odb_new(void) +{ + struct object_database *o = xmalloc(sizeof(*o)); + + memset(o, 0, sizeof(*o)); + INIT_LIST_HEAD(&o->packed_git_mru); + hashmap_init(&o->pack_map, pack_map_entry_cmp, NULL, 0); + pthread_mutex_init(&o->replace_mutex, NULL); + return o; +} + +static void free_object_directories(struct object_database *o) +{ + while (o->sources) { + struct odb_source *next; + + next = o->sources->next; + free_object_directory(o->sources); + o->sources = next; + } + kh_destroy_odb_path_map(o->source_by_path); + o->source_by_path = NULL; +} + +void odb_clear(struct object_database *o) +{ + FREE_AND_NULL(o->alternate_db); + + oidmap_clear(&o->replace_map, 1); + pthread_mutex_destroy(&o->replace_mutex); + + free_commit_graph(o->commit_graph); + o->commit_graph = NULL; + o->commit_graph_attempted = 0; + + free_object_directories(o); + o->sources_tail = NULL; + o->loaded_alternates = 0; + + for (size_t i = 0; i < o->cached_object_nr; i++) + free((char *) o->cached_objects[i].value.buf); + FREE_AND_NULL(o->cached_objects); + + INIT_LIST_HEAD(&o->packed_git_mru); + close_object_store(o); + + /* + * `close_object_store()` only closes the packfiles, but doesn't free + * them. We thus have to do this manually. + */ + for (struct packed_git *p = o->packed_git, *next; p; p = next) { + next = p->next; + free(p); + } + o->packed_git = NULL; + + hashmap_clear(&o->pack_map); +} diff --git a/odb.h b/odb.h new file mode 100644 index 0000000000..6f56b168e4 --- /dev/null +++ b/odb.h @@ -0,0 +1,355 @@ +#ifndef ODB_H +#define ODB_H + +#include "hashmap.h" +#include "object.h" +#include "list.h" +#include "oidset.h" +#include "oidmap.h" +#include "thread-utils.h" + +struct oidmap; +struct oidtree; +struct strbuf; +struct repository; + +/* + * 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. + */ +struct odb_source { + struct odb_source *next; + + /* + * Used to store the results of readdir(3) calls when we are OK + * sacrificing accuracy due to races for speed. That includes + * object existence with OBJECT_INFO_QUICK, as well as + * our search for unique abbreviated hashes. Don't use it for tasks + * requiring greater accuracy! + * + * Be sure to call odb_load_loose_cache() before using. + */ + uint32_t loose_objects_subdir_seen[8]; /* 256 bits */ + struct oidtree *loose_objects_cache; + + /* Map between object IDs for loose objects. */ + struct loose_object_map *loose_map; + + /* + * This is a temporary object store created by the tmp_objdir + * facility. Disable ref updates since the objects in the store + * might be discarded on rollback. + */ + int disable_ref_updates; + + /* + * 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. + */ + char *path; +}; + +void prepare_alt_odb(struct repository *r); +int has_alt_odb(struct repository *r); +char *compute_alternate_path(const char *path, struct strbuf *err); +struct odb_source *find_odb(struct repository *r, const char *obj_dir); +typedef int alt_odb_fn(struct odb_source *, void *); +int foreach_alt_odb(alt_odb_fn, void*); +typedef void alternate_ref_fn(const struct object_id *oid, void *); +void for_each_alternate_ref(alternate_ref_fn, void *); + +/* + * Add the directory to the on-disk alternates file; the new entry will also + * take effect in the current process. + */ +void add_to_alternates_file(const char *dir); + +/* + * Add the directory to the in-memory list of alternates (along with any + * recursive alternates it points to), but do not modify the on-disk alternates + * file. + */ +void add_to_alternates_memory(const char *dir); + +/* + * Replace the current writable object directory with the specified temporary + * object directory; returns the former primary object directory. + */ +struct odb_source *set_temporary_primary_odb(const char *dir, int will_destroy); + +/* + * Restore a previous ODB replaced by set_temporary_main_odb. + */ +void restore_primary_odb(struct odb_source *restore_alternate, const char *old_path); + +struct packed_git; +struct multi_pack_index; +struct cached_object_entry; + +/* + * 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. + */ +struct object_database { + /* + * 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; + struct kh_odb_path_map *source_by_path; + + int loaded_alternates; + + /* + * A list of alternate object directories loaded from the environment; + * this should not generally need to be accessed directly, but will + * populate the "sources" list when prepare_alt_odb() is run. + */ + char *alternate_db; + + /* + * Objects that should be substituted by other objects + * (see git-replace(1)). + */ + struct oidmap replace_map; + unsigned replace_map_initialized : 1; + pthread_mutex_t replace_mutex; /* protect object replace functions */ + + struct commit_graph *commit_graph; + unsigned commit_graph_attempted : 1; /* if loading has been attempted */ + + /* + * private data + * + * should only be accessed directly by packfile.c and midx.c + */ + struct multi_pack_index *multi_pack_index; + + /* + * private data + * + * should only be accessed directly by packfile.c + */ + + struct packed_git *packed_git; + /* A most-recently-used ordered version of the packed_git list. */ + struct list_head packed_git_mru; + + struct { + struct packed_git **packs; + unsigned flags; + } kept_pack_cache; + + /* + * This is meant to hold a *small* number of objects that you would + * want repo_read_object_file() to be able to return, but yet you do not want + * to write them into the object store (e.g. a browse-only + * application). + */ + struct cached_object_entry *cached_objects; + size_t cached_object_nr, cached_object_alloc; + + /* + * A map of packfiles to packed_git structs for tracking which + * packs have been loaded already. + */ + struct hashmap pack_map; + + /* + * A fast, rough count of the number of objects in the repository. + * These two fields are not meant for direct access. Use + * repo_approximate_object_count() instead. + */ + unsigned long approximate_object_count; + unsigned approximate_object_count_valid : 1; + + /* + * Whether packed_git has already been populated with this repository's + * packs. + */ + unsigned packed_git_initialized : 1; +}; + +struct object_database *odb_new(void); +void odb_clear(struct object_database *o); + +/* + * Create a temporary file rooted in the object database directory, or + * die on failure. The filename is taken from "pattern", which should have the + * usual "XXXXXX" trailer, and the resulting filename is written into the + * "template" buffer. Returns the open descriptor. + */ +int odb_mkstemp(struct strbuf *temp_filename, const char *pattern); + +void *repo_read_object_file(struct repository *r, + const struct object_id *oid, + enum object_type *type, + unsigned long *size); + +/* Read and unpack an object file into memory, write memory to an object file */ +int oid_object_info(struct repository *r, const struct object_id *, unsigned long *); + +/* + * Add an object file to the in-memory object store, without writing it + * to disk. + * + * Callers are responsible for calling write_object_file to record the + * object in persistent storage before writing any other new objects + * that reference it. + */ +int pretend_object_file(struct repository *repo, + void *buf, unsigned long len, enum object_type type, + struct object_id *oid); + +struct object_info { + /* Request */ + enum object_type *typep; + unsigned long *sizep; + off_t *disk_sizep; + struct object_id *delta_base_oid; + void **contentp; + + /* Response */ + enum { + OI_CACHED, + OI_LOOSE, + OI_PACKED, + OI_DBCACHED + } whence; + union { + /* + * struct { + * ... Nothing to expose in this case + * } cached; + * struct { + * ... Nothing to expose in this case + * } loose; + */ + struct { + struct packed_git *pack; + off_t offset; + unsigned int is_delta; + } packed; + } u; +}; + +/* + * Initializer for a "struct object_info" that wants no items. You may + * also memset() the memory to all-zeroes. + */ +#define OBJECT_INFO_INIT { 0 } + +/* Invoke lookup_replace_object() on the given hash */ +#define OBJECT_INFO_LOOKUP_REPLACE 1 +/* Do not retry packed storage after checking packed and loose storage */ +#define OBJECT_INFO_QUICK 8 +/* + * Do not attempt to fetch the object if missing (even if fetch_is_missing is + * nonzero). + */ +#define OBJECT_INFO_SKIP_FETCH_OBJECT 16 +/* + * This is meant for bulk prefetching of missing blobs in a partial + * clone. Implies OBJECT_INFO_SKIP_FETCH_OBJECT and OBJECT_INFO_QUICK + */ +#define OBJECT_INFO_FOR_PREFETCH (OBJECT_INFO_SKIP_FETCH_OBJECT | OBJECT_INFO_QUICK) + +/* Die if object corruption (not just an object being missing) was detected. */ +#define OBJECT_INFO_DIE_IF_CORRUPT 32 + +int oid_object_info_extended(struct repository *r, + const struct object_id *, + struct object_info *, unsigned flags); + +enum { + /* Retry packed storage after checking packed and loose storage */ + HAS_OBJECT_RECHECK_PACKED = (1 << 0), + /* Allow fetching the object in case the repository has a promisor remote. */ + HAS_OBJECT_FETCH_PROMISOR = (1 << 1), +}; + +/* + * Returns 1 if the object exists. This function will not lazily fetch objects + * in a partial clone by default. + */ +int has_object(struct repository *r, const struct object_id *oid, + unsigned flags); + +void assert_oid_type(const struct object_id *oid, enum object_type expect); + +/* + * Enabling the object read lock allows multiple threads to safely call the + * following functions in parallel: repo_read_object_file(), + * read_object_with_reference(), oid_object_info() and oid_object_info_extended(). + * + * obj_read_lock() and obj_read_unlock() may also be used to protect other + * section which cannot execute in parallel with object reading. Since the used + * lock is a recursive mutex, these sections can even contain calls to object + * reading functions. However, beware that in these cases zlib inflation won't + * be performed in parallel, losing performance. + * + * TODO: oid_object_info_extended()'s call stack has a recursive behavior. If + * any of its callees end up calling it, this recursive call won't benefit from + * parallel inflation. + */ +void enable_obj_read_lock(void); +void disable_obj_read_lock(void); + +extern int obj_read_use_lock; +extern pthread_mutex_t obj_read_mutex; + +static inline void obj_read_lock(void) +{ + if(obj_read_use_lock) + pthread_mutex_lock(&obj_read_mutex); +} + +static inline void obj_read_unlock(void) +{ + if(obj_read_use_lock) + pthread_mutex_unlock(&obj_read_mutex); +} +/* Flags for for_each_*_object(). */ +enum for_each_object_flags { + /* Iterate only over local objects, not alternates. */ + FOR_EACH_OBJECT_LOCAL_ONLY = (1<<0), + + /* Only iterate over packs obtained from the promisor remote. */ + FOR_EACH_OBJECT_PROMISOR_ONLY = (1<<1), + + /* + * Visit objects within a pack in packfile order rather than .idx order + */ + FOR_EACH_OBJECT_PACK_ORDER = (1<<2), + + /* Only iterate over packs that are not marked as kept in-core. */ + FOR_EACH_OBJECT_SKIP_IN_CORE_KEPT_PACKS = (1<<3), + + /* Only iterate over packs that do not have .keep files. */ + FOR_EACH_OBJECT_SKIP_ON_DISK_KEPT_PACKS = (1<<4), +}; + + +void *read_object_with_reference(struct repository *r, + const struct object_id *oid, + enum object_type required_type, + unsigned long *size, + struct object_id *oid_ret); + +#endif /* ODB_H */ diff --git a/oss-fuzz/fuzz-pack-idx.c b/oss-fuzz/fuzz-pack-idx.c index 609a343ee3..d2a92f34d9 100644 --- a/oss-fuzz/fuzz-pack-idx.c +++ b/oss-fuzz/fuzz-pack-idx.c @@ -1,5 +1,5 @@ #include "git-compat-util.h" -#include "object-store.h" +#include "odb.h" #include "packfile.h" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); diff --git a/pack-bitmap-write.c b/pack-bitmap-write.c index 7f400ee012..37648b5712 100644 --- a/pack-bitmap-write.c +++ b/pack-bitmap-write.c @@ -4,7 +4,7 @@ #include "environment.h" #include "gettext.h" #include "hex.h" -#include "object-store.h" +#include "odb.h" #include "commit.h" #include "diff.h" #include "revision.h" diff --git a/pack-bitmap.c b/pack-bitmap.c index ac6d62b980..a695a794e9 100644 --- a/pack-bitmap.c +++ b/pack-bitmap.c @@ -17,7 +17,7 @@ #include "packfile.h" #include "repository.h" #include "trace2.h" -#include "object-store.h" +#include "odb.h" #include "list-objects-filter-options.h" #include "midx.h" #include "config.h" diff --git a/pack-check.c b/pack-check.c index 874897d6cb..67cb2cf72f 100644 --- a/pack-check.c +++ b/pack-check.c @@ -8,7 +8,7 @@ #include "progress.h" #include "packfile.h" #include "object-file.h" -#include "object-store.h" +#include "odb.h" struct idx_entry { off_t offset; diff --git a/pack-mtimes.c b/pack-mtimes.c index 20900ca88d..8e1f2dec0e 100644 --- a/pack-mtimes.c +++ b/pack-mtimes.c @@ -1,7 +1,7 @@ #include "git-compat-util.h" #include "gettext.h" #include "pack-mtimes.h" -#include "object-store.h" +#include "odb.h" #include "packfile.h" #include "strbuf.h" diff --git a/pack-objects.h b/pack-objects.h index 475a2d67ce..1ac8644201 100644 --- a/pack-objects.h +++ b/pack-objects.h @@ -1,7 +1,7 @@ #ifndef PACK_OBJECTS_H #define PACK_OBJECTS_H -#include "object-store.h" +#include "odb.h" #include "thread-utils.h" #include "pack.h" #include "packfile.h" diff --git a/pack-revindex.c b/pack-revindex.c index ffcde48870..0cc422a1e6 100644 --- a/pack-revindex.c +++ b/pack-revindex.c @@ -1,7 +1,7 @@ #include "git-compat-util.h" #include "gettext.h" #include "pack-revindex.h" -#include "object-store.h" +#include "odb.h" #include "packfile.h" #include "strbuf.h" #include "trace2.h" diff --git a/packfile.c b/packfile.c index 60661ad009..346c2f9ce9 100644 --- a/packfile.c +++ b/packfile.c @@ -19,7 +19,7 @@ #include "tree-walk.h" #include "tree.h" #include "object-file.h" -#include "object-store.h" +#include "odb.h" #include "midx.h" #include "commit-graph.h" #include "pack-revindex.h" diff --git a/packfile.h b/packfile.h index 826eb7f475..53c3b7d3b4 100644 --- a/packfile.h +++ b/packfile.h @@ -3,10 +3,10 @@ #include "list.h" #include "object.h" -#include "object-store.h" +#include "odb.h" #include "oidset.h" -/* in object-store.h */ +/* in odb.h */ struct object_info; struct packed_git { diff --git a/path.c b/path.c index c347829aa6..7f56eaf993 100644 --- a/path.c +++ b/path.c @@ -15,7 +15,7 @@ #include "submodule-config.h" #include "path.h" #include "packfile.h" -#include "object-store.h" +#include "odb.h" #include "lockfile.h" #include "exec-cmd.h" diff --git a/promisor-remote.c b/promisor-remote.c index 9d058586df..2baa286bfd 100644 --- a/promisor-remote.c +++ b/promisor-remote.c @@ -3,7 +3,7 @@ #include "git-compat-util.h" #include "gettext.h" #include "hex.h" -#include "object-store.h" +#include "odb.h" #include "promisor-remote.h" #include "config.h" #include "trace2.h" diff --git a/protocol-caps.c b/protocol-caps.c index 9b8db37a21..3022f69a1b 100644 --- a/protocol-caps.c +++ b/protocol-caps.c @@ -6,7 +6,7 @@ #include "hash.h" #include "hex.h" #include "object.h" -#include "object-store.h" +#include "odb.h" #include "repository.h" #include "string-list.h" #include "strbuf.h" diff --git a/read-cache.c b/read-cache.c index c0bb760ad4..c3fa968676 100644 --- a/read-cache.c +++ b/read-cache.c @@ -20,7 +20,7 @@ #include "refs.h" #include "dir.h" #include "object-file.h" -#include "object-store.h" +#include "odb.h" #include "oid-array.h" #include "tree.h" #include "commit.h" diff --git a/ref-filter.c b/ref-filter.c index 7a274633cf..4ce45440ad 100644 --- a/ref-filter.c +++ b/ref-filter.c @@ -12,7 +12,7 @@ #include "refs.h" #include "wildmatch.h" #include "object-name.h" -#include "object-store.h" +#include "odb.h" #include "oid-array.h" #include "repo-settings.h" #include "repository.h" diff --git a/reflog.c b/reflog.c index 15d81ebea9..4f8a3b717c 100644 --- a/reflog.c +++ b/reflog.c @@ -5,7 +5,7 @@ #include "config.h" #include "gettext.h" #include "parse-options.h" -#include "object-store.h" +#include "odb.h" #include "reflog.h" #include "refs.h" #include "revision.h" diff --git a/refs.c b/refs.c index 5f6a386cc9..0ff0e582a6 100644 --- a/refs.c +++ b/refs.c @@ -19,7 +19,7 @@ #include "run-command.h" #include "hook.h" #include "object-name.h" -#include "object-store.h" +#include "odb.h" #include "object.h" #include "path.h" #include "submodule.h" diff --git a/remote.c b/remote.c index 4099183cac..17a842f568 100644 --- a/remote.c +++ b/remote.c @@ -12,7 +12,7 @@ #include "refs.h" #include "refspec.h" #include "object-name.h" -#include "object-store.h" +#include "odb.h" #include "path.h" #include "commit.h" #include "diff.h" diff --git a/replace-object.c b/replace-object.c index f8c5f68837..3eae051074 100644 --- a/replace-object.c +++ b/replace-object.c @@ -2,7 +2,7 @@ #include "gettext.h" #include "hex.h" #include "oidmap.h" -#include "object-store.h" +#include "odb.h" #include "replace-object.h" #include "refs.h" #include "repository.h" diff --git a/replace-object.h b/replace-object.h index 3052e96a62..4c9f2a2383 100644 --- a/replace-object.h +++ b/replace-object.h @@ -3,7 +3,7 @@ #include "oidmap.h" #include "repository.h" -#include "object-store.h" +#include "odb.h" struct replace_object { struct oidmap_entry original; diff --git a/repository.c b/repository.c index 7528beccdd..13426db0f2 100644 --- a/repository.c +++ b/repository.c @@ -1,7 +1,7 @@ #include "git-compat-util.h" #include "abspath.h" #include "repository.h" -#include "object-store.h" +#include "odb.h" #include "config.h" #include "object.h" #include "lockfile.h" diff --git a/rerere.c b/rerere.c index 3cd37c5f0a..951e4bf8b4 100644 --- a/rerere.c +++ b/rerere.c @@ -18,7 +18,7 @@ #include "path.h" #include "pathspec.h" #include "object-file.h" -#include "object-store.h" +#include "odb.h" #include "strmap.h" #define RESOLVED 0 diff --git a/revision.c b/revision.c index 2c36a9c179..cdefe7d6e4 100644 --- a/revision.c +++ b/revision.c @@ -8,7 +8,7 @@ #include "hex.h" #include "object-name.h" #include "object-file.h" -#include "object-store.h" +#include "odb.h" #include "oidset.h" #include "tag.h" #include "blob.h" diff --git a/send-pack.c b/send-pack.c index 86592ce526..abca2dd38a 100644 --- a/send-pack.c +++ b/send-pack.c @@ -4,7 +4,7 @@ #include "date.h" #include "gettext.h" #include "hex.h" -#include "object-store.h" +#include "odb.h" #include "pkt-line.h" #include "sideband.h" #include "run-command.h" diff --git a/sequencer.c b/sequencer.c index 1ee0abbd45..2432d0a39e 100644 --- a/sequencer.c +++ b/sequencer.c @@ -13,7 +13,7 @@ #include "dir.h" #include "object-file.h" #include "object-name.h" -#include "object-store.h" +#include "odb.h" #include "object.h" #include "pager.h" #include "commit.h" diff --git a/server-info.c b/server-info.c index d6cd20a39d..9bb30d9ab7 100644 --- a/server-info.c +++ b/server-info.c @@ -11,7 +11,7 @@ #include "packfile.h" #include "path.h" #include "object-file.h" -#include "object-store.h" +#include "odb.h" #include "server-info.h" #include "strbuf.h" #include "tempfile.h" diff --git a/shallow.c b/shallow.c index faeeeb45f9..d379756e39 100644 --- a/shallow.c +++ b/shallow.c @@ -5,7 +5,7 @@ #include "repository.h" #include "tempfile.h" #include "lockfile.h" -#include "object-store.h" +#include "odb.h" #include "commit.h" #include "tag.h" #include "pkt-line.h" diff --git a/streaming.c b/streaming.c index 6d6512e2e0..81c42673a2 100644 --- a/streaming.c +++ b/streaming.c @@ -10,7 +10,7 @@ #include "streaming.h" #include "repository.h" #include "object-file.h" -#include "object-store.h" +#include "odb.h" #include "replace-object.h" #include "packfile.h" diff --git a/submodule-config.c b/submodule-config.c index b30d9365fb..9c80f9f7b6 100644 --- a/submodule-config.c +++ b/submodule-config.c @@ -13,7 +13,7 @@ #include "submodule.h" #include "strbuf.h" #include "object-name.h" -#include "object-store.h" +#include "odb.h" #include "parse-options.h" #include "thread-utils.h" #include "tree-walk.h" diff --git a/submodule.c b/submodule.c index ead3fb5dad..9b1018877d 100644 --- a/submodule.c +++ b/submodule.c @@ -27,7 +27,7 @@ #include "parse-options.h" #include "object-file.h" #include "object-name.h" -#include "object-store.h" +#include "odb.h" #include "commit-reach.h" #include "read-cache-ll.h" #include "setup.h" diff --git a/t/helper/test-find-pack.c b/t/helper/test-find-pack.c index 76c2f4eba8..611a13a326 100644 --- a/t/helper/test-find-pack.c +++ b/t/helper/test-find-pack.c @@ -2,7 +2,7 @@ #include "test-tool.h" #include "object-name.h" -#include "object-store.h" +#include "odb.h" #include "packfile.h" #include "parse-options.h" #include "setup.h" diff --git a/t/helper/test-pack-mtimes.c b/t/helper/test-pack-mtimes.c index fdf1b13437..d51aaa3dc4 100644 --- a/t/helper/test-pack-mtimes.c +++ b/t/helper/test-pack-mtimes.c @@ -3,7 +3,7 @@ #include "test-tool.h" #include "hex.h" #include "strbuf.h" -#include "object-store.h" +#include "odb.h" #include "packfile.h" #include "pack-mtimes.h" #include "setup.h" diff --git a/t/helper/test-partial-clone.c b/t/helper/test-partial-clone.c index 34f1aee558..dba227259a 100644 --- a/t/helper/test-partial-clone.c +++ b/t/helper/test-partial-clone.c @@ -1,7 +1,7 @@ #include "test-tool.h" #include "hex.h" #include "repository.h" -#include "object-store.h" +#include "odb.h" #include "setup.h" /* diff --git a/t/helper/test-read-graph.c b/t/helper/test-read-graph.c index 53b633e2ba..ef5339bbee 100644 --- a/t/helper/test-read-graph.c +++ b/t/helper/test-read-graph.c @@ -3,7 +3,7 @@ #include "test-tool.h" #include "commit-graph.h" #include "repository.h" -#include "object-store.h" +#include "odb.h" #include "bloom.h" #include "setup.h" diff --git a/t/helper/test-read-midx.c b/t/helper/test-read-midx.c index ac81390899..da2aa036b5 100644 --- a/t/helper/test-read-midx.c +++ b/t/helper/test-read-midx.c @@ -4,7 +4,7 @@ #include "hex.h" #include "midx.h" #include "repository.h" -#include "object-store.h" +#include "odb.h" #include "pack-bitmap.h" #include "packfile.h" #include "setup.h" diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c index 4cfc7c90b5..2920ca59d7 100644 --- a/t/helper/test-ref-store.c +++ b/t/helper/test-ref-store.c @@ -5,7 +5,7 @@ #include "refs.h" #include "setup.h" #include "worktree.h" -#include "object-store.h" +#include "odb.h" #include "path.h" #include "repository.h" #include "strbuf.h" diff --git a/tag.c b/tag.c index 05be39067c..5f6868bf7b 100644 --- a/tag.c +++ b/tag.c @@ -5,7 +5,7 @@ #include "environment.h" #include "tag.h" #include "object-name.h" -#include "object-store.h" +#include "odb.h" #include "commit.h" #include "tree.h" #include "blob.h" diff --git a/tmp-objdir.c b/tmp-objdir.c index 056484404b..bef2f917cd 100644 --- a/tmp-objdir.c +++ b/tmp-objdir.c @@ -10,7 +10,7 @@ #include "strbuf.h" #include "strvec.h" #include "quote.h" -#include "object-store.h" +#include "odb.h" #include "repository.h" struct tmp_objdir { diff --git a/tree-walk.c b/tree-walk.c index 90655d5237..34b0fff487 100644 --- a/tree-walk.c +++ b/tree-walk.c @@ -6,7 +6,7 @@ #include "gettext.h" #include "hex.h" #include "object-file.h" -#include "object-store.h" +#include "odb.h" #include "trace2.h" #include "tree.h" #include "pathspec.h" diff --git a/tree.c b/tree.c index b85f56267f..341b7c2ff3 100644 --- a/tree.c +++ b/tree.c @@ -4,7 +4,7 @@ #include "hex.h" #include "tree.h" #include "object-name.h" -#include "object-store.h" +#include "odb.h" #include "commit.h" #include "alloc.h" #include "tree-walk.h" diff --git a/unpack-trees.c b/unpack-trees.c index 471837f032..f38c761ab9 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -26,7 +26,7 @@ #include "symlinks.h" #include "trace2.h" #include "fsmonitor.h" -#include "object-store.h" +#include "odb.h" #include "promisor-remote.h" #include "entry.h" #include "parallel-checkout.h" diff --git a/upload-pack.c b/upload-pack.c index 26f29b85b5..e994d6a901 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -10,7 +10,7 @@ #include "pkt-line.h" #include "sideband.h" #include "repository.h" -#include "object-store.h" +#include "odb.h" #include "oid-array.h" #include "object.h" #include "commit.h" diff --git a/walker.c b/walker.c index b470d43e54..a8abe8a2e7 100644 --- a/walker.c +++ b/walker.c @@ -5,7 +5,7 @@ #include "hex.h" #include "walker.h" #include "repository.h" -#include "object-store.h" +#include "odb.h" #include "commit.h" #include "strbuf.h" #include "tree.h" diff --git a/xdiff-interface.c b/xdiff-interface.c index 1edcd319e6..01e6e378ea 100644 --- a/xdiff-interface.c +++ b/xdiff-interface.c @@ -5,7 +5,7 @@ #include "gettext.h" #include "config.h" #include "hex.h" -#include "object-store.h" +#include "odb.h" #include "strbuf.h" #include "xdiff-interface.h" #include "xdiff/xtypes.h" -- cgit v1.2.3 From bd52ea343d2af91574fedcf765250f44f3d624d4 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Tue, 1 Jul 2025 14:22:17 +0200 Subject: odb: get rid of `the_repository` in `find_odb()` Get rid of our dependency on `the_repository` in `find_odb()` by passing in the object database in which we want to search for the source and adjusting all callers. Rename the function to `odb_find_source()`. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- builtin/commit-graph.c | 4 ++-- midx-write.c | 2 +- odb.c | 6 +++--- odb.h | 7 ++++++- 4 files changed, 12 insertions(+), 7 deletions(-) (limited to 'builtin/commit-graph.c') diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c index f04eaba525..77d7e88a98 100644 --- a/builtin/commit-graph.c +++ b/builtin/commit-graph.c @@ -101,7 +101,7 @@ static int graph_verify(int argc, const char **argv, const char *prefix, if (opts.progress) flags |= COMMIT_GRAPH_WRITE_PROGRESS; - source = find_odb(the_repository, opts.obj_dir); + source = odb_find_source(the_repository->objects, opts.obj_dir); graph_name = get_commit_graph_filename(source); chain_name = get_commit_graph_chain_filename(source); if (open_commit_graph(graph_name, &fd, &st)) @@ -289,7 +289,7 @@ 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 = find_odb(the_repository, opts.obj_dir); + source = odb_find_source(the_repository->objects, opts.obj_dir); if (opts.reachable) { if (write_commit_graph_reachable(source, flags, &write_opts)) diff --git a/midx-write.c b/midx-write.c index ba4a94950a..f2cfb85476 100644 --- a/midx-write.c +++ b/midx-write.c @@ -922,7 +922,7 @@ static struct multi_pack_index *lookup_multi_pack_index(struct repository *r, struct strbuf cur_path_real = STRBUF_INIT; /* Ensure the given object_dir is local, or a known alternate. */ - find_odb(r, obj_dir_real); + odb_find_source(r->objects, obj_dir_real); for (cur = get_multi_pack_index(r); cur; cur = cur->next) { strbuf_realpath(&cur_path_real, cur->object_dir, 1); diff --git a/odb.c b/odb.c index 0464d7f54a..240fc62ca2 100644 --- a/odb.c +++ b/odb.c @@ -448,14 +448,14 @@ out: return ref_git; } -struct odb_source *find_odb(struct repository *r, const char *obj_dir) +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; - prepare_alt_odb(r); - for (source = r->objects->sources; source; source = source->next) { + prepare_alt_odb(odb->repo); + 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; diff --git a/odb.h b/odb.h index c3851e2966..941329c694 100644 --- a/odb.h +++ b/odb.h @@ -68,7 +68,6 @@ struct odb_source { void prepare_alt_odb(struct repository *r); int has_alt_odb(struct repository *r); char *compute_alternate_path(const char *path, struct strbuf *err); -struct odb_source *find_odb(struct repository *r, const char *obj_dir); typedef int alt_odb_fn(struct odb_source *, void *); int foreach_alt_odb(alt_odb_fn, void*); typedef void alternate_ref_fn(const struct object_id *oid, void *); @@ -195,6 +194,12 @@ struct object_database { struct object_database *odb_new(struct repository *repo); void odb_clear(struct object_database *o); +/* + * Find source by its object directory path. Dies in case the source couldn't + * be found. + */ +struct odb_source *odb_find_source(struct object_database *odb, const char *obj_dir); + /* * Create a temporary file rooted in the object database directory, or * die on failure. The filename is taken from "pattern", which should have the -- cgit v1.2.3