Merge branch 'sb/object-store'
authorJunio C Hamano <gitster@pobox.com>
Wed, 11 Apr 2018 04:09:55 +0000 (13:09 +0900)
committerJunio C Hamano <gitster@pobox.com>
Wed, 11 Apr 2018 04:09:55 +0000 (13:09 +0900)
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
...

39 files changed:
builtin/am.c
builtin/clone.c
builtin/count-objects.c
builtin/fetch.c
builtin/fsck.c
builtin/gc.c
builtin/grep.c
builtin/index-pack.c
builtin/merge.c
builtin/pack-objects.c
builtin/pack-redundant.c
builtin/receive-pack.c
builtin/submodule--helper.c
cache.h
environment.c
fast-import.c
http-backend.c
http-push.c
http-walker.c
http.c
object-store.h [new file with mode: 0644]
object.c
pack-bitmap.c
pack-check.c
pack-revindex.c
packfile.c
packfile.h
path.c
reachable.c
repository.c
repository.h
server-info.c
sha1_file.c
sha1_name.c
streaming.c
submodule.c
t/helper/test-ref-store.c
tmp-objdir.c
transport.c
index 1bcc3606c54f62c02ea6b7e70c895bf21714ae65..9c82603f70ff9605aa25c78023355b94860a7ce0 100644 (file)
@@ -1862,7 +1862,7 @@ static void am_run(struct am_state *state, int resume)
         */
        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);
        }
 }
index 101c27a593f4c64a735410f18bfcb46489728696..7df5932b855e874d45b970f6150d65ed25b06f5f 100644 (file)
@@ -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();
        }
 
index 33343818c830bf64452640b14b2ce7b876221022..b28ff00be23531314722925533d09b84941fba6f 100644 (file)
@@ -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))
index 8295f92b3e63d2675b8238d6bc17e9b1fc81319a..dcdfc66f09af70c4b8e3c08a99c80202be7b4e68 100644 (file)
@@ -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)
index 09225586835eb872ea0152018f1f85dc23f63710..13c0a8048ece6bc21a5326f290432601b9f65486 100644 (file)
@@ -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))
index f51e5a6500fc294cb719716671259de42f31bfe7..cef38e5427773892d8eb7fc797e783f4652eadec 100644 (file)
@@ -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)
index 668cb8050ae68a729cf522011f36d727fff04cfb..5f32d2ce84f27bca725c12aa51d2d91a0c38be8b 100644 (file)
@@ -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) {
index 657a5dda06556baf909134f98c96029c615ae719..d81473e722e7c99b9b05b34506fa4925196ff6d7 100644 (file)
@@ -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>])";
index 8746c5e3e867d79c85728974825ebca4b07a2e9a..9db5a2cf16e189bb3bd0ceec7d34c6651d630225 100644 (file)
@@ -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);
                }
        }
index e7e673266e8e2e6fcbe7723c851c6d216eecb84c..89f49bb5f63673839d9b5220a499e592acd0b18d 100644 (file)
@@ -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;
index 991e1bb76fd66bb189a3523ea5cddf0cd823e343..f060b941b5160a33a3a1ea9c11b09c5c9b3347ac 100644 (file)
@@ -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);
index 2bf7f2d1a3e589f982400fef1aa5bec6e97ccfbd..19428ef97dc0b75fb51adc8b991b675ca0dc38f9 100644 (file)
@@ -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);
index 6ba8587b6d3b7b8b1bc7a96451916c60210b093b..a2327c98b0710fd5c3fb55852c30c72261930cfd 100644 (file)
@@ -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 6e45c1b5377cfca2e0621d529f69daac304e3f12..bbaf5c349ab893a6f0f4549b61bcc70eff50745f 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -940,12 +940,6 @@ extern void check_repository_format(void);
 #define DATA_CHANGED    0x0020
 #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
@@ -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];
index 21565c3c525c64793282d8c3f029733615a87fc2..39b3d906c89048cd094f352fa2ea81d873deb31a 100644 (file)
@@ -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)
index a2e8b1d763a30e1bbec97a92da46c82f0f33353d..b2f6d6d583e7337ae649ecd151c07c95ea75bcad 100644 (file)
@@ -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! */
index f3dc218b2a3d2662efda56fb6c8878a37a4e67a4..64dde78c1b4e9f96bedc2833b1c4e5b8407c6d73 100644 (file)
@@ -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);
        }
