about summary refs log tree commit
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2018-04-11 13:09:55 +0900
committerJunio C Hamano <gitster@pobox.com>2018-04-11 13:09:55 +0900
commitcf0b1793ead9428d88e6592e624c7cb222913c58 (patch)
tree13906a437b3a68fdaf9cfa4617280dae44aa41db
parent5ff42d42da9c2c26737988d19b347c99489c8faa (diff)
parent4a7c05f7d7f17cd7a42fa944e79c2ef294cb17b6 (diff)
downloadgit-cf0b1793ead9428d88e6592e624c7cb222913c58.tar.gz
Refactoring the internal global data structure to make it possible
to open multiple repositories, work with and then close them.

Rerolled by Duy on top of a separate preliminary clean-up topic.
The resulting structure of the topics looked very sensible.

* sb/object-store: (27 commits)
  sha1_file: allow sha1_loose_object_info to handle arbitrary repositories
  sha1_file: allow map_sha1_file to handle arbitrary repositories
  sha1_file: allow map_sha1_file_1 to handle arbitrary repositories
  sha1_file: allow open_sha1_file to handle arbitrary repositories
  sha1_file: allow stat_sha1_file to handle arbitrary repositories
  sha1_file: allow sha1_file_name to handle arbitrary repositories
  sha1_file: add repository argument to sha1_loose_object_info
  sha1_file: add repository argument to map_sha1_file
  sha1_file: add repository argument to map_sha1_file_1
  sha1_file: add repository argument to open_sha1_file
  sha1_file: add repository argument to stat_sha1_file
  sha1_file: add repository argument to sha1_file_name
  sha1_file: allow prepare_alt_odb to handle arbitrary repositories
  sha1_file: allow link_alt_odb_entries to handle arbitrary repositories
  sha1_file: add repository argument to prepare_alt_odb
  sha1_file: add repository argument to link_alt_odb_entries
  sha1_file: add repository argument to read_info_alternates
  sha1_file: add repository argument to link_alt_odb_entry
  sha1_file: add raw_object_store argument to alt_odb_usable
  pack: move approximate object count to object store
  ...
-rw-r--r--builtin/am.c2
-rw-r--r--builtin/clone.c3
-rw-r--r--builtin/count-objects.c6
-rw-r--r--builtin/fetch.c2
-rw-r--r--builtin/fsck.c13
-rw-r--r--builtin/gc.c4
-rw-r--r--builtin/grep.c3
-rw-r--r--builtin/index-pack.c1
-rw-r--r--builtin/merge.c2
-rw-r--r--builtin/pack-objects.c21
-rw-r--r--builtin/pack-redundant.c6
-rw-r--r--builtin/receive-pack.c2
-rw-r--r--builtin/submodule--helper.c1
-rw-r--r--cache.h87
-rw-r--r--environment.c5
-rw-r--r--fast-import.c8
-rw-r--r--http-backend.c6
-rw-r--r--http-push.c1
-rw-r--r--http-walker.c4
-rw-r--r--http.c6
-rw-r--r--object-store.h132
-rw-r--r--object.c42
-rw-r--r--pack-bitmap.c4
-rw-r--r--pack-check.c1
-rw-r--r--pack-revindex.c1
-rw-r--r--packfile.c77
-rw-r--r--packfile.h5
-rw-r--r--path.c3
-rw-r--r--reachable.c1
-rw-r--r--repository.c15
-rw-r--r--repository.h11
-rw-r--r--server-info.c6
-rw-r--r--sha1_file.c125
-rw-r--r--sha1_name.c11
-rw-r--r--streaming.c5
-rw-r--r--submodule.c1
-rw-r--r--t/helper/test-ref-store.c1
-rw-r--r--tmp-objdir.c1
-rw-r--r--transport.c1
39 files changed, 393 insertions, 233 deletions
diff --git a/builtin/am.c b/builtin/am.c
index 1bcc3606c5..9c82603f70 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -1862,7 +1862,7 @@ next:
          */
         if (!state->rebasing) {
                 am_destroy(state);
-                close_all_packs();
+                close_all_packs(the_repository->objects);
                 run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);
         }
 }
diff --git a/builtin/clone.c b/builtin/clone.c
index 101c27a593..7df5932b85 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -27,6 +27,7 @@
 #include "connected.h"
 #include "packfile.h"
 #include "list-objects-filter-options.h"
+#include "object-store.h"
 
 /*
  * Overall FIXMEs:
@@ -1217,7 +1218,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
         transport_disconnect(transport);
 
         if (option_dissociate) {
-                close_all_packs();
+                close_all_packs(the_repository->objects);
                 dissociate_from_references();
         }
 
diff --git a/builtin/count-objects.c b/builtin/count-objects.c
index 33343818c8..b28ff00be2 100644
--- a/builtin/count-objects.c
+++ b/builtin/count-objects.c
@@ -7,10 +7,12 @@
 #include "cache.h"
 #include "config.h"
 #include "dir.h"
+#include "repository.h"
 #include "builtin.h"
 #include "parse-options.h"
 #include "quote.h"
 #include "packfile.h"
+#include "object-store.h"
 
 static unsigned long garbage;
 static off_t size_garbage;
@@ -120,9 +122,9 @@ int cmd_count_objects(int argc, const char **argv, const char *prefix)
                 struct strbuf loose_buf = STRBUF_INIT;
                 struct strbuf pack_buf = STRBUF_INIT;
                 struct strbuf garbage_buf = STRBUF_INIT;
-                if (!packed_git)
+                if (!get_packed_git(the_repository))
                         prepare_packed_git();
-                for (p = packed_git; p; p = p->next) {
+                for (p = get_packed_git(the_repository); p; p = p->next) {
                         if (!p->pack_local)
                                 continue;
                         if (open_pack_index(p))
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 8295f92b3e..dcdfc66f09 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -1516,7 +1516,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
 
         string_list_clear(&list, 0);
 
-        close_all_packs();
+        close_all_packs(the_repository->objects);
 
         argv_array_pushl(&argv_gc_auto, "gc", "--auto", NULL);
         if (verbosity < 0)
diff --git a/builtin/fsck.c b/builtin/fsck.c
index 0922558683..13c0a8048e 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -1,5 +1,6 @@
 #include "builtin.h"
 #include "cache.h"
+#include "repository.h"
 #include "config.h"
 #include "commit.h"
 #include "tree.h"
@@ -16,6 +17,7 @@
 #include "streaming.h"
 #include "decorate.h"
 #include "packfile.h"
+#include "object-store.h"
 
 #define REACHABLE 0x0001
 #define SEEN      0x0002
@@ -719,9 +721,12 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
                 for_each_loose_object(mark_loose_for_connectivity, NULL, 0);
                 for_each_packed_object(mark_packed_for_connectivity, NULL, 0);
         } else {
+                struct alternate_object_database *alt_odb_list;
+
                 fsck_object_dir(get_object_directory());
 
-                prepare_alt_odb();
+                prepare_alt_odb(the_repository);
+                alt_odb_list = the_repository->objects->alt_odb_list;
                 for (alt = alt_odb_list; alt; alt = alt->next)
                         fsck_object_dir(alt->path);
 
@@ -733,7 +738,8 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
                         prepare_packed_git();
 
                         if (show_progress) {
-                                for (p = packed_git; p; p = p->next) {
+                                for (p = get_packed_git(the_repository); p;
+                                     p = p->next) {
                                         if (open_pack_index(p))
                                                 continue;
                                         total += p->num_objects;
@@ -741,7 +747,8 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
 
                                 progress = start_progress(_("Checking objects"), total);
                         }
-                        for (p = packed_git; p; p = p->next) {
+                        for (p = get_packed_git(the_repository); p;
+                             p = p->next) {
                                 /* verify gives error messages itself */
                                 if (verify_pack(p, fsck_obj_buffer,
                                                 progress, count))
diff --git a/builtin/gc.c b/builtin/gc.c
index f51e5a6500..cef38e5427 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -11,6 +11,7 @@
  */
 
 #include "builtin.h"
+#include "repository.h"
 #include "config.h"
 #include "tempfile.h"
 #include "lockfile.h"
@@ -20,6 +21,7 @@
 #include "argv-array.h"
 #include "commit.h"
 #include "packfile.h"
+#include "object-store.h"
 
 #define FAILED_RUN "failed to run %s"
 
@@ -173,7 +175,7 @@ static int too_many_packs(void)
                 return 0;
 
         prepare_packed_git();
