diff options
author | Junio C Hamano <gitster@pobox.com> | 2018-05-08 15:59:21 +0900 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2018-05-08 15:59:21 +0900 |
commit | 174774cd519846616edc475fcbc98237409ffc21 (patch) | |
tree | 604a92001e30c35c702e341c2aa835e41ce3a113 | |
parent | Merge branch 'ds/commit-graph' (diff) | |
parent | replace-object: allow lookup_replace_object to handle arbitrary repositories (diff) | |
download | tgif-174774cd519846616edc475fcbc98237409ffc21.tar.xz |
Merge branch 'sb/object-store-replace'
The effort to pass the repository in-core structure throughout the
API continues. This round deals with the code that implements the
refs/replace/ mechanism.
* sb/object-store-replace:
replace-object: allow lookup_replace_object to handle arbitrary repositories
replace-object: allow do_lookup_replace_object to handle arbitrary repositories
replace-object: allow prepare_replace_object to handle arbitrary repositories
refs: allow for_each_replace_ref to handle arbitrary repositories
refs: store the main ref store inside the repository struct
replace-object: add repository argument to lookup_replace_object
replace-object: add repository argument to do_lookup_replace_object
replace-object: add repository argument to prepare_replace_object
refs: add repository argument to for_each_replace_ref
refs: add repository argument to get_main_ref_store
replace-object: check_replace_refs is safe in multi repo environment
replace-object: eliminate replace objects prepared flag
object-store: move lookup_replace_object to replace-object.h
replace-object: move replace_map to object store
replace_object: use oidmap
-rw-r--r-- | builtin/mktag.c | 3 | ||||
-rw-r--r-- | builtin/pack-refs.c | 3 | ||||
-rw-r--r-- | builtin/replace.c | 4 | ||||
-rw-r--r-- | cache.h | 19 | ||||
-rw-r--r-- | environment.c | 2 | ||||
-rw-r--r-- | object-store.h | 8 | ||||
-rw-r--r-- | object.c | 3 | ||||
-rw-r--r-- | refs.c | 80 | ||||
-rw-r--r-- | refs.h | 4 | ||||
-rw-r--r-- | refs/files-backend.c | 4 | ||||
-rw-r--r-- | replace-object.c | 97 | ||||
-rw-r--r-- | replace-object.h | 36 | ||||
-rw-r--r-- | repository.h | 3 | ||||
-rw-r--r-- | revision.c | 5 | ||||
-rw-r--r-- | sha1-file.c | 7 | ||||
-rw-r--r-- | streaming.c | 3 | ||||
-rw-r--r-- | t/helper/test-ref-store.c | 3 |
17 files changed, 134 insertions, 150 deletions
diff --git a/builtin/mktag.c b/builtin/mktag.c index 9f5a50a8fd..82a6e86077 100644 --- a/builtin/mktag.c +++ b/builtin/mktag.c @@ -1,5 +1,6 @@ #include "builtin.h" #include "tag.h" +#include "replace-object.h" /* * A signature file has a very simple fixed format: four lines @@ -24,7 +25,7 @@ static int verify_object(const struct object_id *oid, const char *expected_type) enum object_type type; unsigned long size; void *buffer = read_object_file(oid, &type, &size); - const struct object_id *repl = lookup_replace_object(oid); + const struct object_id *repl = lookup_replace_object(the_repository, oid); if (buffer) { if (type == type_from_string(expected_type)) diff --git a/builtin/pack-refs.c b/builtin/pack-refs.c index b106a392a4..f3353564f9 100644 --- a/builtin/pack-refs.c +++ b/builtin/pack-refs.c @@ -1,6 +1,7 @@ #include "builtin.h" #include "parse-options.h" #include "refs.h" +#include "repository.h" static char const * const pack_refs_usage[] = { N_("git pack-refs [<options>]"), @@ -17,5 +18,5 @@ int cmd_pack_refs(int argc, const char **argv, const char *prefix) }; if (parse_options(argc, argv, prefix, opts, pack_refs_usage, 0)) usage_with_options(pack_refs_usage, opts); - return refs_pack_refs(get_main_ref_store(), flags); + return refs_pack_refs(get_main_ref_store(the_repository), flags); } diff --git a/builtin/replace.c b/builtin/replace.c index 935647be6b..237ea656cf 100644 --- a/builtin/replace.c +++ b/builtin/replace.c @@ -14,6 +14,8 @@ #include "refs.h" #include "parse-options.h" #include "run-command.h" +#include "object-store.h" +#include "repository.h" #include "tag.h" static const char * const git_replace_usage[] = { @@ -83,7 +85,7 @@ static int list_replace_refs(const char *pattern, const char *format) "valid formats are 'short', 'medium' and 'long'\n", format); - for_each_replace_ref(show_reference, (void *)&data); + for_each_replace_ref(the_repository, show_reference, (void *)&data); return 0; } @@ -1193,25 +1193,6 @@ static inline void *read_object_file(const struct object_id *oid, enum object_ty return read_object_file_extended(oid, type, size, 1); } -/* - * This internal function is only declared here for the benefit of - * lookup_replace_object(). Please do not call it directly. - */ -extern const struct object_id *do_lookup_replace_object(const struct object_id *oid); - -/* - * If object sha1 should be replaced, return the replacement object's - * name (replaced recursively, if necessary). The return value is - * either sha1 or a pointer to a permanently-allocated value. When - * object replacement is suppressed, always return sha1. - */ -static inline const struct object_id *lookup_replace_object(const struct object_id *oid) -{ - if (!check_replace_refs) - return oid; - return do_lookup_replace_object(oid); -} - /* Read and unpack an object file into memory, write memory to an object file */ extern int oid_object_info(const struct object_id *, unsigned long *); diff --git a/environment.c b/environment.c index 80542e2b4f..f4dd45eb3d 100644 --- a/environment.c +++ b/environment.c @@ -51,7 +51,7 @@ const char *editor_program; const char *askpass_program; const char *excludes_file; enum auto_crlf auto_crlf = AUTO_CRLF_FALSE; -int check_replace_refs = 1; +int check_replace_refs = 1; /* NEEDSWORK: rename to read_replace_refs */ char *git_replace_ref_base; enum eol core_eol = EOL_UNSET; int global_conv_flags_eol = CONV_EOL_RNDTRP_WARN; diff --git a/object-store.h b/object-store.h index fef33f345f..1ff862c7f9 100644 --- a/object-store.h +++ b/object-store.h @@ -1,6 +1,8 @@ #ifndef OBJECT_STORE_H #define OBJECT_STORE_H +#include "oidmap.h" + struct alternate_object_database { struct alternate_object_database *next; @@ -94,6 +96,12 @@ struct raw_object_store { struct alternate_object_database **alt_odb_tail; /* + * Objects that should be substituted by other objects + * (see git-replace(1)). + */ + struct oidmap *replace_map; + + /* * private data * * should only be accessed directly by packfile.c @@ -1,5 +1,6 @@ #include "cache.h" #include "object.h" +#include "replace-object.h" #include "blob.h" #include "tree.h" #include "commit.h" @@ -246,7 +247,7 @@ struct object *parse_object(const struct object_id *oid) unsigned long size; enum object_type type; int eaten; - const struct object_id *repl = lookup_replace_object(oid); + const struct object_id *repl = lookup_replace_object(the_repository, oid); void *buffer; struct object *obj; @@ -14,6 +14,7 @@ #include "submodule.h" #include "worktree.h" #include "argv-array.h" +#include "repository.h" /* * List of all available backends @@ -207,7 +208,7 @@ char *refs_resolve_refdup(struct ref_store *refs, char *resolve_refdup(const char *refname, int resolve_flags, struct object_id *oid, int *flags) { - return refs_resolve_refdup(get_main_ref_store(), + return refs_resolve_refdup(get_main_ref_store(the_repository), refname, resolve_flags, oid, flags); } @@ -229,7 +230,7 @@ int refs_read_ref_full(struct ref_store *refs, const char *refname, int read_ref_full(const char *refname, int resolve_flags, struct object_id *oid, int *flags) { - return refs_read_ref_full(get_main_ref_store(), refname, + return refs_read_ref_full(get_main_ref_store(the_repository), refname, resolve_flags, oid, flags); } @@ -376,7 +377,7 @@ int refs_for_each_tag_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data) int for_each_tag_ref(each_ref_fn fn, void *cb_data) { - return refs_for_each_tag_ref(get_main_ref_store(), fn, cb_data); + return refs_for_each_tag_ref(get_main_ref_store(the_repository), fn, cb_data); } int refs_for_each_branch_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data) @@ -386,7 +387,7 @@ int refs_for_each_branch_ref(struct ref_store *refs, each_ref_fn fn, void *cb_da int for_each_branch_ref(each_ref_fn fn, void *cb_data) { - return refs_for_each_branch_ref(get_main_ref_store(), fn, cb_data); + return refs_for_each_branch_ref(get_main_ref_store(the_repository), fn, cb_data); } int refs_for_each_remote_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data) @@ -396,7 +397,7 @@ int refs_for_each_remote_ref(struct ref_store *refs, each_ref_fn fn, void *cb_da int for_each_remote_ref(each_ref_fn fn, void *cb_data) { - return refs_for_each_remote_ref(get_main_ref_store(), fn, cb_data); + return refs_for_each_remote_ref(get_main_ref_store(the_repository), fn, cb_data); } int head_ref_namespaced(each_ref_fn fn, void *cb_data) @@ -744,7 +745,7 @@ int refs_delete_ref(struct ref_store *refs, const char *msg, struct strbuf err = STRBUF_INIT; if (ref_type(refname) == REF_TYPE_PSEUDOREF) { - assert(refs == get_main_ref_store()); + assert(refs == get_main_ref_store(the_repository)); return delete_pseudoref(refname, old_oid); } @@ -766,7 +767,7 @@ int refs_delete_ref(struct ref_store *refs, const char *msg, int delete_ref(const char *msg, const char *refname, const struct object_id *old_oid, unsigned int flags) { - return refs_delete_ref(get_main_ref_store(), msg, refname, + return refs_delete_ref(get_main_ref_store(the_repository), msg, refname, old_oid, flags); } @@ -942,7 +943,7 @@ struct ref_transaction *ref_store_transaction_begin(struct ref_store *refs, struct ref_transaction *ref_transaction_begin(struct strbuf *err) { - return ref_store_transaction_begin(get_main_ref_store(), err); + return ref_store_transaction_begin(get_main_ref_store(the_repository), err); } void ref_transaction_free(struct ref_transaction *transaction) @@ -1074,7 +1075,7 @@ int refs_update_ref(struct ref_store *refs, const char *msg, int ret = 0; if (ref_type(refname) == REF_TYPE_PSEUDOREF) { - assert(refs == get_main_ref_store()); + assert(refs == get_main_ref_store(the_repository)); ret = write_pseudoref(refname, new_oid, old_oid, &err); } else { t = ref_store_transaction_begin(refs, &err); @@ -1113,7 +1114,7 @@ int update_ref(const char *msg, const char *refname, const struct object_id *old_oid, unsigned int flags, enum action_on_err onerr) { - return refs_update_ref(get_main_ref_store(), msg, refname, new_oid, + return refs_update_ref(get_main_ref_store(the_repository), msg, refname, new_oid, old_oid, flags, onerr); } @@ -1334,7 +1335,7 @@ int refs_head_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data) int head_ref(each_ref_fn fn, void *cb_data) { - return refs_head_ref(get_main_ref_store(), fn, cb_data); + return refs_head_ref(get_main_ref_store(the_repository), fn, cb_data); } struct ref_iterator *refs_ref_iterator_begin( @@ -1393,7 +1394,7 @@ int refs_for_each_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data) int for_each_ref(each_ref_fn fn, void *cb_data) { - return refs_for_each_ref(get_main_ref_store(), fn, cb_data); + return refs_for_each_ref(get_main_ref_store(the_repository), fn, cb_data); } int refs_for_each_ref_in(struct ref_store *refs, const char *prefix, @@ -1404,7 +1405,7 @@ int refs_for_each_ref_in(struct ref_store *refs, const char *prefix, int for_each_ref_in(const char *prefix, each_ref_fn fn, void *cb_data) { - return refs_for_each_ref_in(get_main_ref_store(), prefix, fn, cb_data); + return refs_for_each_ref_in(get_main_ref_store(the_repository), prefix, fn, cb_data); } int for_each_fullref_in(const char *prefix, each_ref_fn fn, void *cb_data, unsigned int broken) @@ -1413,7 +1414,7 @@ int for_each_fullref_in(const char *prefix, each_ref_fn fn, void *cb_data, unsig if (broken) flag = DO_FOR_EACH_INCLUDE_BROKEN; - return do_for_each_ref(get_main_ref_store(), + return do_for_each_ref(get_main_ref_store(the_repository), prefix, fn, 0, flag, cb_data); } @@ -1428,9 +1429,9 @@ int refs_for_each_fullref_in(struct ref_store *refs, const char *prefix, return do_for_each_ref(refs, prefix, fn, 0, flag, cb_data); } -int for_each_replace_ref(each_ref_fn fn, void *cb_data) +int for_each_replace_ref(struct repository *r, each_ref_fn fn, void *cb_data) { - return do_for_each_ref(get_main_ref_store(), + return do_for_each_ref(get_main_ref_store(r), git_replace_ref_base, fn, strlen(git_replace_ref_base), DO_FOR_EACH_INCLUDE_BROKEN, cb_data); @@ -1441,7 +1442,7 @@ int for_each_namespaced_ref(each_ref_fn fn, void *cb_data) struct strbuf buf = STRBUF_INIT; int ret; strbuf_addf(&buf, "%srefs/", get_git_namespace()); - ret = do_for_each_ref(get_main_ref_store(), + ret = do_for_each_ref(get_main_ref_store(the_repository), buf.buf, fn, 0, 0, cb_data); strbuf_release(&buf); return ret; @@ -1455,7 +1456,7 @@ int refs_for_each_rawref(struct ref_store *refs, each_ref_fn fn, void *cb_data) int for_each_rawref(each_ref_fn fn, void *cb_data) { - return refs_for_each_rawref(get_main_ref_store(), fn, cb_data); + return refs_for_each_rawref(get_main_ref_store(the_repository), fn, cb_data); } int refs_read_raw_ref(struct ref_store *ref_store, @@ -1561,7 +1562,7 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs, /* backend functions */ int refs_init_db(struct strbuf *err) { - struct ref_store *refs = get_main_ref_store(); + struct ref_store *refs = get_main_ref_store(the_repository); return refs->be->init_db(refs, err); } @@ -1569,7 +1570,7 @@ int refs_init_db(struct strbuf *err) const char *resolve_ref_unsafe(const char *refname, int resolve_flags, struct object_id *oid, int *flags) { - return refs_resolve_ref_unsafe(get_main_ref_store(), refname, + return refs_resolve_ref_unsafe(get_main_ref_store(the_repository), refname, resolve_flags, oid, flags); } @@ -1621,9 +1622,6 @@ static struct ref_store_hash_entry *alloc_ref_store_hash_entry( return entry; } -/* A pointer to the ref_store for the main repository: */ -static struct ref_store *main_ref_store; - /* A hashmap of ref_stores, stored by submodule name: */ static struct hashmap submodule_ref_stores; @@ -1665,13 +1663,13 @@ static struct ref_store *ref_store_init(const char *gitdir, return refs; } -struct ref_store *get_main_ref_store(void) +struct ref_store *get_main_ref_store(struct repository *r) { - if (main_ref_store) - return main_ref_store; + if (r->refs) + return r->refs; - main_ref_store = ref_store_init(get_git_dir(), REF_STORE_ALL_CAPS); - return main_ref_store; + r->refs = ref_store_init(r->gitdir, REF_STORE_ALL_CAPS); + return r->refs; } /* @@ -1740,7 +1738,7 @@ struct ref_store *get_worktree_ref_store(const struct worktree *wt) const char *id; if (wt->is_current) - return get_main_ref_store(); + return get_main_ref_store(the_repository); id = wt->id ? wt->id : "/"; refs = lookup_ref_store_map(&worktree_ref_stores, id); @@ -1796,7 +1794,7 @@ int refs_peel_ref(struct ref_store *refs, const char *refname, int peel_ref(const char *refname, struct object_id *oid) { - return refs_peel_ref(get_main_ref_store(), refname, oid); + return refs_peel_ref(get_main_ref_store(the_repository), refname, oid); } int refs_create_symref(struct ref_store *refs, @@ -1812,7 +1810,7 @@ int refs_create_symref(struct ref_store *refs, int create_symref(const char *ref_target, const char *refs_heads_master, const char *logmsg) { - return refs_create_symref(get_main_ref_store(), ref_target, + return refs_create_symref(get_main_ref_store(the_repository), ref_target, refs_heads_master, logmsg); } @@ -2020,7 +2018,7 @@ int refs_for_each_reflog(struct ref_store *refs, each_ref_fn fn, void *cb_data) int for_each_reflog(each_ref_fn fn, void *cb_data) { - return refs_for_each_reflog(get_main_ref_store(), fn, cb_data); + return refs_for_each_reflog(get_main_ref_store(the_repository), fn, cb_data); } int refs_for_each_reflog_ent_reverse(struct ref_store *refs, @@ -2035,7 +2033,7 @@ int refs_for_each_reflog_ent_reverse(struct ref_store *refs, int for_each_reflog_ent_reverse(const char *refname, each_reflog_ent_fn fn, void *cb_data) { - return refs_for_each_reflog_ent_reverse(get_main_ref_store(), + return refs_for_each_reflog_ent_reverse(get_main_ref_store(the_repository), refname, fn, cb_data); } @@ -2048,7 +2046,7 @@ int refs_for_each_reflog_ent(struct ref_store *refs, const char *refname, int for_each_reflog_ent(const char *refname, each_reflog_ent_fn fn, void *cb_data) { - return refs_for_each_reflog_ent(get_main_ref_store(), refname, + return refs_for_each_reflog_ent(get_main_ref_store(the_repository), refname, fn, cb_data); } @@ -2059,7 +2057,7 @@ int refs_reflog_exists(struct ref_store *refs, const char *refname) int reflog_exists(const char *refname) { - return refs_reflog_exists(get_main_ref_store(), refname); + return refs_reflog_exists(get_main_ref_store(the_repository), refname); } int refs_create_reflog(struct ref_store *refs, const char *refname, @@ -2071,7 +2069,7 @@ int refs_create_reflog(struct ref_store *refs, const char *refname, int safe_create_reflog(const char *refname, int force_create, struct strbuf *err) { - return refs_create_reflog(get_main_ref_store(), refname, + return refs_create_reflog(get_main_ref_store(the_repository), refname, force_create, err); } @@ -2082,7 +2080,7 @@ int refs_delete_reflog(struct ref_store *refs, const char *refname) int delete_reflog(const char *refname) { - return refs_delete_reflog(get_main_ref_store(), refname); + return refs_delete_reflog(get_main_ref_store(the_repository), refname); } int refs_reflog_expire(struct ref_store *refs, @@ -2105,7 +2103,7 @@ int reflog_expire(const char *refname, const struct object_id *oid, reflog_expiry_cleanup_fn cleanup_fn, void *policy_cb_data) { - return refs_reflog_expire(get_main_ref_store(), + return refs_reflog_expire(get_main_ref_store(the_repository), refname, oid, flags, prepare_fn, should_prune_fn, cleanup_fn, policy_cb_data); @@ -2128,7 +2126,7 @@ int refs_delete_refs(struct ref_store *refs, const char *msg, int delete_refs(const char *msg, struct string_list *refnames, unsigned int flags) { - return refs_delete_refs(get_main_ref_store(), msg, refnames, flags); + return refs_delete_refs(get_main_ref_store(the_repository), msg, refnames, flags); } int refs_rename_ref(struct ref_store *refs, const char *oldref, @@ -2139,7 +2137,7 @@ int refs_rename_ref(struct ref_store *refs, const char *oldref, int rename_ref(const char *oldref, const char *newref, const char *logmsg) { - return refs_rename_ref(get_main_ref_store(), oldref, newref, logmsg); + return refs_rename_ref(get_main_ref_store(the_repository), oldref, newref, logmsg); } int refs_copy_existing_ref(struct ref_store *refs, const char *oldref, @@ -2150,5 +2148,5 @@ int refs_copy_existing_ref(struct ref_store *refs, const char *oldref, int copy_existing_ref(const char *oldref, const char *newref, const char *logmsg) { - return refs_copy_existing_ref(get_main_ref_store(), oldref, newref, logmsg); + return refs_copy_existing_ref(get_main_ref_store(the_repository), oldref, newref, logmsg); } @@ -307,7 +307,7 @@ int for_each_fullref_in(const char *prefix, each_ref_fn fn, void *cb_data, int for_each_tag_ref(each_ref_fn fn, void *cb_data); int for_each_branch_ref(each_ref_fn fn, void *cb_data); int for_each_remote_ref(each_ref_fn fn, void *cb_data); -int for_each_replace_ref(each_ref_fn fn, void *cb_data); +int for_each_replace_ref(struct repository *r, each_ref_fn fn, void *cb_data); int for_each_glob_ref(each_ref_fn fn, const char *pattern, void *cb_data); int for_each_glob_ref_in(each_ref_fn fn, const char *pattern, const char *prefix, void *cb_data); @@ -765,7 +765,7 @@ int reflog_expire(const char *refname, const struct object_id *oid, int ref_storage_backend_exists(const char *name); -struct ref_store *get_main_ref_store(void); +struct ref_store *get_main_ref_store(struct repository *r); /* * Return the ref_store instance for the specified submodule. For the * main repository, use submodule==NULL; such a call cannot fail. For diff --git a/refs/files-backend.c b/refs/files-backend.c index a92a2aa821..49d8f67bf1 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -62,10 +62,6 @@ struct ref_lock { struct object_id old_oid; }; -/* - * Future: need to be in "struct repository" - * when doing a full libification. - */ struct files_ref_store { struct ref_store base; unsigned int store_flags; diff --git a/replace-object.c b/replace-object.c index 336357394d..246b98cd4f 100644 --- a/replace-object.c +++ b/replace-object.c @@ -1,55 +1,11 @@ #include "cache.h" -#include "sha1-lookup.h" +#include "oidmap.h" +#include "object-store.h" +#include "replace-object.h" #include "refs.h" +#include "repository.h" #include "commit.h" -/* - * An array of replacements. The array is kept sorted by the original - * sha1. - */ -static struct replace_object { - struct object_id original; - struct object_id replacement; -} **replace_object; - -static int replace_object_alloc, replace_object_nr; - -static const unsigned char *replace_sha1_access(size_t index, void *table) -{ - struct replace_object **replace = table; - return replace[index]->original.hash; -} - -static int replace_object_pos(const unsigned char *sha1) -{ - return sha1_pos(sha1, replace_object, replace_object_nr, - replace_sha1_access); -} - -static int register_replace_object(struct replace_object *replace, - int ignore_dups) -{ - int pos = replace_object_pos(replace->original.hash); - - if (0 <= pos) { - if (ignore_dups) - free(replace); - else { - free(replace_object[pos]); - replace_object[pos] = replace; - } - return 1; - } - pos = -pos - 1; - ALLOC_GROW(replace_object, replace_object_nr + 1, replace_object_alloc); - replace_object_nr++; - if (pos < replace_object_nr) - MOVE_ARRAY(replace_object + pos + 1, replace_object + pos, - replace_object_nr - pos - 1); - replace_object[pos] = replace; - return 0; -} - static int register_replace_ref(const char *refname, const struct object_id *oid, int flag, void *cb_data) @@ -59,7 +15,7 @@ static int register_replace_ref(const char *refname, const char *hash = slash ? slash + 1 : refname; struct replace_object *repl_obj = xmalloc(sizeof(*repl_obj)); - if (get_oid_hex(hash, &repl_obj->original)) { + if (get_oid_hex(hash, &repl_obj->original.oid)) { free(repl_obj); warning("bad replace ref name: %s", refname); return 0; @@ -69,23 +25,22 @@ static int register_replace_ref(const char *refname, oidcpy(&repl_obj->replacement, oid); /* Register new object */ - if (register_replace_object(repl_obj, 1)) + if (oidmap_put(the_repository->objects->replace_map, repl_obj)) die("duplicate replace ref: %s", refname); return 0; } -static void prepare_replace_object(void) +static void prepare_replace_object(struct repository *r) { - static int replace_object_prepared; - - if (replace_object_prepared) + if (r->objects->replace_map) return; - for_each_replace_ref(register_replace_ref, NULL); - replace_object_prepared = 1; - if (!replace_object_nr) - check_replace_refs = 0; + r->objects->replace_map = + xmalloc(sizeof(*the_repository->objects->replace_map)); + oidmap_init(r->objects->replace_map, 0); + + for_each_replace_ref(r, register_replace_ref, NULL); } /* We allow "recursive" replacement. Only within reason, though */ @@ -98,23 +53,21 @@ static void prepare_replace_object(void) * permanently-allocated value. This function always respects replace * references, regardless of the value of check_replace_refs. */ -const struct object_id *do_lookup_replace_object(const struct object_id *oid) +const struct object_id *do_lookup_replace_object(struct repository *r, + const struct object_id *oid) { - int pos, depth = MAXREPLACEDEPTH; + int depth = MAXREPLACEDEPTH; const struct object_id *cur = oid; - prepare_replace_object(); + prepare_replace_object(r); /* Try to recursively replace the object */ - do { - if (--depth < 0) - die("replace depth too high for object %s", - oid_to_hex(oid)); - - pos = replace_object_pos(cur->hash); - if (0 <= pos) - cur = &replace_object[pos]->replacement; - } while (0 <= pos); - - return cur; + while (depth-- > 0) { + struct replace_object *repl_obj = + oidmap_get(r->objects->replace_map, cur); + if (!repl_obj) + return cur; + cur = &repl_obj->replacement; + } + die("replace depth too high for object %s", oid_to_hex(oid)); } diff --git a/replace-object.h b/replace-object.h new file mode 100644 index 0000000000..f996de3d62 --- /dev/null +++ b/replace-object.h @@ -0,0 +1,36 @@ +#ifndef REPLACE_OBJECT_H +#define REPLACE_OBJECT_H + +#include "oidmap.h" +#include "repository.h" +#include "object-store.h" + +struct replace_object { + struct oidmap_entry original; + struct object_id replacement; +}; + +/* + * This internal function is only declared here for the benefit of + * lookup_replace_object(). Please do not call it directly. + */ +extern const struct object_id *do_lookup_replace_object(struct repository *r, + const struct object_id *oid); + +/* + * If object sha1 should be replaced, return the replacement object's + * name (replaced recursively, if necessary). The return value is + * either sha1 or a pointer to a permanently-allocated value. When + * object replacement is suppressed, always return sha1. + */ +static inline const struct object_id *lookup_replace_object(struct repository *r, + const struct object_id *oid) +{ + if (!check_replace_refs || + (r->objects->replace_map && + r->objects->replace_map->map.tablesize == 0)) + return oid; + return do_lookup_replace_object(r, oid); +} + +#endif /* REPLACE_OBJECT_H */ diff --git a/repository.h b/repository.h index 6041367f08..f2646f0c52 100644 --- a/repository.h +++ b/repository.h @@ -26,6 +26,9 @@ struct repository { */ struct raw_object_store *objects; + /* The store in which the refs are held. */ + struct ref_store *refs; + /* * Path to the repository's graft file. * Cannot be NULL after initialization. diff --git a/revision.c b/revision.c index b42c836d7a..1cff11833e 100644 --- a/revision.c +++ b/revision.c @@ -6,6 +6,7 @@ #include "diff.h" #include "refs.h" #include "revision.h" +#include "repository.h" #include "graph.h" #include "grep.h" #include "reflog-walk.h" @@ -1285,7 +1286,7 @@ void add_reflogs_to_pending(struct rev_info *revs, unsigned flags) cb.all_revs = revs; cb.all_flags = flags; - cb.refs = get_main_ref_store(); + cb.refs = get_main_ref_store(the_repository); for_each_reflog(handle_one_reflog, &cb); if (!revs->single_worktree) @@ -2176,7 +2177,7 @@ static int handle_revision_pseudo_opt(const char *submodule, die("BUG: --single-worktree cannot be used together with submodule"); refs = get_submodule_ref_store(submodule); } else - refs = get_main_ref_store(); + refs = get_main_ref_store(the_repository); /* * NOTE! diff --git a/sha1-file.c b/sha1-file.c index 77ccaab928..64a5bd7d87 100644 --- a/sha1-file.c +++ b/sha1-file.c @@ -23,6 +23,7 @@ #include "sha1-lookup.h" #include "bulk-checkin.h" #include "repository.h" +#include "replace-object.h" #include "streaming.h" #include "dir.h" #include "list.h" @@ -1239,7 +1240,7 @@ int oid_object_info_extended(const struct object_id *oid, struct object_info *oi int already_retried = 0; if (flags & OBJECT_INFO_LOOKUP_REPLACE) - real = lookup_replace_object(oid); + real = lookup_replace_object(the_repository, oid); if (is_null_oid(real)) return -1; @@ -1383,8 +1384,8 @@ void *read_object_file_extended(const struct object_id *oid, const struct packed_git *p; const char *path; struct stat st; - const struct object_id *repl = lookup_replace ? lookup_replace_object(oid) - : oid; + const struct object_id *repl = lookup_replace ? + lookup_replace_object(the_repository, oid) : oid; errno = 0; data = read_object(repl->hash, type, size); diff --git a/streaming.c b/streaming.c index 7d55ba64c7..cce7b17ea7 100644 --- a/streaming.c +++ b/streaming.c @@ -5,6 +5,7 @@ #include "streaming.h" #include "repository.h" #include "object-store.h" +#include "replace-object.h" #include "packfile.h" enum input_source { @@ -139,7 +140,7 @@ struct git_istream *open_istream(const struct object_id *oid, { struct git_istream *st; struct object_info oi = OBJECT_INFO_INIT; - const struct object_id *real = lookup_replace_object(oid); + const struct object_id *real = lookup_replace_object(the_repository, oid); enum input_source src = istream_source(real, type, &oi); if (src < 0) diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c index 7c4f43746e..e9e0541276 100644 --- a/t/helper/test-ref-store.c +++ b/t/helper/test-ref-store.c @@ -3,6 +3,7 @@ #include "refs.h" #include "worktree.h" #include "object-store.h" +#include "repository.h" static const char *notnull(const char *arg, const char *name) { @@ -23,7 +24,7 @@ static const char **get_store(const char **argv, struct ref_store **refs) if (!argv[0]) { die("ref store required"); } else if (!strcmp(argv[0], "main")) { - *refs = get_main_ref_store(); + *refs = get_main_ref_store(the_repository); } else if (skip_prefix(argv[0], "submodule:", &gitdir)) { struct strbuf sb = STRBUF_INIT; int ret; |