index ff82b63133fe4b3de046e15f1066ce6df27404ac..c0998fd763b6178aa7c0d35603c9b56183d5157f 100644 (file)
@@ -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>
index f506f394ac3b2bb6e7cf253f5af8641b0c14664b..7cdfb2f24c76d2f09b39ae2fa97685ecec2d1630 100644 (file)
@@ -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 a5bd5d62c22c054f82b9971fc1f320c643f1d6fb..9304045b6cc4a8a6d5c7d38e7255cf8342958bef 100644 (file)
--- 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 (file)
index 0000000..fef33f3
--- /dev/null
@@ -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 */
index 2c909385a7c4a31e218b9c4e4fb4b1ec5b19de71..a0a756f24f33621bbe83cbe69b18eef6790edacf 100644 (file)
--- 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;
+}
index 9270983e5f581e40f894a8885396e43d13e71015..22cd425788c2a716bf8d8d148c2b0709cae34646 100644 (file)
@@ -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;
        }
index d0591dd5e8f88b8b939c5720dac36a939fd1edf4..385d964bdd1691b962250ec5a49abf2253ca75c1 100644 (file)
@@ -3,6 +3,7 @@
 #include "pack-revindex.h"
 #include "progress.h"
 #include "packfile.h"
+#include "object-store.h"
 
 struct idx_entry {
        off_t                offset;
index ff5f62c03326a7f01926c72a19be5029ae4c1a8b..bb521cf7fb2911bc2d3653f46224880f8540f9ab 100644 (file)
@@ -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
index 69d3afda6c5b3fd15cab7a32eb50028bba0b6c67..8e8b743910d6b2aa8cdc4d229d4256eff0de60a2 100644 (file)
@@ -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;
index ec08cb2bb039ef005b90e09bcf35e90c5cbfb54b..a7abd602da44c196f7b6ba84de5babcf1577ad53 100644 (file)
@@ -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 da8b655730d363dda5010bdf2d53bd76abb82931..3308b7b95828821fdda6806d9d19228cbf8e61ed 100644 (file)
--- 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)
index 404e1440e96b23abb3e4919fdda110e89fff7626..a6ea33a5db8b616420572cda4b857ac6d7d43cb1 100644 (file)
@@ -11,6 +11,7 @@
 #include "list-objects.h"
 #include "packfile.h"
 #include "worktree.h"
+#include "object-store.h"
 
 struct connectivity_progress {
        struct progress *progress;
index 62f52f47fcaed32c4f14a9f76eb1e66e13d4046a..a4848c1bd05e94efbf7aadf155c2cce504523c83 100644 (file)
@@ -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);
index f21fd93f722714617f0b6f2419c25d34a90311de..09df94a4722dacc40ab106e3b3ca348167daa764 100644 (file)
@@ -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.
index 26a6c20b7d420f679d7cceaeba4acdb8ae8c00e7..75a8b65e4746e9efaae2fd4e569e2558468ef9a6 100644 (file)
@@ -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));
index aea9124a78fce21eb4cb756af29823493274e581..aab3b58e0330531efa8a442eafb18840b1f212f3 100644 (file)
@@ -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;
index 0185c6081a16d25b2ffbc220cc028ca2bfc22d32..509a95f0cfdcac749afd5d21469c9338025fedd7 100644 (file)
@@ -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);
 }
 
index 46fabee3aa43840fbe93dfd0e12eff85d5e81cb2..7d55ba64c7551de0f3be1dfcf56cd3344ebd8f59 100644 (file)
@@ -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,
index a05c544e8dad2600ba196e43fd58b953c6ba3d1b..9a50168b2375d9cac306a22c8be4559dde114d95 100644 (file)
@@ -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;
index 7120634b04733bb8abe1f0622f0e1e9c8280b643..7314b5943effac1fea8d39ee365a4b56fec723cb 100644 (file)
@@ -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)
 {
index b2d9280f104aec7095dd2b37ff1f7165355b5388..fea3f55545cbf193f823db468c7640bfd48d9bbd 100644 (file)
@@ -6,6 +6,7 @@
 #include "strbuf.h"
 #include "argv-array.h"
 #include "quote.h"
+#include "object-store.h"
 
 struct tmp_objdir {
        struct strbuf path;
index b9dfa11bd2a1f849f2c2d33aa4943a1ea9cb2d8b..94eccf29aa3f9758f5acaa9daddedcd559ad3915 100644 (file)
@@ -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)