-        for (cnt = 0, p = packed_git; p; p = p->next) {
+        for (cnt = 0, p = get_packed_git(the_repository); p; p = p->next) {
                 if (!p->pack_local)
                         continue;
                 if (p->pack_keep)
diff --git a/builtin/grep.c b/builtin/grep.c
index 668cb8050a..5f32d2ce84 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -22,6 +22,7 @@
 #include "pathspec.h"
 #include "submodule.h"
 #include "submodule-config.h"
+#include "object-store.h"
 
 static char const * const grep_usage[] = {
         N_("git grep [<options>] [-e] <pattern> [<rev>...] [[--] <path>...]"),
@@ -439,7 +440,7 @@ static int grep_submodule(struct grep_opt *opt, struct repository *superproject,
          * object.
          */
         grep_read_lock();
-        add_to_alternates_memory(submodule.objectdir);
+        add_to_alternates_memory(submodule.objects->objectdir);
         grep_read_unlock();
 
         if (oid) {
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index 657a5dda06..d81473e722 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -13,6 +13,7 @@
 #include "streaming.h"
 #include "thread-utils.h"
 #include "packfile.h"
+#include "object-store.h"
 
 static const char index_pack_usage[] =
 "git index-pack [-v] [-o <index-file>] [--keep | --keep=<msg>] [--verify] [--strict] (<pack-file> | --stdin [--fix-thin] [<pack-file>])";
diff --git a/builtin/merge.c b/builtin/merge.c
index 8746c5e3e8..9db5a2cf16 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -412,7 +412,7 @@ static void finish(struct commit *head_commit,
                          * We ignore errors in 'gc --auto', since the
                          * user should see them.
                          */
-                        close_all_packs();
+                        close_all_packs(the_repository->objects);
                         run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);
                 }
         }
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index e7e673266e..89f49bb5f6 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -1,5 +1,6 @@
 #include "builtin.h"
 #include "cache.h"
+#include "repository.h"
 #include "config.h"
 #include "attr.h"
 #include "object.h"
@@ -28,6 +29,7 @@
 #include "argv-array.h"
 #include "list.h"
 #include "packfile.h"
+#include "object-store.h"
 
 static const char *pack_usage[] = {
         N_("git pack-objects --stdout [<options>...] [< <ref-list> | < <object-list>]"),
@@ -1023,8 +1025,7 @@ static int want_object_in_pack(const struct object_id *oid,
                 if (want != -1)
                         return want;
         }
-
-        list_for_each(pos, &packed_git_mru) {
+        list_for_each(pos, get_packed_git_mru(the_repository)) {
                 struct packed_git *p = list_entry(pos, struct packed_git, mru);
                 off_t offset;
 
@@ -1042,7 +1043,8 @@ static int want_object_in_pack(const struct object_id *oid,
                         }
                         want = want_found_object(exclude, p);
                         if (!exclude && want > 0)
-                                list_move(&p->mru, &packed_git_mru);
+                                list_move(&p->mru,
+                                          get_packed_git_mru(the_repository));
                         if (want != -1)
                                 return want;
                 }
@@ -2669,7 +2671,7 @@ static void add_objects_in_unpacked_packs(struct rev_info *revs)
 
         memset(&in_pack, 0, sizeof(in_pack));
 
-        for (p = packed_git; p; p = p->next) {
+        for (p = get_packed_git(the_repository); p; p = p->next) {
                 struct object_id oid;
                 struct object *o;
 
@@ -2732,7 +2734,8 @@ static int has_sha1_pack_kept_or_nonlocal(const struct object_id *oid)
         static struct packed_git *last_found = (void *)1;
         struct packed_git *p;
 
-        p = (last_found != (void *)1) ? last_found : packed_git;
+        p = (last_found != (void *)1) ? last_found :
+                                        get_packed_git(the_repository);
 
         while (p) {
                 if ((!p->pack_local || p->pack_keep) &&
@@ -2741,7 +2744,7 @@ static int has_sha1_pack_kept_or_nonlocal(const struct object_id *oid)
                         return 1;
                 }
                 if (p == last_found)
-                        p = packed_git;
+                        p = get_packed_git(the_repository);
                 else
                         p = p->next;
                 if (p == last_found)
@@ -2777,7 +2780,7 @@ static void loosen_unused_packed_objects(struct rev_info *revs)
         uint32_t i;
         struct object_id oid;
 
-        for (p = packed_git; p; p = p->next) {
+        for (p = get_packed_git(the_repository); p; p = p->next) {
                 if (!p->pack_local || p->pack_keep)
                         continue;
 
@@ -3148,7 +3151,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
         prepare_packed_git();
         if (ignore_packed_keep) {
                 struct packed_git *p;
-                for (p = packed_git; p; p = p->next)
+                for (p = get_packed_git(the_repository); p; p = p->next)
                         if (p->pack_local && p->pack_keep)
                                 break;
                 if (!p) /* no keep-able packs found */
@@ -3161,7 +3164,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
                  * also covers non-local objects
                  */
                 struct packed_git *p;
-                for (p = packed_git; p; p = p->next) {
+                for (p = get_packed_git(the_repository); p; p = p->next) {
                         if (!p->pack_local) {
                                 have_non_local_packs = 1;
                                 break;
diff --git a/builtin/pack-redundant.c b/builtin/pack-redundant.c
index 991e1bb76f..f060b941b5 100644
--- a/builtin/pack-redundant.c
+++ b/builtin/pack-redundant.c
@@ -7,7 +7,9 @@
 */
 
 #include "builtin.h"
+#include "repository.h"
 #include "packfile.h"
+#include "object-store.h"
 
 #define BLKSIZE 512
 
@@ -571,7 +573,7 @@ static struct pack_list * add_pack(struct packed_git *p)
 
 static struct pack_list * add_pack_file(const char *filename)
 {
-        struct packed_git *p = packed_git;
+        struct packed_git *p = get_packed_git(the_repository);
 
         if (strlen(filename) < 40)
                 die("Bad pack filename: %s", filename);
@@ -586,7 +588,7 @@ static struct pack_list * add_pack_file(const char *filename)
 
 static void load_all(void)
 {
-        struct packed_git *p = packed_git;
+        struct packed_git *p = get_packed_git(the_repository);
 
         while (p) {
                 add_pack(p);
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index 2bf7f2d1a3..19428ef97d 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -2027,7 +2027,7 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
                         proc.git_cmd = 1;
                         proc.argv = argv_gc_auto;
 
-                        close_all_packs();
+                        close_all_packs(the_repository->objects);
                         if (!start_command(&proc)) {
                                 if (use_sideband)
                                         copy_to_sideband(proc.err, -1, NULL);
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 6ba8587b6d..a2327c98b0 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -16,6 +16,7 @@
 #include "revision.h"
 #include "diffcore.h"
 #include "diff.h"
+#include "object-store.h"
 
 #define OPT_QUIET (1 << 0)
 #define OPT_CACHED (1 << 1)
diff --git a/cache.h b/cache.h
index 6e45c1b537..bbaf5c349a 100644
--- a/cache.h
+++ b/cache.h
@@ -941,12 +941,6 @@ extern void check_repository_format(void);
 #define TYPE_CHANGED    0x0040
 
 /*
- * Put in `buf` the name of the file in the local object database that
- * would be used to store a loose object with the specified sha1.
- */
-extern void sha1_file_name(struct strbuf *buf, const unsigned char *sha1);
-
-/*
  * Return an abbreviated sha1 unique within this repository's object database.
  * The result will be at least `len` characters long, and will be NUL
  * terminated.
@@ -1236,7 +1230,6 @@ extern int force_object_loose(const struct object_id *oid, time_t mtime);
 
 extern int git_open_cloexec(const char *name, int flags);
 #define git_open(name) git_open_cloexec(name, O_RDONLY)
-extern void *map_sha1_file(const unsigned char *sha1, unsigned long *size);
 extern int unpack_sha1_header(git_zstream *stream, unsigned char *map, unsigned long mapsize, void *buffer, unsigned long bufsiz);
 extern int parse_sha1_header(const char *hdr, unsigned long *sizep);
 
@@ -1564,57 +1557,6 @@ extern int has_dirs_only_path(const char *name, int len, int prefix_len);
 extern void schedule_dir_for_removal(const char *name, int len);
 extern void remove_scheduled_dirs(void);
 
-extern struct alternate_object_database {
-        struct alternate_object_database *next;
-
-        /* see alt_scratch_buf() */
-        struct strbuf scratch;
-        size_t base_len;
-
-        /*
-         * Used to store the results of readdir(3) calls when searching
-         * for unique abbreviated hashes.  This cache is never
-         * invalidated, thus it's racy and not necessarily accurate.
-         * That's fine for its purpose; don't use it for tasks requiring
-         * greater accuracy!
-         */
-        char loose_objects_subdir_seen[256];
-        struct oid_array loose_objects_cache;
-
-        char path[FLEX_ARRAY];
-} *alt_odb_list;
-extern void prepare_alt_odb(void);
-extern char *compute_alternate_path(const char *path, struct strbuf *err);
-typedef int alt_odb_fn(struct alternate_object_database *, void *);
-extern int foreach_alt_odb(alt_odb_fn, void*);
-
-/*
- * Allocate a "struct alternate_object_database" but do _not_ actually
- * add it to the list of alternates.
- */
-struct alternate_object_database *alloc_alt_odb(const char *dir);
-
-/*
- * Add the directory to the on-disk alternates file; the new entry will also
- * take effect in the current process.
- */
-extern 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.
- */
-extern void add_to_alternates_memory(const char *dir);
-
-/*
- * Returns a scratch strbuf pre-filled with the alternate object directory,
- * including a trailing slash, which can be used to access paths in the
- * alternate. Always use this over direct access to alt->scratch, as it
- * cleans up any previous use of the scratch buffer.
- */
-extern struct strbuf *alt_scratch_buf(struct alternate_object_database *alt);
-
 struct pack_window {
         struct pack_window *next;
         unsigned char *base;
@@ -1624,35 +1566,6 @@ struct pack_window {
         unsigned int inuse_cnt;
 };
 
-extern struct packed_git {
-        struct packed_git *next;
-        struct list_head mru;
-        struct pack_window *windows;
-        off_t pack_size;
-        const void *index_data;
-        size_t index_size;
-        uint32_t num_objects;
-        uint32_t num_bad_objects;
-        unsigned char *bad_object_sha1;
-        int index_version;
-        time_t mtime;
-        int pack_fd;
-        unsigned pack_local:1,
-                 pack_keep:1,
-                 freshened:1,
-                 do_not_close:1,
-                 pack_promisor:1;
-        unsigned char sha1[20];
-        struct revindex_entry *revindex;
-        /* something like ".git/objects/pack/xxxxx.pack" */
-        char pack_name[FLEX_ARRAY]; /* more */
-} *packed_git;
-
-/*
- * A most-recently-used ordered version of the packed_git list.
- */
-extern struct list_head packed_git_mru;
-
 struct pack_entry {
         off_t offset;
         unsigned char sha1[20];
diff --git a/environment.c b/environment.c
index 21565c3c52..39b3d906c8 100644
--- a/environment.c
+++ b/environment.c
@@ -14,6 +14,7 @@
 #include "fmt-merge-msg.h"
 #include "commit.h"
 #include "argv-array.h"
+#include "object-store.h"
 
 int trust_executable_bit = 1;
 int trust_ctime = 1;
@@ -270,9 +271,9 @@ const char *get_git_work_tree(void)
 
 char *get_object_directory(void)
 {
-        if (!the_repository->objectdir)
+        if (!the_repository->objects->objectdir)
                 BUG("git environment hasn't been setup");
-        return the_repository->objectdir;
+        return the_repository->objects->objectdir;
 }
 
 int odb_mkstemp(struct strbuf *temp_filename, const char *pattern)
diff --git a/fast-import.c b/fast-import.c
index a2e8b1d763..b2f6d6d583 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -154,6 +154,7 @@ Format of STDIN stream:
 
 #include "builtin.h"
 #include "cache.h"
+#include "repository.h"
 #include "config.h"
 #include "lockfile.h"
 #include "object.h"
@@ -168,6 +169,7 @@ Format of STDIN stream:
 #include "dir.h"
 #include "run-command.h"
 #include "packfile.h"
+#include "object-store.h"
 
 #define PACK_ID_BITS 16
 #define MAX_PACK_ID ((1<<PACK_ID_BITS)-1)
@@ -1110,7 +1112,8 @@ static int store_object(
         if (e->idx.offset) {
                 duplicate_count_by_type[type]++;
                 return 1;
-        } else if (find_sha1_pack(oid.hash, packed_git)) {
+        } else if (find_sha1_pack(oid.hash,
+                                  get_packed_git(the_repository))) {
                 e->type = type;
                 e->pack_id = MAX_PACK_ID;
                 e->idx.offset = 1; /* just not zero! */
@@ -1307,7 +1310,8 @@ static void stream_blob(uintmax_t len, struct object_id *oidout, uintmax_t mark)
                 duplicate_count_by_type[OBJ_BLOB]++;
                 truncate_pack(&checkpoint);
 
-        } else if (find_sha1_pack(oid.hash, packed_git)) {
+        } else if (find_sha1_pack(oid.hash,
+                                  get_packed_git(the_repository))) {
                 e->type = OBJ_BLOB;
                 e->pack_id = MAX_PACK_ID;
                 e->idx.offset = 1; /* just not zero! */
diff --git a/http-backend.c b/http-backend.c
index f3dc218b2a..64dde78c1b 100644
--- a/http-backend.c
+++ b/http-backend.c
@@ -1,5 +1,6 @@
 #include "cache.h"
 #include "config.h"
+#include "repository.h"
 #include "refs.h"
 #include "pkt-line.h"
 #include "object.h"
@@ -10,6 +11,7 @@
 #include "url.h"
 #include "argv-array.h"
 #include "packfile.h"
+#include "object-store.h"
 
 static const char content_type[] = "Content-Type";
 static const char content_length[] = "Content-Length";
@@ -518,13 +520,13 @@ static void get_info_packs(struct strbuf *hdr, char *arg)
 
         select_getanyfile(hdr);
         prepare_packed_git();
-        for (p = packed_git; p; p = p->next) {
+        for (p = get_packed_git(the_repository); p; p = p->next) {
                 if (p->pack_local)
                         cnt++;
         }
 
         strbuf_grow(&buf, cnt * 53 + 2);
-        for (p = packed_git; p; p = p->next) {
+        for (p = get_packed_git(the_repository); p; p = p->next) {
                 if (p->pack_local)
                         strbuf_addf(&buf, "P %s\n", p->pack_name + objdirlen + 6);
         }
diff --git a/http-push.c b/http-push.c
index ff82b63133..c0998fd763 100644
--- a/http-push.c
+++ b/http-push.c
@@ -12,6 +12,7 @@
 #include "sigchain.h"
 #include "argv-array.h"
 #include "packfile.h"
+#include "object-store.h"
 
 #ifdef EXPAT_NEEDS_XMLPARSE_H
 #include <xmlparse.h>
diff --git a/http-walker.c b/http-walker.c
index f506f394ac..7cdfb2f24c 100644
--- a/http-walker.c
+++ b/http-walker.c
@@ -1,10 +1,12 @@
 #include "cache.h"
+#include "repository.h"
 #include "commit.h"
 #include "walker.h"
 #include "http.h"
 #include "list.h"
 #include "transport.h"
 #include "packfile.h"
+#include "object-store.h"
 
 struct alt_base {
         char *base;
@@ -545,7 +547,7 @@ static int fetch_object(struct walker *walker, unsigned char *sha1)
                 ret = error("File %s has bad hash", hex);
         } else if (req->rename < 0) {
                 struct strbuf buf = STRBUF_INIT;
-                sha1_file_name(&buf, req->sha1);
+                sha1_file_name(the_repository, &buf, req->sha1);
                 ret = error("unable to write sha1 filename %s", buf.buf);
                 strbuf_release(&buf);
         }
diff --git a/http.c b/http.c
index a5bd5d62c2..9304045b6c 100644
--- a/http.c
+++ b/http.c
@@ -14,6 +14,7 @@
 #include "packfile.h"
 #include "protocol.h"
 #include "string-list.h"
+#include "object-store.h"
 
 static struct trace_key trace_curl = TRACE_KEY_INIT(CURL);
 static int trace_curl_data = 1;
@@ -2248,7 +2249,7 @@ struct http_object_request *new_http_object_request(const char *base_url,
         hashcpy(freq->sha1, sha1);
         freq->localfile = -1;
 
-        sha1_file_name(&filename, sha1);
+        sha1_file_name(the_repository, &filename, sha1);
         snprintf(freq->tmpfile, sizeof(freq->tmpfile),
                  "%s.temp", filename.buf);
 
@@ -2397,8 +2398,7 @@ int finish_http_object_request(struct http_object_request *freq)
                 unlink_or_warn(freq->tmpfile);
                 return -1;
         }
-
-        sha1_file_name(&filename, freq->sha1);
+        sha1_file_name(the_repository, &filename, freq->sha1);
         freq->rename = finalize_object_file(freq->tmpfile, filename.buf);
         strbuf_release(&filename);
 
diff --git a/object-store.h b/object-store.h
new file mode 100644
index 0000000000..fef33f345f
--- /dev/null
+++ b/object-store.h
@@ -0,0 +1,132 @@
+#ifndef OBJECT_STORE_H
+#define OBJECT_STORE_H
+
+struct alternate_object_database {
+        struct alternate_object_database *next;
+
+        /* see alt_scratch_buf() */
+        struct strbuf scratch;
+        size_t base_len;
+
+        /*
+         * Used to store the results of readdir(3) calls when searching
+         * for unique abbreviated hashes.  This cache is never
+         * invalidated, thus it's racy and not necessarily accurate.
+         * That's fine for its purpose; don't use it for tasks requiring
+         * greater accuracy!
+         */
+        char loose_objects_subdir_seen[256];
+        struct oid_array loose_objects_cache;
+
+        /*
+         * Path to the alternative object store. If this is a relative path,
+         * it is relative to the current working directory.
+         */
+        char path[FLEX_ARRAY];
+};
+void prepare_alt_odb(struct repository *r);
+char *compute_alternate_path(const char *path, struct strbuf *err);
+typedef int alt_odb_fn(struct alternate_object_database *, void *);
+int foreach_alt_odb(alt_odb_fn, void*);
+
+/*
+ * Allocate a "struct alternate_object_database" but do _not_ actually
+ * add it to the list of alternates.
+ */
+struct alternate_object_database *alloc_alt_odb(const char *dir);
+
+/*
+ * 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);
+
+/*
+ * Returns a scratch strbuf pre-filled with the alternate object directory,
+ * including a trailing slash, which can be used to access paths in the
+ * alternate. Always use this over direct access to alt->scratch, as it
+ * cleans up any previous use of the scratch buffer.
+ */
+struct strbuf *alt_scratch_buf(struct alternate_object_database *alt);
+
+struct packed_git {
+        struct packed_git *next;
+        struct list_head mru;
+        struct pack_window *windows;
+        off_t pack_size;
+        const void *index_data;
+        size_t index_size;
+        uint32_t num_objects;
+        uint32_t num_bad_objects;
+        unsigned char *bad_object_sha1;
+        int index_version;
+        time_t mtime;
+        int pack_fd;
+        unsigned pack_local:1,
+                 pack_keep:1,
+                 freshened:1,
+                 do_not_close:1,
+                 pack_promisor:1;
+        unsigned char sha1[20];
+        struct revindex_entry *revindex;
+        /* something like ".git/objects/pack/xxxxx.pack" */
+        char pack_name[FLEX_ARRAY]; /* more */
+};
+
+struct raw_object_store {
+        /*
+         * Path to the repository's object store.
+         * Cannot be NULL after initialization.
+         */
+        char *objectdir;
+
+        /* Path to extra alternate object database if not NULL */
+        char *alternate_db;
+
+        struct alternate_object_database *alt_odb_list;
+        struct alternate_object_database **alt_odb_tail;
+
+        /*
+         * 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;
+
+        /*
+         * A fast, rough count of the number of objects in the repository.
+         * These two fields are not meant for direct access. Use
+         * 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 raw_object_store *raw_object_store_new(void);
+void raw_object_store_clear(struct raw_object_store *o);
+
+/*
+ * Put in `buf` the name of the file in the local object database that
+ * would be used to store a loose object with the specified sha1.
+ */
+void sha1_file_name(struct repository *r, struct strbuf *buf, const unsigned char *sha1);
+
+void *map_sha1_file(struct repository *r, const unsigned char *sha1, unsigned long *size);
+
+#endif /* OBJECT_STORE_H */
diff --git a/object.c b/object.c
index 2c909385a7..a0a756f24f 100644
--- a/object.c
+++ b/object.c
@@ -4,6 +4,8 @@
 #include "tree.h"
 #include "commit.h"
 #include "tag.h"
+#include "object-store.h"
+#include "packfile.h"
 
 static struct object **obj_hash;
 static int nr_objs, obj_hash_size;
@@ -445,3 +447,43 @@ void clear_commit_marks_all(unsigned int flags)
                         obj->flags &= ~flags;
         }
 }
+
+struct raw_object_store *raw_object_store_new(void)
+{
+        struct raw_object_store *o = xmalloc(sizeof(*o));
+
+        memset(o, 0, sizeof(*o));
+        INIT_LIST_HEAD(&o->packed_git_mru);
+        return o;
+}
+
+static void free_alt_odb(struct alternate_object_database *alt)
+{
+        strbuf_release(&alt->scratch);
+        oid_array_clear(&alt->loose_objects_cache);
+        free(alt);
+}
+
+static void free_alt_odbs(struct raw_object_store *o)
+{
+        while (o->alt_odb_list) {
+                struct alternate_object_database *next;
+
+                next = o->alt_odb_list->next;
+                free_alt_odb(o->alt_odb_list);
+                o->alt_odb_list = next;
+        }
+}
+
+void raw_object_store_clear(struct raw_object_store *o)
+{
+        FREE_AND_NULL(o->objectdir);
+        FREE_AND_NULL(o->alternate_db);
+
+        free_alt_odbs(o);
+        o->alt_odb_tail = NULL;
+
+        INIT_LIST_HEAD(&o->packed_git_mru);
+        close_all_packs(o);
+        o->packed_git = NULL;
+}
diff --git a/pack-bitmap.c b/pack-bitmap.c
index 9270983e5f..22cd425788 100644
--- a/pack-bitmap.c
+++ b/pack-bitmap.c
@@ -10,6 +10,8 @@
 #include "pack-revindex.h"
 #include "pack-objects.h"
 #include "packfile.h"
+#include "repository.h"
+#include "object-store.h"
 
 /*
  * An entry on the bitmap index, representing the bitmap for a given
@@ -335,7 +337,7 @@ static int open_pack_bitmap(void)
         assert(!bitmap_git.map && !bitmap_git.loaded);
 
         prepare_packed_git();
-        for (p = packed_git; p; p = p->next) {
+        for (p = get_packed_git(the_repository); p; p = p->next) {
                 if (open_pack_bitmap_1(p) == 0)
                         ret = 0;
         }
diff --git a/pack-check.c b/pack-check.c
index d0591dd5e8..385d964bdd 100644
--- a/pack-check.c
+++ b/pack-check.c
@@ -3,6 +3,7 @@
 #include "pack-revindex.h"
 #include "progress.h"
 #include "packfile.h"
+#include "object-store.h"
 
 struct idx_entry {
         off_t                offset;
diff --git a/pack-revindex.c b/pack-revindex.c
index ff5f62c033..bb521cf7fb 100644
--- a/pack-revindex.c
+++ b/pack-revindex.c
@@ -1,5 +1,6 @@
 #include "cache.h"
 #include "pack-revindex.h"
+#include "object-store.h"
 
 /*
  * Pack index for existing packs give us easy access to the offsets into
diff --git a/packfile.c b/packfile.c
index 69d3afda6c..8e8b743910 100644
--- a/packfile.c
+++ b/packfile.c
@@ -1,6 +1,7 @@
 #include "cache.h"
 #include "list.h"
 #include "pack.h"
+#include "repository.h"
 #include "dir.h"
 #include "mergesort.h"
 #include "packfile.h"
@@ -13,6 +14,7 @@
 #include "tag.h"
 #include "tree-walk.h"
 #include "tree.h"
+#include "object-store.h"
 
 char *odb_pack_name(struct strbuf *buf,
                     const unsigned char *sha1,
@@ -44,8 +46,6 @@ static unsigned int pack_open_fds;
 static unsigned int pack_max_fds;
 static size_t peak_pack_mapped;
 static size_t pack_mapped;
-struct packed_git *packed_git;
-LIST_HEAD(packed_git_mru);
 
 #define SZ_FMT PRIuMAX
 static inline uintmax_t sz_fmt(size_t s) { return s; }
@@ -245,7 +245,7 @@ static int unuse_one_window(struct packed_git *current)
 
         if (current)
                 scan_windows(current, &lru_p, &lru_w, &lru_l);
-        for (p = packed_git; p; p = p->next)
+        for (p = the_repository->objects->packed_git; p; p = p->next)
                 scan_windows(p, &lru_p, &lru_w, &lru_l);
         if (lru_p) {
                 munmap(lru_w->base, lru_w->len);
@@ -311,11 +311,11 @@ static void close_pack(struct packed_git *p)
         close_pack_index(p);
 }
 
-void close_all_packs(void)
+void close_all_packs(struct raw_object_store *o)
 {
         struct packed_git *p;
 
-        for (p = packed_git; p; p = p->next)
+        for (p = o->packed_git; p; p = p->next)
                 if (p->do_not_close)
                         die("BUG: want to close pack marked 'do-not-close'");
                 else
@@ -383,7 +383,7 @@ static int close_one_pack(void)
         struct pack_window *mru_w = NULL;
         int accept_windows_inuse = 1;
 
-        for (p = packed_git; p; p = p->next) {
+        for (p = the_repository->objects->packed_git; p; p = p->next) {
                 if (p->pack_fd == -1)
                         continue;
                 find_lru_pack(p, &lru_p, &mru_w, &accept_windows_inuse);
@@ -685,8 +685,8 @@ void install_packed_git(struct packed_git *pack)
         if (pack->pack_fd != -1)
                 pack_open_fds++;
 
-        pack->next = packed_git;
-        packed_git = pack;
+        pack->next = the_repository->objects->packed_git;
+        the_repository->objects->packed_git = pack;
 }
 
 void (*report_garbage)(unsigned seen_bits, const char *path);
@@ -768,7 +768,8 @@ static void prepare_packed_git_one(char *objdir, int local)
                 base_len = path.len;
                 if (strip_suffix_mem(path.buf, &base_len, ".idx")) {
                         /* Don't reopen a pack we already have. */
-                        for (p = packed_git; p; p = p->next) {
+                        for (p = the_repository->objects->packed_git; p;
+                             p = p->next) {
                                 size_t len;
                                 if (strip_suffix(p->pack_name, ".pack", &len) &&
                                     len == base_len &&
@@ -802,8 +803,6 @@ static void prepare_packed_git_one(char *objdir, int local)
         strbuf_release(&path);
 }
 
-static int approximate_object_count_valid;
-
 /*
  * Give a fast, rough count of the number of objects in the repository. This
  * ignores loose objects completely. If you have a lot of them, then either
@@ -813,19 +812,20 @@ static int approximate_object_count_valid;
  */
 unsigned long approximate_object_count(void)
 {
-        static unsigned long count;
-        if (!approximate_object_count_valid) {
+        if (!the_repository->objects->approximate_object_count_valid) {
+                unsigned long count;
                 struct packed_git *p;
 
                 prepare_packed_git();
                 count = 0;
-                for (p = packed_git; p; p = p->next) {
+                for (p = the_repository->objects->packed_git; p; p = p->next) {
                         if (open_pack_index(p))
                                 continue;
                         count += p->num_objects;
                 }
+                the_repository->objects->approximate_object_count = count;
         }
-        return count;
+        return the_repository->objects->approximate_object_count;
 }
 
 static void *get_next_packed_git(const void *p)
@@ -868,43 +868,53 @@ static int sort_pack(const void *a_, const void *b_)
 
 static void rearrange_packed_git(void)
 {
-        packed_git = llist_mergesort(packed_git, get_next_packed_git,
-                                     set_next_packed_git, sort_pack);
+        the_repository->objects->packed_git = llist_mergesort(
+                the_repository->objects->packed_git, get_next_packed_git,
+                set_next_packed_git, sort_pack);
 }
 
 static void prepare_packed_git_mru(void)
 {
         struct packed_git *p;
 
-        INIT_LIST_HEAD(&packed_git_mru);
+        INIT_LIST_HEAD(&the_repository->objects->packed_git_mru);
 
-        for (p = packed_git; p; p = p->next)
-                list_add_tail(&p->mru, &packed_git_mru);
+        for (p = the_repository->objects->packed_git; p; p = p->next)
+                list_add_tail(&p->mru, &the_repository->objects->packed_git_mru);
 }
 
-static int prepare_packed_git_run_once = 0;
 void prepare_packed_git(void)
 {
         struct alternate_object_database *alt;
 
-        if (prepare_packed_git_run_once)
+        if (the_repository->objects->packed_git_initialized)
                 return;
         prepare_packed_git_one(get_object_directory(), 1);
-        prepare_alt_odb();
-        for (alt = alt_odb_list; alt; alt = alt->next)
+        prepare_alt_odb(the_repository);
+        for (alt = the_repository->objects->alt_odb_list; alt; alt = alt->next)
                 prepare_packed_git_one(alt->path, 0);
         rearrange_packed_git();
         prepare_packed_git_mru();
-        prepare_packed_git_run_once = 1;
+        the_repository->objects->packed_git_initialized = 1;
 }
 
 void reprepare_packed_git(void)
 {
-        approximate_object_count_valid = 0;
-        prepare_packed_git_run_once = 0;
+        the_repository->objects->approximate_object_count_valid = 0;
+        the_repository->objects->packed_git_initialized = 0;
         prepare_packed_git();
 }
 
+struct packed_git *get_packed_git(struct repository *r)
+{
+        return r->objects->packed_git;
+}
+
+struct list_head *get_packed_git_mru(struct repository *r)
+{
+        return &r->objects->packed_git_mru;
+}
+
 unsigned long unpack_object_header_buffer(const unsigned char *buf,
                 unsigned long len, enum object_type *type, unsigned long *sizep)
 {
@@ -1013,7 +1023,7 @@ const struct packed_git *has_packed_and_bad(const unsigned char *sha1)
         struct packed_git *p;
         unsigned i;
 
-        for (p = packed_git; p; p = p->next)
+        for (p = the_repository->objects->packed_git; p; p = p->next)
                 for (i = 0; i < p->num_bad_objects; i++)
                         if (!hashcmp(sha1, p->bad_object_sha1 + 20 * i))
                                 return p;
@@ -1833,13 +1843,14 @@ int find_pack_entry(const unsigned char *sha1, struct pack_entry *e)
         struct list_head *pos;
 
         prepare_packed_git();
-        if (!packed_git)
+        if (!the_repository->objects->packed_git)
                 return 0;
 
-        list_for_each(pos, &packed_git_mru) {
+        list_for_each(pos, &the_repository->objects->packed_git_mru) {
                 struct packed_git *p = list_entry(pos, struct packed_git, mru);
                 if (fill_pack_entry(sha1, e, p)) {
-                        list_move(&p->mru, &packed_git_mru);
+                        list_move(&p->mru,
+                                  &the_repository->objects->packed_git_mru);
                         return 1;
                 }
         }
@@ -1886,7 +1897,7 @@ int for_each_packed_object(each_packed_object_fn cb, void *data, unsigned flags)
         int pack_errors = 0;
 
         prepare_packed_git();
-        for (p = packed_git; p; p = p->next) {
+        for (p = the_repository->objects->packed_git; p; p = p->next) {
                 if ((flags & FOR_EACH_OBJECT_LOCAL_ONLY) && !p->pack_local)
                         continue;
                 if ((flags & FOR_EACH_OBJECT_PROMISOR_ONLY) &&
@@ -1917,7 +1928,7 @@ static int add_promisor_object(const struct object_id *oid,
 
         /*
          * If this is a tree, commit, or tag, the objects it refers
-         * to are also promisor objects. (Blobs refer to no objects.)
+         * to are also promisor objects. (Blobs refer to no objects->)
          */
         if (obj->type == OBJ_TREE) {
                 struct tree *tree = (struct tree *)obj;
diff --git a/packfile.h b/packfile.h
index ec08cb2bb0..a7abd602da 100644
--- a/packfile.h
+++ b/packfile.h
@@ -38,6 +38,9 @@ extern void prepare_packed_git(void);
 extern void reprepare_packed_git(void);
 extern void install_packed_git(struct packed_git *pack);
 
+struct packed_git *get_packed_git(struct repository *r);
+struct list_head *get_packed_git_mru(struct repository *r);
+
 /*
  * Give a rough count of objects in the repository. This sacrifices accuracy
  * for speed.
@@ -63,7 +66,7 @@ extern void close_pack_index(struct packed_git *);
 
 extern unsigned char *use_pack(struct packed_git *, struct pack_window **, off_t, unsigned long *);
 extern void close_pack_windows(struct packed_git *);
-extern void close_all_packs(void);
+extern void close_all_packs(struct raw_object_store *o);
 extern void unuse_pack(struct pack_window **);
 extern void clear_delta_base_cache(void);
 extern struct packed_git *add_packed_git(const char *path, size_t path_len, int local);
diff --git a/path.c b/path.c
index da8b655730..3308b7b958 100644
--- a/path.c
+++ b/path.c
@@ -10,6 +10,7 @@
 #include "submodule-config.h"
 #include "path.h"
 #include "packfile.h"
+#include "object-store.h"
 
 static int get_st_mode_bits(const char *path, int *mode)
 {
@@ -382,7 +383,7 @@ static void adjust_git_path(const struct repository *repo,
                 strbuf_splice(buf, 0, buf->len,
                               repo->index_file, strlen(repo->index_file));
         else if (dir_prefix(base, "objects"))
-                replace_dir(buf, git_dir_len + 7, repo->objectdir);
+                replace_dir(buf, git_dir_len + 7, repo->objects->objectdir);
         else if (git_hooks_path && dir_prefix(base, "hooks"))
                 replace_dir(buf, git_dir_len + 5, git_hooks_path);
         else if (repo->different_commondir)
diff --git a/reachable.c b/reachable.c
index 404e1440e9..a6ea33a5db 100644
--- a/reachable.c
+++ b/reachable.c
@@ -11,6 +11,7 @@
 #include "list-objects.h"
 #include "packfile.h"
 #include "worktree.h"
+#include "object-store.h"
 
 struct connectivity_progress {
         struct progress *progress;
diff --git a/repository.c b/repository.c
index 62f52f47fc..a4848c1bd0 100644
--- a/repository.c
+++ b/repository.c
@@ -1,5 +1,6 @@
 #include "cache.h"
 #include "repository.h"
+#include "object-store.h"
 #include "config.h"
 #include "submodule-config.h"
 
@@ -12,6 +13,7 @@ void initialize_the_repository(void)
         the_repository = &the_repo;
 
         the_repo.index = &the_index;
+        the_repo.objects = raw_object_store_new();
         repo_set_hash_algo(&the_repo, GIT_HASH_SHA1);
 }
 
@@ -58,10 +60,10 @@ void repo_set_gitdir(struct repository *repo,
         free(old_gitdir);
 
         repo_set_commondir(repo, o->commondir);
-        expand_base_dir(&repo->objectdir, o->object_dir,
+        expand_base_dir(&repo->objects->objectdir, o->object_dir,
                         repo->commondir, "objects");
-        free(repo->alternate_db);
-        repo->alternate_db = xstrdup_or_null(o->alternate_db);
+        free(repo->objects->alternate_db);
+        repo->objects->alternate_db = xstrdup_or_null(o->alternate_db);
         expand_base_dir(&repo->graft_file, o->graft_file,
                         repo->commondir, "info/grafts");
         expand_base_dir(&repo->index_file, o->index_file,
@@ -140,6 +142,8 @@ static int repo_init(struct repository *repo,
         struct repository_format format;
         memset(repo, 0, sizeof(*repo));
 
+        repo->objects = raw_object_store_new();
+
         if (repo_init_gitdir(repo, gitdir))
                 goto error;
 
@@ -214,13 +218,14 @@ void repo_clear(struct repository *repo)
 {
         FREE_AND_NULL(repo->gitdir);
         FREE_AND_NULL(repo->commondir);
-        FREE_AND_NULL(repo->objectdir);
-        FREE_AND_NULL(repo->alternate_db);
         FREE_AND_NULL(repo->graft_file);
         FREE_AND_NULL(repo->index_file);
         FREE_AND_NULL(repo->worktree);
         FREE_AND_NULL(repo->submodule_prefix);
 
+        raw_object_store_clear(repo->objects);
+        FREE_AND_NULL(repo->objects);
+
         if (repo->config) {
                 git_configset_clear(repo->config);
                 FREE_AND_NULL(repo->config);
diff --git a/repository.h b/repository.h
index f21fd93f72..09df94a472 100644
--- a/repository.h
+++ b/repository.h
@@ -2,9 +2,10 @@
 #define REPOSITORY_H
 
 struct config_set;
+struct git_hash_algo;
 struct index_state;
+struct raw_object_store;
 struct submodule_cache;
-struct git_hash_algo;
 
 struct repository {
         /* Environment */
@@ -21,13 +22,9 @@ struct repository {
         char *commondir;
 
         /*
-         * Path to the repository's object store.
-         * Cannot be NULL after initialization.
+         * Holds any information related to accessing the raw object content.
          */
-        char *objectdir;
-
-        /* Path to extra alternate object database if not NULL */
-        char *alternate_db;
+        struct raw_object_store *objects;
 
         /*
          * Path to the repository's graft file.
diff --git a/server-info.c b/server-info.c
index 26a6c20b7d..75a8b65e47 100644
--- a/server-info.c
+++ b/server-info.c
@@ -1,9 +1,11 @@
 #include "cache.h"
+#include "repository.h"
 #include "refs.h"
 #include "object.h"
 #include "commit.h"
 #include "tag.h"
 #include "packfile.h"
+#include "object-store.h"
 
 /*
  * Create the file "path" by writing to a temporary file and renaming
@@ -200,7 +202,7 @@ static void init_pack_info(const char *infofile, int force)
         objdirlen = strlen(objdir);
 
         prepare_packed_git();
-        for (p = packed_git; p; p = p->next) {
+        for (p = get_packed_git(the_repository); p; p = p->next) {
                 /* we ignore things on alternate path since they are
                  * not available to the pullers in general.
                  */
@@ -210,7 +212,7 @@ static void init_pack_info(const char *infofile, int force)
         }
         num_pack = i;
         info = xcalloc(num_pack, sizeof(struct pack_info *));
-        for (i = 0, p = packed_git; p; p = p->next) {
+        for (i = 0, p = get_packed_git(the_repository); p; p = p->next) {
                 if (!p->pack_local)
                         continue;
                 info[i] = xcalloc(1, sizeof(struct pack_info));
diff --git a/sha1_file.c b/sha1_file.c
index aea9124a78..aab3b58e03 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -22,6 +22,7 @@
 #include "pack-revindex.h"
 #include "sha1-lookup.h"
 #include "bulk-checkin.h"
+#include "repository.h"
 #include "streaming.h"
 #include "dir.h"
 #include "list.h"
@@ -29,6 +30,7 @@
 #include "quote.h"
 #include "packfile.h"
 #include "fetch-object.h"
+#include "object-store.h"
 
 /* The maximum size for an object header. */
 #define MAX_HEADER_LEN 32
@@ -322,9 +324,9 @@ static void fill_sha1_path(struct strbuf *buf, const unsigned char *sha1)
         }
 }
 
-void sha1_file_name(struct strbuf *buf, const unsigned char *sha1)
+void sha1_file_name(struct repository *r, struct strbuf *buf, const unsigned char *sha1)
 {
-        strbuf_addstr(buf, get_object_directory());
+        strbuf_addstr(buf, r->objects->objectdir);
         strbuf_addch(buf, '/');
         fill_sha1_path(buf, sha1);
 }
@@ -343,13 +345,12 @@ static const char *alt_sha1_path(struct alternate_object_database *alt,
         return buf->buf;
 }
 
-struct alternate_object_database *alt_odb_list;
-static struct alternate_object_database **alt_odb_tail;
-
 /*
  * Return non-zero iff the path is usable as an alternate object database.
  */
-static int alt_odb_usable(struct strbuf *path, const char *normalized_objdir)
+static int alt_odb_usable(struct raw_object_store *o,
+                          struct strbuf *path,
+                          const char *normalized_objdir)
 {
         struct alternate_object_database *alt;
 
@@ -365,7 +366,7 @@ static int alt_odb_usable(struct strbuf *path, const char *normalized_objdir)
          * Prevent the common mistake of listing the same
          * thing twice, or object directory itself.
          */
-        for (alt = alt_odb_list; alt; alt = alt->next) {
+        for (alt = o->alt_odb_list; alt; alt = alt->next) {
                 if (!fspathcmp(path->buf, alt->path))
                         return 0;
         }
@@ -390,9 +391,11 @@ static int alt_odb_usable(struct strbuf *path, const char *normalized_objdir)
  * SHA1, an extra slash for the first level indirection, and the
  * terminating NUL.
  */
-static void read_info_alternates(const char * relative_base, int depth);
-static int link_alt_odb_entry(const char *entry, const char *relative_base,
-        int depth, const char *normalized_objdir)
+static void read_info_alternates(struct repository *r,
+                                 const char *relative_base,
+                                 int depth);
+static int link_alt_odb_entry(struct repository *r, const char *entry,
+        const char *relative_base, int depth, const char *normalized_objdir)
 {
         struct alternate_object_database *ent;
         struct strbuf pathbuf = STRBUF_INIT;
@@ -417,7 +420,7 @@ static int link_alt_odb_entry(const char *entry, const char *relative_base,
         while (pathbuf.len && pathbuf.buf[pathbuf.len - 1] == '/')
                 strbuf_setlen(&pathbuf, pathbuf.len - 1);
 
-        if (!alt_odb_usable(&pathbuf, normalized_objdir)) {
+        if (!alt_odb_usable(r->objects, &pathbuf, normalized_objdir)) {
                 strbuf_release(&pathbuf);
                 return -1;
         }
@@ -425,12 +428,12 @@ static int link_alt_odb_entry(const char *entry, const char *relative_base,
         ent = alloc_alt_odb(pathbuf.buf);
 
         /* add the alternate entry */
-        *alt_odb_tail = ent;
-        alt_odb_tail = &(ent->next);
+        *r->objects->alt_odb_tail = ent;
+        r->objects->alt_odb_tail = &(ent->next);
         ent->next = NULL;
 
         /* recursively add alternates */
-        read_info_alternates(pathbuf.buf, depth + 1);
+        read_info_alternates(r, pathbuf.buf, depth + 1);
 
         strbuf_release(&pathbuf);
         return 0;
@@ -465,8 +468,8 @@ static const char *parse_alt_odb_entry(const char *string,
         return end;
 }
 
-static void link_alt_odb_entries(const char *alt, int sep,
-                                 const char *relative_base, int depth)
+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;
@@ -480,7 +483,7 @@ static void link_alt_odb_entries(const char *alt, int sep,
                 return;
         }
 
-        strbuf_add_absolute_path(&objdirbuf, get_object_directory());
+        strbuf_add_absolute_path(&objdirbuf, r->objects->objectdir);
         if (strbuf_normalize_path(&objdirbuf) < 0)
                 die("unable to normalize object directory: %s",
                     objdirbuf.buf);
@@ -489,13 +492,16 @@ static void link_alt_odb_entries(const char *alt, int sep,
                 alt = parse_alt_odb_entry(alt, sep, &entry);
                 if (!entry.len)
                         continue;
-                link_alt_odb_entry(entry.buf, relative_base, depth, objdirbuf.buf);
+                link_alt_odb_entry(r, entry.buf,
+                                   relative_base, depth, objdirbuf.buf);
         }
         strbuf_release(&entry);
         strbuf_release(&objdirbuf);
 }
 
-static void read_info_alternates(const char * relative_base, int depth)
+static void read_info_alternates(struct repository *r,
+                                 const char *relative_base,
+                                 int depth)
 {
         char *path;
         struct strbuf buf = STRBUF_INIT;
@@ -507,7 +513,7 @@ static void read_info_alternates(const char * relative_base, int depth)
                 return;
         }
 
-        link_alt_odb_entries(buf.buf, '\n', relative_base, depth);
+        link_alt_odb_entries(r, buf.buf, '\n', relative_base, depth);
         strbuf_release(&buf);
         free(path);
 }
@@ -560,8 +566,9 @@ void add_to_alternates_file(const char *reference)
                 fprintf_or_die(out, "%s\n", reference);
                 if (commit_lock_file(&lock))
                         die_errno("unable to move new alternates file into place");
-                if (alt_odb_tail)
-                        link_alt_odb_entries(reference, '\n', NULL, 0);
+                if (the_repository->objects->alt_odb_tail)
+                        link_alt_odb_entries(the_repository, reference,
+                                             '\n', NULL, 0);
         }
         free(alts);
 }
@@ -572,9 +579,10 @@ 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();
+        prepare_alt_odb(the_repository);
 
-        link_alt_odb_entries(reference, '\n', NULL, 0);
+        link_alt_odb_entries(the_repository, reference,
+                             '\n', NULL, 0);
 }
 
 /*
@@ -657,8 +665,8 @@ int foreach_alt_odb(alt_odb_fn fn, void *cb)
         struct alternate_object_database *ent;
         int r = 0;
 
-        prepare_alt_odb();
-        for (ent = alt_odb_list; ent; ent = ent->next) {
+        prepare_alt_odb(the_repository);
+        for (ent = the_repository->objects->alt_odb_list; ent; ent = ent->next) {
                 r = fn(ent, cb);
                 if (r)
                         break;
@@ -666,15 +674,15 @@ int foreach_alt_odb(alt_odb_fn fn, void *cb)
         return r;
 }
 
-void prepare_alt_odb(void)
+void prepare_alt_odb(struct repository *r)
 {
-        if (alt_odb_tail)
+        if (r->objects->alt_odb_tail)
                 return;
 
-        alt_odb_tail = &alt_odb_list;
-        link_alt_odb_entries(the_repository->alternate_db, PATH_SEP, NULL, 0);
+        r->objects->alt_odb_tail = &r->objects->alt_odb_list;
+        link_alt_odb_entries(r, r->objects->alternate_db, PATH_SEP, NULL, 0);
 
-        read_info_alternates(get_object_directory(), 0);
+        read_info_alternates(r, r->objects->objectdir, 0);
 }
 
 /* Returns 1 if we have successfully freshened the file, 0 otherwise. */
@@ -706,7 +714,7 @@ static int check_and_freshen_local(const unsigned char *sha1, int freshen)
         static struct strbuf buf = STRBUF_INIT;
 
         strbuf_reset(&buf);
-        sha1_file_name(&buf, sha1);
+        sha1_file_name(the_repository, &buf, sha1);
 
         return check_and_freshen_file(buf.buf, freshen);
 }
@@ -714,8 +722,8 @@ static int check_and_freshen_local(const unsigned char *sha1, int freshen)
 static int check_and_freshen_nonlocal(const unsigned char *sha1, int freshen)
 {
         struct alternate_object_database *alt;
-        prepare_alt_odb();
-        for (alt = alt_odb_list; alt; alt = alt->next) {
+        prepare_alt_odb(the_repository);
+        for (alt = the_repository->objects->alt_odb_list; alt; alt = alt->next) {
                 const char *path = alt_sha1_path(alt, sha1);
                 if (check_and_freshen_file(path, freshen))
                         return 1;
@@ -860,22 +868,22 @@ int git_open_cloexec(const char *name, int flags)
  * Note that it may point to static storage and is only valid until another
  * call to sha1_file_name(), etc.
  */
-static int stat_sha1_file(const unsigned char *sha1, struct stat *st,
-                          const char **path)
+static int stat_sha1_file(struct repository *r, const unsigned char *sha1,
+                          struct stat *st, const char **path)
 {
         struct alternate_object_database *alt;
         static struct strbuf buf = STRBUF_INIT;
 
         strbuf_reset(&buf);
-        sha1_file_name(&buf, sha1);
+        sha1_file_name(r, &buf, sha1);
         *path = buf.buf;
 
         if (!lstat(*path, st))
                 return 0;
 
-        prepare_alt_odb();
+        prepare_alt_odb(r);
         errno = ENOENT;
-        for (alt = alt_odb_list; alt; alt = alt->next) {
+        for (alt = r->objects->alt_odb_list; alt; alt = alt->next) {
                 *path = alt_sha1_path(alt, sha1);
                 if (!lstat(*path, st))
                         return 0;
@@ -888,7 +896,8 @@ static int stat_sha1_file(const unsigned char *sha1, struct stat *st,
  * Like stat_sha1_file(), but actually open the object and return the
  * descriptor. See the caveats on the "path" parameter above.
  */
-static int open_sha1_file(const unsigned char *sha1, const char **path)
+static int open_sha1_file(struct repository *r,
+                          const unsigned char *sha1, const char **path)
 {
         int fd;
         struct alternate_object_database *alt;
@@ -896,7 +905,7 @@ static int open_sha1_file(const unsigned char *sha1, const char **path)
         static struct strbuf buf = STRBUF_INIT;
 
         strbuf_reset(&buf);
-        sha1_file_name(&buf, sha1);
+        sha1_file_name(r, &buf, sha1);
         *path = buf.buf;
 
         fd = git_open(*path);
@@ -904,8 +913,8 @@ static int open_sha1_file(const unsigned char *sha1, const char **path)
                 return fd;
         most_interesting_errno = errno;
 
-        prepare_alt_odb();
-        for (alt = alt_odb_list; alt; alt = alt->next) {
+        prepare_alt_odb(r);
+        for (alt = r->objects->alt_odb_list; alt; alt = alt->next) {
                 *path = alt_sha1_path(alt, sha1);
                 fd = git_open(*path);
                 if (fd >= 0)
@@ -921,9 +930,8 @@ static int open_sha1_file(const unsigned char *sha1, const char **path)
  * Map the loose object at "path" if it is not NULL, or the path found by
  * searching for a loose object named "sha1".
  */
-static void *map_sha1_file_1(const char *path,
-                             const unsigned char *sha1,
-                             unsigned long *size)
+static void *map_sha1_file_1(struct repository *r, const char *path,
+                             const unsigned char *sha1, unsigned long *size)
 {
         void *map;
         int fd;
@@ -931,7 +939,7 @@ static void *map_sha1_file_1(const char *path,
         if (path)
                 fd = git_open(path);
         else
-                fd = open_sha1_file(sha1, &path);
+                fd = open_sha1_file(r, sha1, &path);
         map = NULL;
         if (fd >= 0) {
                 struct stat st;
@@ -950,9 +958,10 @@ static void *map_sha1_file_1(const char *path,
         return map;
 }
 
-void *map_sha1_file(const unsigned char *sha1, unsigned long *size)
+void *map_sha1_file(struct repository *r,
+                    const unsigned char *sha1, unsigned long *size)
 {
-        return map_sha1_file_1(NULL, sha1, size);
+        return map_sha1_file_1(r, NULL, sha1, size);
 }
 
 static int unpack_sha1_short_header(git_zstream *stream,
@@ -1141,9 +1150,9 @@ int parse_sha1_header(const char *hdr, unsigned long *sizep)
         return parse_sha1_header_extended(hdr, &oi, 0);
 }
 
-static int sha1_loose_object_info(const unsigned char *sha1,
-                                  struct object_info *oi,
-                                  int flags)
+static int sha1_loose_object_info(struct repository *r,
+                                  const unsigned char *sha1,
+                                  struct object_info *oi, int flags)
 {
         int status = 0;
         unsigned long mapsize;
@@ -1167,14 +1176,14 @@ static int sha1_loose_object_info(const unsigned char *sha1,
         if (!oi->typep && !oi->type_name && !oi->sizep && !oi->contentp) {
                 const char *path;
                 struct stat st;
-                if (stat_sha1_file(sha1, &st, &path) < 0)
+                if (stat_sha1_file(r, sha1, &st, &path) < 0)
                         return -1;
                 if (oi->disk_sizep)
                         *oi->disk_sizep = st.st_size;
                 return 0;
         }
 
-        map = map_sha1_file(sha1, &mapsize);
+        map = map_sha1_file(r, sha1, &mapsize);
         if (!map)
                 return -1;
 
@@ -1266,7 +1275,7 @@ int oid_object_info_extended(const struct object_id *oid, struct object_info *oi
                         return -1;
 
                 /* Most likely it's a loose object. */
-                if (!sha1_loose_object_info(real->hash, oi, flags))
+                if (!sha1_loose_object_info(the_repository, real->hash, oi, flags))
                         return 0;
 
                 /* Not a loose object; someone else may have just packed it. */
@@ -1390,7 +1399,7 @@ void *read_object_file_extended(const struct object_id *oid,
                 die("replacement %s not found for %s",
                     oid_to_hex(repl), oid_to_hex(oid));
 
-        if (!stat_sha1_file(repl->hash, &st, &path))
+        if (!stat_sha1_file(the_repository, repl->hash, &st, &path))
                 die("loose object %s (stored in %s) is corrupt",
                     oid_to_hex(repl), path);
 
@@ -1591,7 +1600,7 @@ static int write_loose_object(const struct object_id *oid, char *hdr,
         static struct strbuf filename = STRBUF_INIT;
 
         strbuf_reset(&filename);
-        sha1_file_name(&filename, oid->hash);
+        sha1_file_name(the_repository, &filename, oid->hash);
 
         fd = create_tmpfile(&tmp_file, filename.buf);
         if (fd < 0) {
@@ -2199,7 +2208,7 @@ int read_loose_object(const char *path,
 
         *contents = NULL;
 
-        map = map_sha1_file_1(path, NULL, &mapsize);
+        map = map_sha1_file_1(the_repository, path, NULL, &mapsize);
         if (!map) {
                 error_errno("unable to mmap %s", path);
                 goto out;
diff --git a/sha1_name.c b/sha1_name.c
index 0185c6081a..509a95f0cf 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -10,6 +10,8 @@
 #include "dir.h"
 #include "sha1-array.h"
 #include "packfile.h"
+#include "object-store.h"
+#include "repository.h"
 
 static int get_oid_oneline(const char *, struct object_id *, struct commit_list *);
 
@@ -104,7 +106,7 @@ static void find_short_object_filename(struct disambiguate_state *ds)
                  */
                 fakeent = alloc_alt_odb(get_object_directory());
         }
-        fakeent->next = alt_odb_list;
+        fakeent->next = the_repository->objects->alt_odb_list;
 
         for (alt = fakeent; alt && !ds->ambiguous; alt = alt->next) {
                 int pos;
@@ -178,7 +180,8 @@ static void find_short_packed_object(struct disambiguate_state *ds)
         struct packed_git *p;
 
         prepare_packed_git();
-        for (p = packed_git; p && !ds->ambiguous; p = p->next)
+        for (p = get_packed_git(the_repository); p && !ds->ambiguous;
+             p = p->next)
                 unique_in_pack(p, ds);
 }
 
@@ -334,7 +337,7 @@ static int init_object_disambiguation(const char *name, int len,
 
         ds->len = len;
         ds->hex_pfx[len] = '\0';
-        prepare_alt_odb();
+        prepare_alt_odb(the_repository);
         return 0;
 }
 
@@ -532,7 +535,7 @@ static void find_abbrev_len_packed(struct min_abbrev_data *mad)
         struct packed_git *p;
 
         prepare_packed_git();
-        for (p = packed_git; p; p = p->next)
+        for (p = get_packed_git(the_repository); p; p = p->next)
                 find_abbrev_len_for_pack(p, mad);
 }
 
diff --git a/streaming.c b/streaming.c
index 46fabee3aa..7d55ba64c7 100644
--- a/streaming.c
+++ b/streaming.c
@@ -3,6 +3,8 @@
  */
 #include "cache.h"
 #include "streaming.h"
+#include "repository.h"
+#include "object-store.h"
 #include "packfile.h"
 
 enum input_source {
@@ -335,7 +337,8 @@ static struct stream_vtbl loose_vtbl = {
 
 static open_method_decl(loose)
 {
-        st->u.loose.mapped = map_sha1_file(oid->hash, &st->u.loose.mapsize);
+        st->u.loose.mapped = map_sha1_file(the_repository,
+                                           oid->hash, &st->u.loose.mapsize);
         if (!st->u.loose.mapped)
                 return -1;
         if ((unpack_sha1_header(&st->z,
diff --git a/submodule.c b/submodule.c
index a05c544e8d..9a50168b23 100644
--- a/submodule.c
+++ b/submodule.c
@@ -21,6 +21,7 @@
 #include "remote.h"
 #include "worktree.h"
 #include "parse-options.h"
+#include "object-store.h"
 
 static int config_update_recurse_submodules = RECURSE_SUBMODULES_OFF;
 static struct string_list changed_submodule_names = STRING_LIST_INIT_DUP;
diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c
index 7120634b04..7314b5943e 100644
--- a/t/helper/test-ref-store.c
+++ b/t/helper/test-ref-store.c
@@ -1,6 +1,7 @@
 #include "cache.h"
 #include "refs.h"
 #include "worktree.h"
+#include "object-store.h"
 
 static const char *notnull(const char *arg, const char *name)
 {
diff --git a/tmp-objdir.c b/tmp-objdir.c
index b2d9280f10..fea3f55545 100644
--- a/tmp-objdir.c
+++ b/tmp-objdir.c
@@ -6,6 +6,7 @@
 #include "strbuf.h"
 #include "argv-array.h"
 #include "quote.h"
+#include "object-store.h"
 
 struct tmp_objdir {
         struct strbuf path;
diff --git a/transport.c b/transport.c
index b9dfa11bd2..94eccf29aa 100644
--- a/transport.c
+++ b/transport.c
@@ -18,6 +18,7 @@
 #include "sha1-array.h"
 #include "sigchain.h"
 #include "transport-internal.h"
+#include "object-store.h"
 
 static void set_upstreams(struct transport *transport, struct ref *refs,
         int pretend)