diff --git a/attr.c b/attr.c index f3dd2de12d..38c586ab63 100644 --- a/attr.c +++ b/attr.c @@ -1301,7 +1301,8 @@ static const char *builtin_object_mode_attr(struct index_state *istate, const ch if (pos >= 0) { if (S_ISGITLINK(istate->cache[pos]->ce_mode)) mode = istate->cache[pos]->ce_mode; - } else if (resolve_gitlink_ref(path, "HEAD", &oid) == 0) { + } else if (repo_resolve_gitlink_ref(the_repository, path, + "HEAD", &oid) == 0) { mode = S_IFGITLINK; } } diff --git a/builtin/clone.c b/builtin/clone.c index 23993b905b..1e07524c53 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -1468,6 +1468,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) } else if (remote_head) { our_head_points_at = NULL; } else { + char *to_free = NULL; const char *branch; if (!mapped_refs) { @@ -1480,7 +1481,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) "refs/heads/", &branch)) { unborn_head = xstrdup(transport_ls_refs_options.unborn_head_target); } else { - branch = git_default_branch_name(0); + branch = to_free = repo_default_branch_name(the_repository, 0); unborn_head = xstrfmt("refs/heads/%s", branch); } @@ -1496,6 +1497,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix) * a match. */ our_head_points_at = find_remote_branch(mapped_refs, branch); + + free(to_free); } write_refspec_config(src_ref_prefix, our_head_points_at, diff --git a/builtin/describe.c b/builtin/describe.c index 82aca00c80..e5287eddf2 100644 --- a/builtin/describe.c +++ b/builtin/describe.c @@ -200,7 +200,7 @@ static int get_name(const char *path, const struct object_id *oid, } /* Is it annotated? */ - if (!peel_iterated_oid(oid, &peeled)) { + if (!peel_iterated_oid(the_repository, oid, &peeled)) { is_annotated = !oideq(oid, &peeled); } else { oidcpy(&peeled, oid); diff --git a/builtin/fetch.c b/builtin/fetch.c index 75255dc600..a319954f9f 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -1412,7 +1412,8 @@ static int prune_refs(struct display_state *display_state, _("(none)"), ref->name, &ref->new_oid, &ref->old_oid, summary_width); - warn_dangling_symref(stderr, dangling_msg, ref->name); + refs_warn_dangling_symref(get_main_ref_store(the_repository), + stderr, dangling_msg, ref->name); } } diff --git a/builtin/gc.c b/builtin/gc.c index 054fca7835..72bac2554f 100644 --- a/builtin/gc.c +++ b/builtin/gc.c @@ -846,7 +846,7 @@ static int dfs_on_ref(const char *refname UNUSED, struct commit_list *stack = NULL; struct commit *commit; - if (!peel_iterated_oid(oid, &peeled)) + if (!peel_iterated_oid(the_repository, oid, &peeled)) oid = &peeled; if (oid_object_info(the_repository, oid, NULL) != OBJ_COMMIT) return 0; diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index a6992eaabb..638f5c57f0 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -779,7 +779,7 @@ static int mark_tagged(const char *path UNUSED, const struct object_id *oid, if (entry) entry->tagged = 1; - if (!peel_iterated_oid(oid, &peeled)) { + if (!peel_iterated_oid(the_repository, oid, &peeled)) { entry = packlist_find(&to_pack, &peeled); if (entry) entry->tagged = 1; @@ -3132,7 +3132,7 @@ static int add_ref_tag(const char *tag UNUSED, const struct object_id *oid, { struct object_id peeled; - if (!peel_iterated_oid(oid, &peeled) && obj_is_packed(&peeled)) + if (!peel_iterated_oid(the_repository, oid, &peeled) && obj_is_packed(&peeled)) add_tag_chain(oid); return 0; } @@ -4081,7 +4081,7 @@ static int mark_bitmap_preferred_tip(const char *refname, struct object_id peeled; struct object *object; - if (!peel_iterated_oid(oid, &peeled)) + if (!peel_iterated_oid(the_repository, oid, &peeled)) oid = &peeled; object = parse_object_or_die(oid, refname); diff --git a/builtin/reflog.c b/builtin/reflog.c index b4650cea16..0d2ff95c6e 100644 --- a/builtin/reflog.c +++ b/builtin/reflog.c @@ -378,7 +378,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix) char *ref; struct expire_reflog_policy_cb cb = { .cmd = cmd }; - if (!dwim_log(argv[i], strlen(argv[i]), NULL, &ref)) { + if (!repo_dwim_log(the_repository, argv[i], strlen(argv[i]), NULL, &ref)) { status |= error(_("%s points nowhere!"), argv[i]); continue; } diff --git a/builtin/remote.c b/builtin/remote.c index d52b1c0e10..447ef1d3c9 100644 --- a/builtin/remote.c +++ b/builtin/remote.c @@ -1477,7 +1477,8 @@ static int prune_remote(const char *remote, int dry_run) abbrev_ref(refname, "refs/remotes/")); } - warn_dangling_symrefs(stdout, dangling_msg, &refs_to_prune); + refs_warn_dangling_symrefs(get_main_ref_store(the_repository), + stdout, dangling_msg, &refs_to_prune); string_list_clear(&refs_to_prune, 0); free_remote_ref_states(&states); diff --git a/builtin/repack.c b/builtin/repack.c index 43491a4cbf..58ad82dd97 100644 --- a/builtin/repack.c +++ b/builtin/repack.c @@ -673,7 +673,7 @@ static int midx_snapshot_ref_one(const char *refname UNUSED, struct midx_snapshot_ref_data *data = _data; struct object_id peeled; - if (!peel_iterated_oid(oid, &peeled)) + if (!peel_iterated_oid(the_repository, oid, &peeled)) oid = &peeled; if (oidset_insert(&data->seen, oid)) diff --git a/builtin/replace.c b/builtin/replace.c index f46ff57691..ce9f6974d2 100644 --- a/builtin/replace.c +++ b/builtin/replace.c @@ -43,11 +43,12 @@ enum replace_format { }; struct show_data { + struct repository *repo; const char *pattern; enum replace_format format; }; -static int show_reference(struct repository *r, const char *refname, +static int show_reference(const char *refname, const struct object_id *oid, int flag UNUSED, void *cb_data) { @@ -62,11 +63,11 @@ static int show_reference(struct repository *r, const char *refname, struct object_id object; enum object_type obj_type, repl_type; - if (repo_get_oid(r, refname, &object)) + if (repo_get_oid(data->repo, refname, &object)) return error(_("failed to resolve '%s' as a valid ref"), refname); - obj_type = oid_object_info(r, &object, NULL); - repl_type = oid_object_info(r, oid, NULL); + obj_type = oid_object_info(data->repo, &object, NULL); + repl_type = oid_object_info(data->repo, oid, NULL); printf("%s (%s) -> %s (%s)\n", refname, type_name(obj_type), oid_to_hex(oid), type_name(repl_type)); @@ -80,6 +81,7 @@ static int list_replace_refs(const char *pattern, const char *format) { struct show_data data; + data.repo = the_repository; if (!pattern) pattern = "*"; data.pattern = pattern; @@ -99,7 +101,8 @@ static int list_replace_refs(const char *pattern, const char *format) "valid formats are 'short', 'medium' and 'long'"), format); - for_each_replace_ref(the_repository, show_reference, (void *)&data); + refs_for_each_replace_ref(get_main_ref_store(the_repository), + show_reference, (void *)&data); return 0; } diff --git a/builtin/show-ref.c b/builtin/show-ref.c index 151ef35134..3114bdc391 100644 --- a/builtin/show-ref.c +++ b/builtin/show-ref.c @@ -50,7 +50,7 @@ static void show_one(const struct show_one_options *opts, if (!opts->deref_tags) return; - if (!peel_iterated_oid(oid, &peeled)) { + if (!peel_iterated_oid(the_repository, oid, &peeled)) { hex = repo_find_unique_abbrev(the_repository, &peeled, opts->abbrev); printf("%s %s^{}\n", hex, refname); } diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index e604cb5ddb..897f19868e 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -679,7 +679,8 @@ static void status_submodule(const char *path, const struct object_id *ce_oid, displaypath); } else if (!(flags & OPT_CACHED)) { struct object_id oid; - struct ref_store *refs = get_submodule_ref_store(path); + struct ref_store *refs = repo_get_submodule_ref_store(the_repository, + path); if (!refs) { print_status(flags, '-', path, ce_oid, displaypath); @@ -903,7 +904,8 @@ static void generate_submodule_summary(struct summary_cb *info, if (!info->cached && oideq(&p->oid_dst, null_oid())) { if (S_ISGITLINK(p->mod_dst)) { - struct ref_store *refs = get_submodule_ref_store(p->sm_path); + struct ref_store *refs = repo_get_submodule_ref_store(the_repository, + p->sm_path); if (refs) refs_head_ref(refs, handle_submodule_head_ref, &p->oid_dst); @@ -2598,7 +2600,8 @@ static int update_submodule(struct update_data *update_data) if (update_data->just_cloned) oidcpy(&update_data->suboid, null_oid()); - else if (resolve_gitlink_ref(update_data->sm_path, "HEAD", &update_data->suboid)) + else if (repo_resolve_gitlink_ref(the_repository, update_data->sm_path, + "HEAD", &update_data->suboid)) return die_message(_("Unable to find current revision in submodule path '%s'"), update_data->displaypath); @@ -2625,7 +2628,8 @@ static int update_submodule(struct update_data *update_data) update_data->sm_path); } - if (resolve_gitlink_ref(update_data->sm_path, remote_ref, &update_data->oid)) + if (repo_resolve_gitlink_ref(the_repository, update_data->sm_path, + remote_ref, &update_data->oid)) return die_message(_("Unable to find %s revision in submodule path '%s'"), remote_ref, update_data->sm_path); @@ -3355,7 +3359,7 @@ static void die_on_repo_without_commits(const char *path) strbuf_addstr(&sb, path); if (is_nonbare_repository_dir(&sb)) { struct object_id oid; - if (resolve_gitlink_ref(path, "HEAD", &oid) < 0) + if (repo_resolve_gitlink_ref(the_repository, path, "HEAD", &oid) < 0) die(_("'%s' does not have a commit checked out"), path); } strbuf_release(&sb); diff --git a/builtin/update-index.c b/builtin/update-index.c index 20aa1c4c68..d343416ae2 100644 --- a/builtin/update-index.c +++ b/builtin/update-index.c @@ -349,7 +349,8 @@ static int process_directory(const char *path, int len, struct stat *st) if (S_ISGITLINK(ce->ce_mode)) { /* Do nothing to the index if there is no HEAD! */ - if (resolve_gitlink_ref(path, "HEAD", &oid) < 0) + if (repo_resolve_gitlink_ref(the_repository, path, + "HEAD", &oid) < 0) return 0; return add_one_path(ce, path, len, st); @@ -375,7 +376,7 @@ static int process_directory(const char *path, int len, struct stat *st) } /* No match - should we add it as a gitlink? */ - if (!resolve_gitlink_ref(path, "HEAD", &oid)) + if (!repo_resolve_gitlink_ref(the_repository, path, "HEAD", &oid)) return add_one_path(NULL, path, len, st); /* Error out. */ diff --git a/builtin/var.c b/builtin/var.c index cf5567208a..5dc384810c 100644 --- a/builtin/var.c +++ b/builtin/var.c @@ -46,7 +46,7 @@ static char *pager(int ident_flag UNUSED) static char *default_branch(int ident_flag UNUSED) { - return xstrdup_or_null(git_default_branch_name(1)); + return repo_default_branch_name(the_repository, 1); } static char *shell_path(int ident_flag UNUSED) diff --git a/builtin/worktree.c b/builtin/worktree.c index 7e0868df72..893e973871 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -509,7 +509,7 @@ static int add_worktree(const char *path, const char *refname, } wt_refs = get_worktree_ref_store(wt); - ret = refs_init_db(wt_refs, REFS_INIT_DB_IS_WORKTREE, &sb); + ret = ref_store_create_on_disk(wt_refs, REF_STORE_CREATE_ON_DISK_IS_WORKTREE, &sb); if (ret) goto done; diff --git a/combine-diff.c b/combine-diff.c index d6d6fa1689..4960d904ac 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -1066,7 +1066,8 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, elem->mode = canon_mode(st.st_mode); } else if (S_ISDIR(st.st_mode)) { struct object_id oid; - if (resolve_gitlink_ref(elem->path, "HEAD", &oid) < 0) + if (repo_resolve_gitlink_ref(the_repository, elem->path, + "HEAD", &oid) < 0) result = grab_blob(opt->repo, &elem->oid, elem->mode, &result_size, NULL, NULL); diff --git a/commit-graph.c b/commit-graph.c index c4c156ff52..e5dd3553df 100644 --- a/commit-graph.c +++ b/commit-graph.c @@ -1821,7 +1821,7 @@ static int add_ref_to_set(const char *refname UNUSED, struct object_id peeled; struct refs_cb_data *data = (struct refs_cb_data *)cb_data; - if (!peel_iterated_oid(oid, &peeled)) + if (!peel_iterated_oid(the_repository, oid, &peeled)) oid = &peeled; if (oid_object_info(the_repository, oid, NULL) == OBJ_COMMIT) oidset_insert(data->commits, oid); diff --git a/diff-lib.c b/diff-lib.c index 12b1541478..5a5a50c5a1 100644 --- a/diff-lib.c +++ b/diff-lib.c @@ -66,7 +66,8 @@ static int check_removed(const struct cache_entry *ce, struct stat *st) * a directory --- the blob was removed! */ if (!S_ISGITLINK(ce->ce_mode) && - resolve_gitlink_ref(ce->name, "HEAD", &sub)) + repo_resolve_gitlink_ref(the_repository, ce->name, + "HEAD", &sub)) return 1; } return 0; diff --git a/dir.c b/dir.c index 2d83f3311a..f6066cc01d 100644 --- a/dir.c +++ b/dir.c @@ -3318,7 +3318,8 @@ static int remove_dir_recurse(struct strbuf *path, int flag, int *kept_up) struct object_id submodule_head; if ((flag & REMOVE_DIR_KEEP_NESTED_GIT) && - !resolve_gitlink_ref(path->buf, "HEAD", &submodule_head)) { + !repo_resolve_gitlink_ref(the_repository, path->buf, + "HEAD", &submodule_head)) { /* Do not descend and nuke a nested git work tree. */ if (kept_up) *kept_up = 1; diff --git a/ls-refs.c b/ls-refs.c index 8e3ffff811..398afe4ce3 100644 --- a/ls-refs.c +++ b/ls-refs.c @@ -110,7 +110,7 @@ static int send_ref(const char *refname, const struct object_id *oid, if (data->peel && oid) { struct object_id peeled; - if (!peel_iterated_oid(oid, &peeled)) + if (!peel_iterated_oid(the_repository, oid, &peeled)) strbuf_addf(&data->buf, " peeled:%s", oid_to_hex(&peeled)); } diff --git a/midx-write.c b/midx-write.c index 2fa120c213..4998707eb8 100644 --- a/midx-write.c +++ b/midx-write.c @@ -664,7 +664,7 @@ static int add_ref_to_pending(const char *refname, return 0; } - if (!peel_iterated_oid(oid, &peeled)) + if (!peel_iterated_oid(the_repository, oid, &peeled)) oid = &peeled; object = parse_object_or_die(oid, refname); diff --git a/object-file.c b/object-file.c index 610b1f465c..a40300ce4a 100644 --- a/object-file.c +++ b/object-file.c @@ -2669,7 +2669,7 @@ int index_path(struct index_state *istate, struct object_id *oid, strbuf_release(&sb); break; case S_IFDIR: - return resolve_gitlink_ref(path, "HEAD", oid); + return repo_resolve_gitlink_ref(the_repository, path, "HEAD", oid); default: return error(_("%s: unsupported file type"), path); } diff --git a/object.c b/object.c index 51e384828e..93b5d97fdb 100644 --- a/object.c +++ b/object.c @@ -207,6 +207,29 @@ struct object *lookup_object_by_type(struct repository *r, } } +enum peel_status peel_object(struct repository *r, + const struct object_id *name, + struct object_id *oid) +{ + struct object *o = lookup_unknown_object(r, name); + + if (o->type == OBJ_NONE) { + int type = oid_object_info(r, name, NULL); + if (type < 0 || !object_as_type(o, type, 0)) + return PEEL_INVALID; + } + + if (o->type != OBJ_TAG) + return PEEL_NON_TAG; + + o = deref_tag_noverify(r, o); + if (!o) + return PEEL_INVALID; + + oidcpy(oid, &o->oid); + return PEEL_PEELED; +} + struct object *parse_object_buffer(struct repository *r, const struct object_id *oid, enum object_type type, unsigned long size, void *buffer, int *eaten_p) { struct object *obj; diff --git a/object.h b/object.h index 99b9c8f114..73b4ec3904 100644 --- a/object.h +++ b/object.h @@ -257,6 +257,41 @@ struct object *lookup_unknown_object(struct repository *r, const struct object_i struct object *lookup_object_by_type(struct repository *r, const struct object_id *oid, enum object_type type); +enum peel_status { + /* object was peeled successfully: */ + PEEL_PEELED = 0, + + /* + * object cannot be peeled because the named object (or an + * object referred to by a tag in the peel chain), does not + * exist. + */ + PEEL_INVALID = -1, + + /* object cannot be peeled because it is not a tag: */ + PEEL_NON_TAG = -2, + + /* ref_entry contains no peeled value because it is a symref: */ + PEEL_IS_SYMREF = -3, + + /* + * ref_entry cannot be peeled because it is broken (i.e., the + * symbolic reference cannot even be resolved to an object + * name): + */ + PEEL_BROKEN = -4 +}; + +/* + * Peel the named object; i.e., if the object is a tag, resolve the + * tag recursively until a non-tag is found. If successful, store the + * result to oid and return PEEL_PEELED. If the object is not a tag + * or is not valid, return PEEL_NON_TAG or PEEL_INVALID, respectively, + * and leave oid unchanged. + */ +enum peel_status peel_object(struct repository *r, + const struct object_id *name, struct object_id *oid); + struct object_list *object_list_insert(struct object *item, struct object_list **list_p); diff --git a/read-cache.c b/read-cache.c index a6db25a16d..447109aa76 100644 --- a/read-cache.c +++ b/read-cache.c @@ -271,7 +271,8 @@ static int ce_compare_gitlink(const struct cache_entry *ce) * * If so, we consider it always to match. */ - if (resolve_gitlink_ref(ce->name, "HEAD", &oid) < 0) + if (repo_resolve_gitlink_ref(the_repository, ce->name, + "HEAD", &oid) < 0) return 0; return !oideq(&oid, &ce->oid); } @@ -711,7 +712,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st, namelen = strlen(path); if (S_ISDIR(st_mode)) { - if (resolve_gitlink_ref(path, "HEAD", &oid) < 0) + if (repo_resolve_gitlink_ref(the_repository, path, "HEAD", &oid) < 0) return error(_("'%s' does not have a commit checked out"), path); while (namelen && path[namelen-1] == '/') namelen--; diff --git a/ref-filter.c b/ref-filter.c index cf6525195a..f7fb0c7e0e 100644 --- a/ref-filter.c +++ b/ref-filter.c @@ -2520,7 +2520,7 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err) * If it is a tag object, see if we use the peeled value. If we do, * grab the peeled OID. */ - if (need_tagged && peel_iterated_oid(&obj->oid, &oi_deref.oid)) + if (need_tagged && peel_iterated_oid(the_repository, &obj->oid, &oi_deref.oid)) die("bad tag"); return get_object(ref, 1, &obj, &oi_deref, err); diff --git a/reflog-walk.c b/reflog-walk.c index f11b97e889..5f09552c5c 100644 --- a/reflog-walk.c +++ b/reflog-walk.c @@ -191,8 +191,8 @@ int add_reflog_for_walk(struct reflog_walk_info *info, reflogs = read_complete_reflog(branch); if (!reflogs || reflogs->nr == 0) { char *b; - int ret = dwim_log(branch, strlen(branch), - NULL, &b); + int ret = repo_dwim_log(the_repository, branch, strlen(branch), + NULL, &b); if (ret > 1) free(b); else if (ret == 1) { diff --git a/reflog.c b/reflog.c index 8861c2d606..3c80950186 100644 --- a/reflog.c +++ b/reflog.c @@ -409,7 +409,7 @@ int reflog_delete(const char *rev, enum expire_reflog_flags flags, int verbose) if (!spec) return error(_("not a reflog: %s"), rev); - if (!dwim_log(rev, spec - rev, NULL, &ref)) { + if (!repo_dwim_log(the_repository, rev, spec - rev, NULL, &ref)) { status |= error(_("no reflog for '%s'"), rev); goto cleanup; } diff --git a/refs.c b/refs.c index 8260c27cde..31032588e0 100644 --- a/refs.c +++ b/refs.c @@ -6,7 +6,7 @@ #include "advice.h" #include "config.h" #include "environment.h" -#include "hashmap.h" +#include "strmap.h" #include "gettext.h" #include "hex.h" #include "lockfile.h" @@ -19,7 +19,6 @@ #include "object-store-ll.h" #include "object.h" #include "path.h" -#include "tag.h" #include "submodule.h" #include "worktree.h" #include "strvec.h" @@ -425,28 +424,8 @@ static int for_each_filter_refs(const char *refname, return filter->fn(refname, oid, flags, filter->cb_data); } -enum peel_status peel_object(const struct object_id *name, struct object_id *oid) -{ - struct object *o = lookup_unknown_object(the_repository, name); - - if (o->type == OBJ_NONE) { - int type = oid_object_info(the_repository, name, NULL); - if (type < 0 || !object_as_type(o, type, 0)) - return PEEL_INVALID; - } - - if (o->type != OBJ_TAG) - return PEEL_NON_TAG; - - o = deref_tag_noverify(o); - if (!o) - return PEEL_INVALID; - - oidcpy(oid, &o->oid); - return PEEL_PEELED; -} - struct warn_if_dangling_data { + struct ref_store *refs; FILE *fp; const char *refname; const struct string_list *refnames; @@ -463,8 +442,7 @@ static int warn_if_dangling_symref(const char *refname, if (!(flags & REF_ISSYMREF)) return 0; - resolves_to = refs_resolve_ref_unsafe(get_main_ref_store(the_repository), - refname, 0, NULL, NULL); + resolves_to = refs_resolve_ref_unsafe(d->refs, refname, 0, NULL, NULL); if (!resolves_to || (d->refname ? strcmp(resolves_to, d->refname) @@ -477,28 +455,28 @@ static int warn_if_dangling_symref(const char *refname, return 0; } -void warn_dangling_symref(FILE *fp, const char *msg_fmt, const char *refname) +void refs_warn_dangling_symref(struct ref_store *refs, FILE *fp, + const char *msg_fmt, const char *refname) { - struct warn_if_dangling_data data; - - data.fp = fp; - data.refname = refname; - data.refnames = NULL; - data.msg_fmt = msg_fmt; - refs_for_each_rawref(get_main_ref_store(the_repository), - warn_if_dangling_symref, &data); + struct warn_if_dangling_data data = { + .refs = refs, + .fp = fp, + .refname = refname, + .msg_fmt = msg_fmt, + }; + refs_for_each_rawref(refs, warn_if_dangling_symref, &data); } -void warn_dangling_symrefs(FILE *fp, const char *msg_fmt, const struct string_list *refnames) +void refs_warn_dangling_symrefs(struct ref_store *refs, FILE *fp, + const char *msg_fmt, const struct string_list *refnames) { - struct warn_if_dangling_data data; - - data.fp = fp; - data.refname = NULL; - data.refnames = refnames; - data.msg_fmt = msg_fmt; - refs_for_each_rawref(get_main_ref_store(the_repository), - warn_if_dangling_symref, &data); + struct warn_if_dangling_data data = { + .refs = refs, + .fp = fp, + .refnames = refnames, + .msg_fmt = msg_fmt, + }; + refs_for_each_rawref(refs, warn_if_dangling_symref, &data); } int refs_for_each_tag_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data) @@ -686,16 +664,6 @@ char *repo_default_branch_name(struct repository *r, int quiet) return ret; } -const char *git_default_branch_name(int quiet) -{ - static char *ret; - - if (!ret) - ret = repo_default_branch_name(the_repository, quiet); - - return ret; -} - /* * *string and *len will only be substituted, and *string returned (for * later free()ing) if the string passed in is a magic short-hand form @@ -807,11 +775,6 @@ int repo_dwim_log(struct repository *r, const char *str, int len, return logs_found; } -int dwim_log(const char *str, int len, struct object_id *oid, char **log) -{ - return repo_dwim_log(the_repository, str, len, oid, log); -} - int is_per_worktree_ref(const char *refname) { return starts_with(refname, "refs/worktree/") || @@ -1597,53 +1560,12 @@ struct ref_iterator *refs_ref_iterator_begin( return iter; } -/* - * Call fn for each reference in the specified submodule for which the - * refname begins with prefix. If trim is non-zero, then trim that - * many characters off the beginning of each refname before passing - * the refname to fn. flags can be DO_FOR_EACH_INCLUDE_BROKEN to - * include broken references in the iteration. If fn ever returns a - * non-zero value, stop the iteration and return that value; - * otherwise, return 0. - */ -static int do_for_each_repo_ref(struct repository *r, const char *prefix, - each_repo_ref_fn fn, int trim, int flags, - void *cb_data) -{ - struct ref_iterator *iter; - struct ref_store *refs = get_main_ref_store(r); - - if (!refs) - return 0; - - iter = refs_ref_iterator_begin(refs, prefix, NULL, trim, flags); - - return do_for_each_repo_ref_iterator(r, iter, fn, cb_data); -} - -struct do_for_each_ref_help { - each_ref_fn *fn; - void *cb_data; -}; - -static int do_for_each_ref_helper(struct repository *r UNUSED, - const char *refname, - const struct object_id *oid, - int flags, - void *cb_data) -{ - struct do_for_each_ref_help *hp = cb_data; - - return hp->fn(refname, oid, flags, hp->cb_data); -} - static int do_for_each_ref(struct ref_store *refs, const char *prefix, const char **exclude_patterns, each_ref_fn fn, int trim, enum do_for_each_ref_flags flags, void *cb_data) { struct ref_iterator *iter; - struct do_for_each_ref_help hp = { fn, cb_data }; if (!refs) return 0; @@ -1651,8 +1573,7 @@ static int do_for_each_ref(struct ref_store *refs, const char *prefix, iter = refs_ref_iterator_begin(refs, prefix, exclude_patterns, trim, flags); - return do_for_each_repo_ref_iterator(the_repository, iter, - do_for_each_ref_helper, &hp); + return do_for_each_ref_iterator(iter, fn, cb_data); } int refs_for_each_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data) @@ -1673,12 +1594,12 @@ int refs_for_each_fullref_in(struct ref_store *refs, const char *prefix, return do_for_each_ref(refs, prefix, exclude_patterns, fn, 0, 0, cb_data); } -int for_each_replace_ref(struct repository *r, each_repo_ref_fn fn, void *cb_data) +int refs_for_each_replace_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data) { const char *git_replace_ref_base = ref_namespace[NAMESPACE_REPLACE].ref; - return do_for_each_repo_ref(r, git_replace_ref_base, fn, - strlen(git_replace_ref_base), - DO_FOR_EACH_INCLUDE_BROKEN, cb_data); + return do_for_each_ref(refs, git_replace_ref_base, NULL, fn, + strlen(git_replace_ref_base), + DO_FOR_EACH_INCLUDE_BROKEN, cb_data); } int refs_for_each_namespaced_ref(struct ref_store *refs, @@ -1928,19 +1849,19 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs, } /* backend functions */ -int refs_init_db(struct ref_store *refs, int flags, struct strbuf *err) +int ref_store_create_on_disk(struct ref_store *refs, int flags, struct strbuf *err) { - return refs->be->init_db(refs, flags, err); + return refs->be->create_on_disk(refs, flags, err); } -int resolve_gitlink_ref(const char *submodule, const char *refname, - struct object_id *oid) +int repo_resolve_gitlink_ref(struct repository *r, + const char *submodule, const char *refname, + struct object_id *oid) { struct ref_store *refs; int flags; - refs = get_submodule_ref_store(submodule); - + refs = repo_get_submodule_ref_store(r, submodule); if (!refs) return -1; @@ -1950,66 +1871,21 @@ int resolve_gitlink_ref(const char *submodule, const char *refname, return 0; } -struct ref_store_hash_entry -{ - struct hashmap_entry ent; - - struct ref_store *refs; - - /* NUL-terminated identifier of the ref store: */ - char name[FLEX_ARRAY]; -}; - -static int ref_store_hash_cmp(const void *cmp_data UNUSED, - const struct hashmap_entry *eptr, - const struct hashmap_entry *entry_or_key, - const void *keydata) -{ - const struct ref_store_hash_entry *e1, *e2; - const char *name; - - e1 = container_of(eptr, const struct ref_store_hash_entry, ent); - e2 = container_of(entry_or_key, const struct ref_store_hash_entry, ent); - name = keydata ? keydata : e2->name; - - return strcmp(e1->name, name); -} - -static struct ref_store_hash_entry *alloc_ref_store_hash_entry( - const char *name, struct ref_store *refs) -{ - struct ref_store_hash_entry *entry; - - FLEX_ALLOC_STR(entry, name, name); - hashmap_entry_init(&entry->ent, strhash(name)); - entry->refs = refs; - return entry; -} - -/* A hashmap of ref_stores, stored by submodule name: */ -static struct hashmap submodule_ref_stores; - -/* A hashmap of ref_stores, stored by worktree id: */ -static struct hashmap worktree_ref_stores; - /* * Look up a ref store by name. If that ref_store hasn't been * registered yet, return NULL. */ -static struct ref_store *lookup_ref_store_map(struct hashmap *map, +static struct ref_store *lookup_ref_store_map(struct strmap *map, const char *name) { - struct ref_store_hash_entry *entry; - unsigned int hash; + struct strmap_entry *entry; - if (!map->tablesize) + if (!map->map.tablesize) /* It's initialized on demand in register_ref_store(). */ return NULL; - hash = strhash(name); - entry = hashmap_get_entry_from_hash(map, hash, name, - struct ref_store_hash_entry, ent); - return entry ? entry->refs : NULL; + entry = strmap_get_entry(map, name); + return entry ? entry->value : NULL; } /* @@ -2031,6 +1907,12 @@ static struct ref_store *ref_store_init(struct repository *repo, return refs; } +void ref_store_release(struct ref_store *ref_store) +{ + ref_store->be->release(ref_store); + free(ref_store->gitdir); +} + struct ref_store *get_main_ref_store(struct repository *r) { if (r->refs_private) @@ -2048,22 +1930,19 @@ struct ref_store *get_main_ref_store(struct repository *r) * Associate a ref store with a name. It is a fatal error to call this * function twice for the same name. */ -static void register_ref_store_map(struct hashmap *map, +static void register_ref_store_map(struct strmap *map, const char *type, struct ref_store *refs, const char *name) { - struct ref_store_hash_entry *entry; - - if (!map->tablesize) - hashmap_init(map, ref_store_hash_cmp, NULL, 0); - - entry = alloc_ref_store_hash_entry(name, refs); - if (hashmap_put(map, &entry->ent)) + if (!map->map.tablesize) + strmap_init(map); + if (strmap_put(map, name, refs)) BUG("%s ref_store '%s' initialized twice", type, name); } -struct ref_store *get_submodule_ref_store(const char *submodule) +struct ref_store *repo_get_submodule_ref_store(struct repository *repo, + const char *submodule) { struct strbuf submodule_sb = STRBUF_INIT; struct ref_store *refs; @@ -2084,7 +1963,7 @@ struct ref_store *get_submodule_ref_store(const char *submodule) /* We need to strip off one or more trailing slashes */ submodule = to_free = xmemdupz(submodule, len); - refs = lookup_ref_store_map(&submodule_ref_stores, submodule); + refs = lookup_ref_store_map(&repo->submodule_ref_stores, submodule); if (refs) goto done; @@ -2096,20 +1975,15 @@ struct ref_store *get_submodule_ref_store(const char *submodule) goto done; subrepo = xmalloc(sizeof(*subrepo)); - /* - * NEEDSWORK: Make get_submodule_ref_store() work with arbitrary - * superprojects other than the_repository. This probably should be - * done by making it take a struct repository * parameter instead of a - * submodule path. - */ - if (repo_submodule_init(subrepo, the_repository, submodule, + + if (repo_submodule_init(subrepo, repo, submodule, null_oid())) { free(subrepo); goto done; } refs = ref_store_init(subrepo, submodule_sb.buf, REF_STORE_READ | REF_STORE_ODB); - register_ref_store_map(&submodule_ref_stores, "submodule", + register_ref_store_map(&repo->submodule_ref_stores, "submodule", refs, submodule); done: @@ -2125,25 +1999,29 @@ struct ref_store *get_worktree_ref_store(const struct worktree *wt) const char *id; if (wt->is_current) - return get_main_ref_store(the_repository); + return get_main_ref_store(wt->repo); id = wt->id ? wt->id : "/"; - refs = lookup_ref_store_map(&worktree_ref_stores, id); + refs = lookup_ref_store_map(&wt->repo->worktree_ref_stores, id); if (refs) return refs; - if (wt->id) - refs = ref_store_init(the_repository, - git_common_path("worktrees/%s", wt->id), + if (wt->id) { + struct strbuf common_path = STRBUF_INIT; + strbuf_git_common_path(&common_path, wt->repo, + "worktrees/%s", wt->id); + refs = ref_store_init(wt->repo, common_path.buf, REF_STORE_ALL_CAPS); - else - refs = ref_store_init(the_repository, - get_git_common_dir(), + strbuf_release(&common_path); + } else { + refs = ref_store_init(wt->repo, wt->repo->commondir, REF_STORE_ALL_CAPS); + } if (refs) - register_ref_store_map(&worktree_ref_stores, "worktree", - refs, id); + register_ref_store_map(&wt->repo->worktree_ref_stores, + "worktree", refs, id); + return refs; } @@ -2161,14 +2039,14 @@ int refs_pack_refs(struct ref_store *refs, struct pack_refs_opts *opts) return refs->be->pack_refs(refs, opts); } -int peel_iterated_oid(const struct object_id *base, struct object_id *peeled) +int peel_iterated_oid(struct repository *r, const struct object_id *base, struct object_id *peeled) { if (current_ref_iter && (current_ref_iter->oid == base || oideq(current_ref_iter->oid, base))) return ref_iterator_peel(current_ref_iter, peeled); - return peel_object(base, peeled) ? -1 : 0; + return peel_object(r, base, peeled) ? -1 : 0; } int refs_update_symref(struct ref_store *refs, const char *ref, @@ -2478,8 +2356,7 @@ struct do_for_each_reflog_help { void *cb_data; }; -static int do_for_each_reflog_helper(struct repository *r UNUSED, - const char *refname, +static int do_for_each_reflog_helper(const char *refname, const struct object_id *oid UNUSED, int flags, void *cb_data) @@ -2495,8 +2372,7 @@ int refs_for_each_reflog(struct ref_store *refs, each_reflog_fn fn, void *cb_dat iter = refs->be->reflog_iterator_begin(refs); - return do_for_each_repo_ref_iterator(the_repository, iter, - do_for_each_reflog_helper, &hp); + return do_for_each_ref_iterator(iter, do_for_each_reflog_helper, &hp); } int refs_for_each_reflog_ent_reverse(struct ref_store *refs, diff --git a/refs.h b/refs.h index 34568ee1fb..fe7f0db35e 100644 --- a/refs.h +++ b/refs.h @@ -114,21 +114,27 @@ int should_autocreate_reflog(const char *refname); int is_branch(const char *refname); -#define REFS_INIT_DB_IS_WORKTREE (1 << 0) +#define REF_STORE_CREATE_ON_DISK_IS_WORKTREE (1 << 0) -int refs_init_db(struct ref_store *refs, int flags, struct strbuf *err); +int ref_store_create_on_disk(struct ref_store *refs, int flags, struct strbuf *err); + +/* + * Release all memory and resources associated with the ref store. + */ +void ref_store_release(struct ref_store *ref_store); /* * Return the peeled value of the oid currently being iterated via * for_each_ref(), etc. This is equivalent to calling: * - * peel_object(oid, &peeled); + * peel_object(r, oid, &peeled); * * with the "oid" value given to the each_ref_fn callback, except * that some ref storage may be able to answer the query without * actually loading the object in memory. */ -int peel_iterated_oid(const struct object_id *base, struct object_id *peeled); +int peel_iterated_oid(struct repository *r, + const struct object_id *base, struct object_id *peeled); /** * Resolve refname in the nested "gitlink" repository in the specified @@ -136,8 +142,9 @@ int peel_iterated_oid(const struct object_id *base, struct object_id *peeled); * successful, return 0 and set oid to the name of the object; * otherwise, return a non-zero value. */ -int resolve_gitlink_ref(const char *submodule, const char *refname, - struct object_id *oid); +int repo_resolve_gitlink_ref(struct repository *r, + const char *submodule, const char *refname, + struct object_id *oid); /* * Return true iff abbrev_name is a possible abbreviation for @@ -157,15 +164,12 @@ int expand_ref(struct repository *r, const char *str, int len, struct object_id int repo_dwim_ref(struct repository *r, const char *str, int len, struct object_id *oid, char **ref, int nonfatal_dangling_mark); int repo_dwim_log(struct repository *r, const char *str, int len, struct object_id *oid, char **ref); -int dwim_log(const char *str, int len, struct object_id *oid, char **ref); /* * Retrieves the default branch name for newly-initialized repositories. * - * The return value of `repo_default_branch_name()` is an allocated string. The - * return value of `git_default_branch_name()` is a singleton. + * The return value is an allocated string. */ -const char *git_default_branch_name(int quiet); char *repo_default_branch_name(struct repository *r, int quiet); /* @@ -292,16 +296,6 @@ struct ref_transaction; typedef int each_ref_fn(const char *refname, const struct object_id *oid, int flags, void *cb_data); -/* - * The same as each_ref_fn, but also with a repository argument that - * contains the repository associated with the callback. - */ -typedef int each_repo_ref_fn(struct repository *r, - const char *refname, - const struct object_id *oid, - int flags, - void *cb_data); - /* * The following functions invoke the specified callback function for * each reference indicated. If the function ever returns a nonzero @@ -323,6 +317,8 @@ int refs_for_each_branch_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data); int refs_for_each_remote_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data); +int refs_for_each_replace_ref(struct ref_store *refs, + each_ref_fn fn, void *cb_data); /* * references matching any pattern in "exclude_patterns" are omitted from the @@ -347,11 +343,6 @@ int refs_for_each_fullref_in_prefixes(struct ref_store *refs, const char **exclude_patterns, each_ref_fn fn, void *cb_data); -/** - * iterate refs from the respective area. - */ -int for_each_replace_ref(struct repository *r, each_repo_ref_fn fn, void *cb_data); - /* iterates all refs that match the specified glob pattern. */ int refs_for_each_glob_ref(struct ref_store *refs, each_ref_fn fn, const char *pattern, void *cb_data); @@ -395,9 +386,10 @@ static inline const char *has_glob_specials(const char *pattern) return strpbrk(pattern, "?*["); } -void warn_dangling_symref(FILE *fp, const char *msg_fmt, const char *refname); -void warn_dangling_symrefs(FILE *fp, const char *msg_fmt, - const struct string_list *refnames); +void refs_warn_dangling_symref(struct ref_store *refs, FILE *fp, + const char *msg_fmt, const char *refname); +void refs_warn_dangling_symrefs(struct ref_store *refs, FILE *fp, + const char *msg_fmt, const struct string_list *refnames); /* * Flags for controlling behaviour of pack_refs() @@ -965,7 +957,8 @@ struct ref_store *get_main_ref_store(struct repository *r); * For backwards compatibility, submodule=="" is treated the same as * submodule==NULL. */ -struct ref_store *get_submodule_ref_store(const char *submodule); +struct ref_store *repo_get_submodule_ref_store(struct repository *repo, + const char *submodule); struct ref_store *get_worktree_ref_store(const struct worktree *wt); /* diff --git a/refs/debug.c b/refs/debug.c index 8be316bb67..547d9245b9 100644 --- a/refs/debug.c +++ b/refs/debug.c @@ -33,11 +33,18 @@ struct ref_store *maybe_debug_wrap_ref_store(const char *gitdir, struct ref_stor return (struct ref_store *)res; } -static int debug_init_db(struct ref_store *refs, int flags, struct strbuf *err) +static void debug_release(struct ref_store *refs) { struct debug_ref_store *drefs = (struct debug_ref_store *)refs; - int res = drefs->refs->be->init_db(drefs->refs, flags, err); - trace_printf_key(&trace_refs, "init_db: %d\n", res); + drefs->refs->be->release(drefs->refs); + trace_printf_key(&trace_refs, "release\n"); +} + +static int debug_create_on_disk(struct ref_store *refs, int flags, struct strbuf *err) +{ + struct debug_ref_store *drefs = (struct debug_ref_store *)refs; + int res = drefs->refs->be->create_on_disk(drefs->refs, flags, err); + trace_printf_key(&trace_refs, "create_on_disk: %d\n", res); return res; } @@ -415,7 +422,8 @@ static int debug_reflog_expire(struct ref_store *ref_store, const char *refname, struct ref_storage_be refs_be_debug = { .name = "debug", .init = NULL, - .init_db = debug_init_db, + .release = debug_release, + .create_on_disk = debug_create_on_disk, /* * None of these should be NULL. If the "files" backend (in diff --git a/refs/files-backend.c b/refs/files-backend.c index 5f3089d947..324c59b096 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -89,9 +89,9 @@ static void clear_loose_ref_cache(struct files_ref_store *refs) * Create a new submodule ref cache and add it to the internal * set of caches. */ -static struct ref_store *files_ref_store_create(struct repository *repo, - const char *gitdir, - unsigned int flags) +static struct ref_store *files_ref_store_init(struct repository *repo, + const char *gitdir, + unsigned int flags) { struct files_ref_store *refs = xcalloc(1, sizeof(*refs)); struct ref_store *ref_store = (struct ref_store *)refs; @@ -102,7 +102,7 @@ static struct ref_store *files_ref_store_create(struct repository *repo, get_common_dir_noenv(&sb, gitdir); refs->gitcommondir = strbuf_detach(&sb, NULL); refs->packed_ref_store = - packed_ref_store_create(repo, refs->gitcommondir, flags); + packed_ref_store_init(repo, refs->gitcommondir, flags); chdir_notify_reparent("files-backend $GIT_DIR", &refs->base.gitdir); chdir_notify_reparent("files-backend $GIT_COMMONDIR", @@ -149,6 +149,14 @@ static struct files_ref_store *files_downcast(struct ref_store *ref_store, return refs; } +static void files_ref_store_release(struct ref_store *ref_store) +{ + struct files_ref_store *refs = files_downcast(ref_store, 0, "release"); + free_ref_cache(refs->loose); + free(refs->gitcommondir); + ref_store_release(refs->packed_ref_store); +} + static void files_reflog_path(struct files_ref_store *refs, struct strbuf *sb, const char *refname) @@ -1230,7 +1238,8 @@ static void prune_refs(struct files_ref_store *refs, struct ref_to_prune **refs_ /* * Return true if the specified reference should be packed. */ -static int should_pack_ref(const char *refname, +static int should_pack_ref(struct files_ref_store *refs, + const char *refname, const struct object_id *oid, unsigned int ref_flags, struct pack_refs_opts *opts) { @@ -1246,7 +1255,7 @@ static int should_pack_ref(const char *refname, return 0; /* Do not pack broken refs: */ - if (!ref_resolves_to_object(refname, the_repository, oid, ref_flags)) + if (!ref_resolves_to_object(refname, refs->base.repo, oid, ref_flags)) return 0; if (ref_excluded(opts->exclusions, refname)) @@ -1278,14 +1287,14 @@ static int files_pack_refs(struct ref_store *ref_store, packed_refs_lock(refs->packed_ref_store, LOCK_DIE_ON_ERROR, &err); iter = cache_ref_iterator_begin(get_loose_ref_cache(refs, 0), NULL, - the_repository, 0); + refs->base.repo, 0); while ((ok = ref_iterator_advance(iter)) == ITER_OK) { /* * If the loose reference can be packed, add an entry * in the packed ref cache. If the reference should be * pruned, also add it to refs_to_prune. */ - if (!should_pack_ref(iter->refname, iter->oid, iter->flags, opts)) + if (!should_pack_ref(refs, iter->refname, iter->oid, iter->flags, opts)) continue; /* @@ -1382,7 +1391,8 @@ static int rename_tmp_log(struct files_ref_store *refs, const char *newrefname) return ret; } -static int write_ref_to_lockfile(struct ref_lock *lock, +static int write_ref_to_lockfile(struct files_ref_store *refs, + struct ref_lock *lock, const struct object_id *oid, int skip_oid_verification, struct strbuf *err); static int commit_ref_update(struct files_ref_store *refs, @@ -1530,7 +1540,7 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store, } oidcpy(&lock->old_oid, &orig_oid); - if (write_ref_to_lockfile(lock, &orig_oid, 0, &err) || + if (write_ref_to_lockfile(refs, lock, &orig_oid, 0, &err) || commit_ref_update(refs, lock, &orig_oid, logmsg, &err)) { error("unable to write current sha1 into %s: %s", newrefname, err.buf); strbuf_release(&err); @@ -1550,7 +1560,7 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store, flag = log_all_ref_updates; log_all_ref_updates = LOG_REFS_NONE; - if (write_ref_to_lockfile(lock, &orig_oid, 0, &err) || + if (write_ref_to_lockfile(refs, lock, &orig_oid, 0, &err) || commit_ref_update(refs, lock, &orig_oid, NULL, &err)) { error("unable to write current sha1 into %s: %s", oldrefname, err.buf); strbuf_release(&err); @@ -1784,7 +1794,8 @@ static int files_log_ref_write(struct files_ref_store *refs, * Write oid into the open lockfile, then close the lockfile. On * errors, rollback the lockfile, fill in *err and return -1. */ -static int write_ref_to_lockfile(struct ref_lock *lock, +static int write_ref_to_lockfile(struct files_ref_store *refs, + struct ref_lock *lock, const struct object_id *oid, int skip_oid_verification, struct strbuf *err) { @@ -1793,7 +1804,7 @@ static int write_ref_to_lockfile(struct ref_lock *lock, int fd; if (!skip_oid_verification) { - o = parse_object(the_repository, oid); + o = parse_object(refs->base.repo, oid); if (!o) { strbuf_addf( err, @@ -1812,7 +1823,7 @@ static int write_ref_to_lockfile(struct ref_lock *lock, } } fd = get_lock_file_fd(&lock->lk); - if (write_in_full(fd, oid_to_hex(oid), the_hash_algo->hexsz) < 0 || + if (write_in_full(fd, oid_to_hex(oid), refs->base.repo->hash_algo->hexsz) < 0 || write_in_full(fd, &term, 1) < 0 || fsync_component(FSYNC_COMPONENT_REFERENCE, get_lock_file_fd(&lock->lk)) < 0 || close_ref_gently(lock) < 0) { @@ -2547,7 +2558,7 @@ static int lock_ref_for_update(struct files_ref_store *refs, * value, so we don't need to write it. */ } else if (write_ref_to_lockfile( - lock, &update->new_oid, + refs, lock, &update->new_oid, update->flags & REF_SKIP_OID_VERIFICATION, err)) { char *write_err = strbuf_detach(err, NULL); @@ -3230,7 +3241,7 @@ static int files_reflog_expire(struct ref_store *ref_store, rollback_lock_file(&reflog_lock); } else if (update && (write_in_full(get_lock_file_fd(&lock->lk), - oid_to_hex(&cb.last_kept_oid), the_hash_algo->hexsz) < 0 || + oid_to_hex(&cb.last_kept_oid), refs->base.repo->hash_algo->hexsz) < 0 || write_str_in_full(get_lock_file_fd(&lock->lk), "\n") < 0 || close_ref_gently(lock) < 0)) { status |= error("couldn't write %s", @@ -3254,12 +3265,12 @@ static int files_reflog_expire(struct ref_store *ref_store, return -1; } -static int files_init_db(struct ref_store *ref_store, - int flags, - struct strbuf *err UNUSED) +static int files_ref_store_create_on_disk(struct ref_store *ref_store, + int flags, + struct strbuf *err UNUSED) { struct files_ref_store *refs = - files_downcast(ref_store, REF_STORE_WRITE, "init_db"); + files_downcast(ref_store, REF_STORE_WRITE, "create"); struct strbuf sb = STRBUF_INIT; /* @@ -3282,7 +3293,7 @@ static int files_init_db(struct ref_store *ref_store, * There is no need to create directories for common refs when creating * a worktree ref store. */ - if (!(flags & REFS_INIT_DB_IS_WORKTREE)) { + if (!(flags & REF_STORE_CREATE_ON_DISK_IS_WORKTREE)) { /* * Create .git/refs/{heads,tags} */ @@ -3301,8 +3312,10 @@ static int files_init_db(struct ref_store *ref_store, struct ref_storage_be refs_be_files = { .name = "files", - .init = files_ref_store_create, - .init_db = files_init_db, + .init = files_ref_store_init, + .release = files_ref_store_release, + .create_on_disk = files_ref_store_create_on_disk, + .transaction_prepare = files_transaction_prepare, .transaction_finish = files_transaction_finish, .transaction_abort = files_transaction_abort, diff --git a/refs/iterator.c b/refs/iterator.c index 9db8b056d5..d355ebf0d5 100644 --- a/refs/iterator.c +++ b/refs/iterator.c @@ -440,15 +440,15 @@ struct ref_iterator *prefix_ref_iterator_begin(struct ref_iterator *iter0, struct ref_iterator *current_ref_iter = NULL; -int do_for_each_repo_ref_iterator(struct repository *r, struct ref_iterator *iter, - each_repo_ref_fn fn, void *cb_data) +int do_for_each_ref_iterator(struct ref_iterator *iter, + each_ref_fn fn, void *cb_data) { int retval = 0, ok; struct ref_iterator *old_ref_iter = current_ref_iter; current_ref_iter = iter; while ((ok = ref_iterator_advance(iter)) == ITER_OK) { - retval = fn(r, iter->refname, iter->oid, iter->flags, cb_data); + retval = fn(iter->refname, iter->oid, iter->flags, cb_data); if (retval) { /* * If ref_iterator_abort() returns ITER_ERROR, diff --git a/refs/packed-backend.c b/refs/packed-backend.c index a937e7dbfc..2789fd92f5 100644 --- a/refs/packed-backend.c +++ b/refs/packed-backend.c @@ -200,9 +200,14 @@ static int release_snapshot(struct snapshot *snapshot) } } -struct ref_store *packed_ref_store_create(struct repository *repo, - const char *gitdir, - unsigned int store_flags) +static size_t snapshot_hexsz(const struct snapshot *snapshot) +{ + return snapshot->refs->base.repo->hash_algo->hexsz; +} + +struct ref_store *packed_ref_store_init(struct repository *repo, + const char *gitdir, + unsigned int store_flags) { struct packed_ref_store *refs = xcalloc(1, sizeof(*refs)); struct ref_store *ref_store = (struct ref_store *)refs; @@ -252,6 +257,15 @@ static void clear_snapshot(struct packed_ref_store *refs) } } +static void packed_ref_store_release(struct ref_store *ref_store) +{ + struct packed_ref_store *refs = packed_downcast(ref_store, 0, "release"); + clear_snapshot(refs); + rollback_lock_file(&refs->lock); + delete_tempfile(&refs->tempfile); + free(refs->path); +} + static NORETURN void die_unterminated_line(const char *path, const char *p, size_t len) { @@ -280,11 +294,13 @@ struct snapshot_record { size_t len; }; -static int cmp_packed_ref_records(const void *v1, const void *v2) +static int cmp_packed_ref_records(const void *v1, const void *v2, + void *cb_data) { + const struct snapshot *snapshot = cb_data; const struct snapshot_record *e1 = v1, *e2 = v2; - const char *r1 = e1->start + the_hash_algo->hexsz + 1; - const char *r2 = e2->start + the_hash_algo->hexsz + 1; + const char *r1 = e1->start + snapshot_hexsz(snapshot) + 1; + const char *r2 = e2->start + snapshot_hexsz(snapshot) + 1; while (1) { if (*r1 == '\n') @@ -305,9 +321,9 @@ static int cmp_packed_ref_records(const void *v1, const void *v2) * refname. */ static int cmp_record_to_refname(const char *rec, const char *refname, - int start) + int start, const struct snapshot *snapshot) { - const char *r1 = rec + the_hash_algo->hexsz + 1; + const char *r1 = rec + snapshot_hexsz(snapshot) + 1; const char *r2 = refname; while (1) { @@ -354,7 +370,7 @@ static void sort_snapshot(struct snapshot *snapshot) if (!eol) /* The safety check should prevent this. */ BUG("unterminated line found in packed-refs"); - if (eol - pos < the_hash_algo->hexsz + 2) + if (eol - pos < snapshot_hexsz(snapshot) + 2) die_invalid_line(snapshot->refs->path, pos, eof - pos); eol++; @@ -380,7 +396,7 @@ static void sort_snapshot(struct snapshot *snapshot) if (sorted && nr > 1 && cmp_packed_ref_records(&records[nr - 2], - &records[nr - 1]) >= 0) + &records[nr - 1], snapshot) >= 0) sorted = 0; pos = eol; @@ -390,7 +406,7 @@ static void sort_snapshot(struct snapshot *snapshot) goto cleanup; /* We need to sort the memory. First we sort the records array: */ - QSORT(records, nr, cmp_packed_ref_records); + QSORT_S(records, nr, cmp_packed_ref_records, snapshot); /* * Allocate a new chunk of memory, and copy the old memory to @@ -466,7 +482,8 @@ static void verify_buffer_safe(struct snapshot *snapshot) return; last_line = find_start_of_record(start, eof - 1); - if (*(eof - 1) != '\n' || eof - last_line < the_hash_algo->hexsz + 2) + if (*(eof - 1) != '\n' || + eof - last_line < snapshot_hexsz(snapshot) + 2) die_invalid_line(snapshot->refs->path, last_line, eof - last_line); } @@ -561,7 +578,7 @@ static const char *find_reference_location_1(struct snapshot *snapshot, mid = lo + (hi - lo) / 2; rec = find_start_of_record(lo, mid); - cmp = cmp_record_to_refname(rec, refname, start); + cmp = cmp_record_to_refname(rec, refname, start, snapshot); if (cmp < 0) { lo = find_end_of_record(mid, hi); } else if (cmp > 0) { @@ -858,7 +875,7 @@ static int next_record(struct packed_ref_iterator *iter) iter->base.flags = REF_ISPACKED; p = iter->pos; - if (iter->eof - p < the_hash_algo->hexsz + 2 || + if (iter->eof - p < snapshot_hexsz(iter->snapshot) + 2 || parse_oid_hex(p, &iter->oid, &p) || !isspace(*p++)) die_invalid_line(iter->snapshot->refs->path, @@ -888,7 +905,7 @@ static int next_record(struct packed_ref_iterator *iter) if (iter->pos < iter->eof && *iter->pos == '^') { p = iter->pos + 1; - if (iter->eof - p < the_hash_algo->hexsz + 1 || + if (iter->eof - p < snapshot_hexsz(iter->snapshot) + 1 || parse_oid_hex(p, &iter->peeled, &p) || *p++ != '\n') die_invalid_line(iter->snapshot->refs->path, @@ -944,16 +961,13 @@ static int packed_ref_iterator_peel(struct ref_iterator *ref_iterator, struct packed_ref_iterator *iter = (struct packed_ref_iterator *)ref_iterator; - if (iter->repo != the_repository) - BUG("peeling for non-the_repository is not supported"); - if ((iter->base.flags & REF_KNOWS_PEELED)) { oidcpy(peeled, &iter->peeled); return is_null_oid(&iter->peeled) ? -1 : 0; } else if ((iter->base.flags & (REF_ISBROKEN | REF_ISSYMREF))) { return -1; } else { - return peel_object(&iter->oid, peeled) ? -1 : 0; + return peel_object(iter->repo, &iter->oid, peeled) ? -1 : 0; } } @@ -1244,9 +1258,9 @@ int packed_refs_is_locked(struct ref_store *ref_store) static const char PACKED_REFS_HEADER[] = "# pack-refs with: peeled fully-peeled sorted \n"; -static int packed_init_db(struct ref_store *ref_store UNUSED, - int flags UNUSED, - struct strbuf *err UNUSED) +static int packed_ref_store_create_on_disk(struct ref_store *ref_store UNUSED, + int flags UNUSED, + struct strbuf *err UNUSED) { /* Nothing to do. */ return 0; @@ -1412,7 +1426,8 @@ static int write_with_updates(struct packed_ref_store *refs, i++; } else { struct object_id peeled; - int peel_error = peel_object(&update->new_oid, + int peel_error = peel_object(refs->base.repo, + &update->new_oid, &peeled); if (write_packed_entry(out, update->refname, @@ -1706,8 +1721,10 @@ static struct ref_iterator *packed_reflog_iterator_begin(struct ref_store *ref_s struct ref_storage_be refs_be_packed = { .name = "packed", - .init = packed_ref_store_create, - .init_db = packed_init_db, + .init = packed_ref_store_init, + .release = packed_ref_store_release, + .create_on_disk = packed_ref_store_create_on_disk, + .transaction_prepare = packed_transaction_prepare, .transaction_finish = packed_transaction_finish, .transaction_abort = packed_transaction_abort, diff --git a/refs/packed-backend.h b/refs/packed-backend.h index 9dd8a344c3..09437ad13b 100644 --- a/refs/packed-backend.h +++ b/refs/packed-backend.h @@ -13,9 +13,9 @@ struct ref_transaction; * even among packed refs. */ -struct ref_store *packed_ref_store_create(struct repository *repo, - const char *gitdir, - unsigned int store_flags); +struct ref_store *packed_ref_store_init(struct repository *repo, + const char *gitdir, + unsigned int store_flags); /* * Lock the packed-refs file for writing. Flags is passed to diff --git a/refs/ref-cache.c b/refs/ref-cache.c index 9f9797209a..b6c53fc8ed 100644 --- a/refs/ref-cache.c +++ b/refs/ref-cache.c @@ -441,10 +441,7 @@ static int cache_ref_iterator_peel(struct ref_iterator *ref_iterator, { struct cache_ref_iterator *iter = (struct cache_ref_iterator *)ref_iterator; - - if (iter->repo != the_repository) - BUG("peeling for non-the_repository is not supported"); - return peel_object(ref_iterator->oid, peeled) ? -1 : 0; + return peel_object(iter->repo, ref_iterator->oid, peeled) ? -1 : 0; } static int cache_ref_iterator_abort(struct ref_iterator *ref_iterator) diff --git a/refs/refs-internal.h b/refs/refs-internal.h index 53a6c5d842..33749fbd83 100644 --- a/refs/refs-internal.h +++ b/refs/refs-internal.h @@ -69,40 +69,6 @@ int ref_resolves_to_object(const char *refname, const struct object_id *oid, unsigned int flags); -enum peel_status { - /* object was peeled successfully: */ - PEEL_PEELED = 0, - - /* - * object cannot be peeled because the named object (or an - * object referred to by a tag in the peel chain), does not - * exist. - */ - PEEL_INVALID = -1, - - /* object cannot be peeled because it is not a tag: */ - PEEL_NON_TAG = -2, - - /* ref_entry contains no peeled value because it is a symref: */ - PEEL_IS_SYMREF = -3, - - /* - * ref_entry cannot be peeled because it is broken (i.e., the - * symbolic reference cannot even be resolved to an object - * name): - */ - PEEL_BROKEN = -4 -}; - -/* - * Peel the named object; i.e., if the object is a tag, resolve the - * tag recursively until a non-tag is found. If successful, store the - * result to oid and return PEEL_PEELED. If the object is not a tag - * or is not valid, return PEEL_NON_TAG or PEEL_INVALID, respectively, - * and leave oid unchanged. - */ -enum peel_status peel_object(const struct object_id *name, struct object_id *oid); - /** * Information needed for a single ref update. Set new_oid to the new * value or to null_oid to delete the ref. To check the old value @@ -517,9 +483,8 @@ extern struct ref_iterator *current_ref_iter; * adapter between the callback style of reference iteration and the * iterator style. */ -int do_for_each_repo_ref_iterator(struct repository *r, - struct ref_iterator *iter, - each_repo_ref_fn fn, void *cb_data); +int do_for_each_ref_iterator(struct ref_iterator *iter, + each_ref_fn fn, void *cb_data); struct ref_store; @@ -543,10 +508,14 @@ struct ref_store; typedef struct ref_store *ref_store_init_fn(struct repository *repo, const char *gitdir, unsigned int flags); +/* + * Release all memory and resources associated with the ref store. + */ +typedef void ref_store_release_fn(struct ref_store *refs); -typedef int ref_init_db_fn(struct ref_store *refs, - int flags, - struct strbuf *err); +typedef int ref_store_create_on_disk_fn(struct ref_store *refs, + int flags, + struct strbuf *err); typedef int ref_transaction_prepare_fn(struct ref_store *refs, struct ref_transaction *transaction, @@ -678,7 +647,8 @@ typedef int read_symbolic_ref_fn(struct ref_store *ref_store, const char *refnam struct ref_storage_be { const char *name; ref_store_init_fn *init; - ref_init_db_fn *init_db; + ref_store_release_fn *release; + ref_store_create_on_disk_fn *create_on_disk; ref_transaction_prepare_fn *transaction_prepare; ref_transaction_finish_fn *transaction_finish; @@ -709,7 +679,7 @@ extern struct ref_storage_be refs_be_packed; /* * A representation of the reference store for the main repository or * a submodule. The ref_store instances for submodules are kept in a - * hash map; see get_submodule_ref_store() for more info. + * hash map; see repo_get_submodule_ref_store() for more info. */ struct ref_store { /* The backend describing this ref_store's storage scheme: */ diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c index 24dfbfd2e3..438b5c478b 100644 --- a/refs/reftable-backend.c +++ b/refs/reftable-backend.c @@ -333,12 +333,33 @@ static struct ref_store *reftable_be_init(struct repository *repo, return &refs->base; } -static int reftable_be_init_db(struct ref_store *ref_store, - int flags UNUSED, - struct strbuf *err UNUSED) +static void reftable_be_release(struct ref_store *ref_store) +{ + struct reftable_ref_store *refs = reftable_be_downcast(ref_store, 0, "release"); + struct strmap_entry *entry; + struct hashmap_iter iter; + + if (refs->main_stack) { + reftable_stack_destroy(refs->main_stack); + refs->main_stack = NULL; + } + + if (refs->worktree_stack) { + reftable_stack_destroy(refs->worktree_stack); + refs->worktree_stack = NULL; + } + + strmap_for_each_entry(&refs->worktree_stacks, &iter, entry) + reftable_stack_destroy(entry->value); + strmap_clear(&refs->worktree_stacks, 0); +} + +static int reftable_be_create_on_disk(struct ref_store *ref_store, + int flags UNUSED, + struct strbuf *err UNUSED) { struct reftable_ref_store *refs = - reftable_be_downcast(ref_store, REF_STORE_WRITE, "init_db"); + reftable_be_downcast(ref_store, REF_STORE_WRITE, "create"); struct strbuf sb = STRBUF_INIT; strbuf_addf(&sb, "%s/reftable", refs->base.gitdir); @@ -1187,7 +1208,7 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data ref.refname = (char *)u->refname; ref.update_index = ts; - peel_error = peel_object(&u->new_oid, &peeled); + peel_error = peel_object(arg->refs->base.repo, &u->new_oid, &peeled); if (!peel_error) { ref.value_type = REFTABLE_REF_VAL2; memcpy(ref.value.val2.target_value, peeled.hash, GIT_MAX_RAWSZ); @@ -1980,6 +2001,7 @@ static int reftable_be_delete_reflog(struct ref_store *ref_store, } struct reflog_expiry_arg { + struct reftable_ref_store *refs; struct reftable_stack *stack; struct reftable_log_record *records; struct object_id update_oid; @@ -2008,7 +2030,7 @@ static int write_reflog_expiry_table(struct reftable_writer *writer, void *cb_da ref.refname = (char *)arg->refname; ref.update_index = ts; - if (!peel_object(&arg->update_oid, &peeled)) { + if (!peel_object(arg->refs->base.repo, &arg->update_oid, &peeled)) { ref.value_type = REFTABLE_REF_VAL2; memcpy(ref.value.val2.target_value, peeled.hash, GIT_MAX_RAWSZ); memcpy(ref.value.val2.value, arg->update_oid.hash, GIT_MAX_RAWSZ); @@ -2171,6 +2193,7 @@ static int reftable_be_reflog_expire(struct ref_store *ref_store, reftable_ref_record_val1(&ref_record)) oidread(&arg.update_oid, last_hash); + arg.refs = refs; arg.records = rewritten; arg.len = logs_nr; arg.stack = stack, @@ -2205,7 +2228,9 @@ static int reftable_be_reflog_expire(struct ref_store *ref_store, struct ref_storage_be refs_be_reftable = { .name = "reftable", .init = reftable_be_init, - .init_db = reftable_be_init_db, + .release = reftable_be_release, + .create_on_disk = reftable_be_create_on_disk, + .transaction_prepare = reftable_be_transaction_prepare, .transaction_finish = reftable_be_transaction_finish, .transaction_abort = reftable_be_transaction_abort, diff --git a/remote.c b/remote.c index ec8c158e60..85c390b199 100644 --- a/remote.c +++ b/remote.c @@ -305,7 +305,7 @@ static void read_remotes_file(struct remote_state *remote_state, static void read_branches_file(struct remote_state *remote_state, struct remote *remote) { - char *frag; + char *frag, *to_free = NULL; struct strbuf buf = STRBUF_INIT; FILE *f = fopen_or_warn(git_path("branches/%s", remote->name), "r"); @@ -333,7 +333,7 @@ static void read_branches_file(struct remote_state *remote_state, if (frag) *(frag++) = '\0'; else - frag = (char *)git_default_branch_name(0); + frag = to_free = repo_default_branch_name(the_repository, 0); add_url_alias(remote_state, remote, strbuf_detach(&buf, NULL)); refspec_appendf(&remote->fetch, "refs/heads/%s:refs/heads/%s", @@ -345,6 +345,8 @@ static void read_branches_file(struct remote_state *remote_state, */ refspec_appendf(&remote->push, "HEAD:refs/heads/%s", frag); remote->fetch_tags = 1; /* always auto-follow */ + + free(to_free); } static int handle_config(const char *key, const char *value, @@ -2388,11 +2390,13 @@ struct ref *guess_remote_head(const struct ref *head, /* If a remote branch exists with the default branch name, let's use it. */ if (!all) { - char *ref = xstrfmt("refs/heads/%s", - git_default_branch_name(0)); + char *default_branch = repo_default_branch_name(the_repository, 0); + char *ref = xstrfmt("refs/heads/%s", default_branch); r = find_ref_by_name(refs, ref); free(ref); + free(default_branch); + if (r && oideq(&r->old_oid, &head->old_oid)) return copy_ref(r); diff --git a/replace-object.c b/replace-object.c index 523215589d..73f5acbcd9 100644 --- a/replace-object.c +++ b/replace-object.c @@ -8,12 +8,13 @@ #include "repository.h" #include "commit.h" -static int register_replace_ref(struct repository *r, - const char *refname, +static int register_replace_ref(const char *refname, const struct object_id *oid, int flag UNUSED, - void *cb_data UNUSED) + void *cb_data) { + struct repository *r = cb_data; + /* Get sha1 from refname */ const char *slash = strrchr(refname, '/'); const char *hash = slash ? slash + 1 : refname; @@ -50,7 +51,8 @@ void prepare_replace_object(struct repository *r) xmalloc(sizeof(*r->objects->replace_map)); oidmap_init(r->objects->replace_map, 0); - for_each_replace_ref(r, register_replace_ref, NULL); + refs_for_each_replace_ref(get_main_ref_store(r), + register_replace_ref, r); r->objects->replace_map_initialized = 1; pthread_mutex_unlock(&r->objects->replace_mutex); diff --git a/repository.c b/repository.c index e4192af986..9f3014b3b5 100644 --- a/repository.c +++ b/repository.c @@ -14,6 +14,7 @@ #include "sparse-index.h" #include "trace2.h" #include "promisor-remote.h" +#include "refs.h" /* The main repository */ static struct repository the_repo; @@ -269,6 +270,9 @@ static void repo_clear_path_cache(struct repo_path_cache *cache) void repo_clear(struct repository *repo) { + struct hashmap_iter iter; + struct strmap_entry *e; + FREE_AND_NULL(repo->gitdir); FREE_AND_NULL(repo->commondir); FREE_AND_NULL(repo->graft_file); @@ -309,6 +313,14 @@ void repo_clear(struct repository *repo) FREE_AND_NULL(repo->remote_state); } + strmap_for_each_entry(&repo->submodule_ref_stores, &iter, e) + ref_store_release(e->value); + strmap_clear(&repo->submodule_ref_stores, 1); + + strmap_for_each_entry(&repo->worktree_ref_stores, &iter, e) + ref_store_release(e->value); + strmap_clear(&repo->worktree_ref_stores, 1); + repo_clear_path_cache(&repo->cached_paths); } diff --git a/repository.h b/repository.h index 41ed22543a..4bd8969005 100644 --- a/repository.h +++ b/repository.h @@ -1,6 +1,8 @@ #ifndef REPOSITORY_H #define REPOSITORY_H +#include "strmap.h" + struct config_set; struct fsmonitor_settings; struct git_hash_algo; @@ -108,6 +110,18 @@ struct repository { */ struct ref_store *refs_private; + /* + * A strmap of ref_stores, stored by submodule name, accessible via + * `repo_get_submodule_ref_store()`. + */ + struct strmap submodule_ref_stores; + + /* + * A strmap of ref_stores, stored by worktree id, accessible via + * `get_worktree_ref_store()`. + */ + struct strmap worktree_ref_stores; + /* * Contains path to often used file names. */ diff --git a/setup.c b/setup.c index 9b721ea2a9..f00f6cf2b6 100644 --- a/setup.c +++ b/setup.c @@ -2099,10 +2099,11 @@ void create_reference_database(unsigned int ref_storage_format, const char *initial_branch, int quiet) { struct strbuf err = STRBUF_INIT; + char *to_free = NULL; int reinit = is_reinit(); repo_set_ref_storage_format(the_repository, ref_storage_format); - if (refs_init_db(get_main_ref_store(the_repository), 0, &err)) + if (ref_store_create_on_disk(get_main_ref_store(the_repository), 0, &err)) die("failed to set up refs db: %s", err.buf); /* @@ -2113,7 +2114,8 @@ void create_reference_database(unsigned int ref_storage_format, char *ref; if (!initial_branch) - initial_branch = git_default_branch_name(quiet); + initial_branch = to_free = + repo_default_branch_name(the_repository, quiet); ref = xstrfmt("refs/heads/%s", initial_branch); if (check_refname_format(ref, 0) < 0) @@ -2130,6 +2132,7 @@ void create_reference_database(unsigned int ref_storage_format, initial_branch); strbuf_release(&err); + free(to_free); } static int create_default_files(const char *template_path, diff --git a/submodule.c b/submodule.c index f6313cd99f..759cf1e1cd 100644 --- a/submodule.c +++ b/submodule.c @@ -99,7 +99,8 @@ int is_staging_gitmodules_ok(struct index_state *istate) static int for_each_remote_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data) { - return refs_for_each_remote_ref(get_submodule_ref_store(submodule), + return refs_for_each_remote_ref(repo_get_submodule_ref_store(the_repository, + submodule), fn, cb_data); } diff --git a/t/helper/test-reach.c b/t/helper/test-reach.c index 1e3b431e3e..1ba226f1f9 100644 --- a/t/helper/test-reach.c +++ b/t/helper/test-reach.c @@ -62,7 +62,7 @@ int cmd__reach(int ac, const char **av) die("failed to resolve %s", buf.buf + 2); orig = parse_object(r, &oid); - peeled = deref_tag_noverify(orig); + peeled = deref_tag_noverify(the_repository, orig); if (!peeled) die("failed to load commit for input %s resulting in oid %s\n", diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c index 4651e4ced7..c9efd74c2b 100644 --- a/t/helper/test-ref-store.c +++ b/t/helper/test-ref-store.c @@ -82,7 +82,7 @@ static const char **get_store(const char **argv, struct ref_store **refs) add_to_alternates_memory(sb.buf); strbuf_release(&sb); - *refs = get_submodule_ref_store(gitdir); + *refs = repo_get_submodule_ref_store(the_repository, gitdir); } else if (skip_prefix(argv[0], "worktree:", &gitdir)) { struct worktree **p, **worktrees = get_worktrees(); diff --git a/tag.c b/tag.c index fc3834db46..52bbe50819 100644 --- a/tag.c +++ b/tag.c @@ -91,10 +91,10 @@ struct object *deref_tag(struct repository *r, struct object *o, const char *war return o; } -struct object *deref_tag_noverify(struct object *o) +struct object *deref_tag_noverify(struct repository *r, struct object *o) { while (o && o->type == OBJ_TAG) { - o = parse_object(the_repository, &o->oid); + o = parse_object(r, &o->oid); if (o && o->type == OBJ_TAG && ((struct tag *)o)->tagged) o = ((struct tag *)o)->tagged; else diff --git a/tag.h b/tag.h index 3ce8e72192..c49d7c19ad 100644 --- a/tag.h +++ b/tag.h @@ -16,7 +16,7 @@ int parse_tag_buffer(struct repository *r, struct tag *item, const void *data, u int parse_tag(struct tag *item); void release_tag_memory(struct tag *t); struct object *deref_tag(struct repository *r, struct object *, const char *, int); -struct object *deref_tag_noverify(struct object *); +struct object *deref_tag_noverify(struct repository *r, struct object *); int gpg_verify_tag(const struct object_id *oid, const char *name_to_report, unsigned flags); struct object_id *get_tagged_oid(struct tag *tag); diff --git a/unpack-trees.c b/unpack-trees.c index c2b20b80d5..304ea2ed86 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -2318,7 +2318,8 @@ static int verify_clean_subdirectory(const struct cache_entry *ce, if (S_ISGITLINK(ce->ce_mode)) { struct object_id oid; - int sub_head = resolve_gitlink_ref(ce->name, "HEAD", &oid); + int sub_head = repo_resolve_gitlink_ref(the_repository, ce->name, + "HEAD", &oid); /* * If we are not going to update the submodule, then * we don't care. diff --git a/upload-pack.c b/upload-pack.c index 8fbd138515..bbfb04c8bd 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -1269,7 +1269,7 @@ static void write_v0_ref(struct upload_pack_data *data, packet_fwrite_fmt(stdout, "%s %s\n", oid_to_hex(oid), refname_nons); } capabilities = NULL; - if (!peel_iterated_oid(oid, &peeled)) + if (!peel_iterated_oid(the_repository, oid, &peeled)) packet_fwrite_fmt(stdout, "%s %s^{}\n", oid_to_hex(&peeled), refname_nons); return; } diff --git a/worktree.c b/worktree.c index cf5eea8c93..12eadacc61 100644 --- a/worktree.c +++ b/worktree.c @@ -65,6 +65,7 @@ static struct worktree *get_main_worktree(int skip_reading_head) strbuf_strip_suffix(&worktree_path, "/.git"); CALLOC_ARRAY(worktree, 1); + worktree->repo = the_repository; worktree->path = strbuf_detach(&worktree_path, NULL); /* * NEEDSWORK: If this function is called from a secondary worktree and @@ -98,6 +99,7 @@ struct worktree *get_linked_worktree(const char *id, strbuf_strip_suffix(&worktree_path, "/.git"); CALLOC_ARRAY(worktree, 1); + worktree->repo = the_repository; worktree->path = strbuf_detach(&worktree_path, NULL); worktree->id = xstrdup(id); if (!skip_reading_head) diff --git a/worktree.h b/worktree.h index f14784a2ff..7cc6d90e66 100644 --- a/worktree.h +++ b/worktree.h @@ -6,6 +6,8 @@ struct strbuf; struct worktree { + /* The repository this worktree belongs to. */ + struct repository *repo; char *path; char *id; char *head_ref; /* NULL if HEAD is broken or detached */