Merge branch 'jt/no-abuse-alternate-odb-for-submodules'

Follow through the work to use the repo interface to access
submodule objects in-process, instead of abusing the alternate
object database interface.

* jt/no-abuse-alternate-odb-for-submodules:
  submodule: trace adding submodule ODB as alternate
  submodule: pass repo to check_has_commit()
  object-file: only register submodule ODB if needed
  merge-{ort,recursive}: remove add_submodule_odb()
  refs: peeling non-the_repository iterators is BUG
  refs: teach arbitrary repo support to iterators
  refs: plumb repo into ref stores
This commit is contained in:
Junio C Hamano 2021-10-25 16:06:56 -07:00
commit 162a13b855
20 changed files with 148 additions and 68 deletions

View File

@ -609,6 +609,7 @@ static int err(struct merge_options *opt, const char *err, ...)
static void format_commit(struct strbuf *sb, static void format_commit(struct strbuf *sb,
int indent, int indent,
struct repository *repo,
struct commit *commit) struct commit *commit)
{ {
struct merge_remote_desc *desc; struct merge_remote_desc *desc;
@ -622,7 +623,7 @@ static void format_commit(struct strbuf *sb,
return; return;
} }
format_commit_message(commit, "%h %s", sb, &ctx); repo_format_commit_message(repo, commit, "%h %s", sb, &ctx);
strbuf_addch(sb, '\n'); strbuf_addch(sb, '\n');
} }
@ -1578,17 +1579,6 @@ static int merge_submodule(struct merge_options *opt,
if (is_null_oid(b)) if (is_null_oid(b))
return 0; return 0;
/*
* NEEDSWORK: Remove this when all submodule object accesses are
* through explicitly specified repositores.
*/
if (add_submodule_odb(path)) {
path_msg(opt, path, 0,
_("Failed to merge submodule %s (not checked out)"),
path);
return 0;
}
if (repo_submodule_init(&subrepo, opt->repo, path, null_oid())) { if (repo_submodule_init(&subrepo, opt->repo, path, null_oid())) {
path_msg(opt, path, 0, path_msg(opt, path, 0,
_("Failed to merge submodule %s (not checked out)"), _("Failed to merge submodule %s (not checked out)"),
@ -1653,7 +1643,7 @@ static int merge_submodule(struct merge_options *opt,
break; break;
case 1: case 1:
format_commit(&sb, 4, format_commit(&sb, 4, &subrepo,
(struct commit *)merges.objects[0].item); (struct commit *)merges.objects[0].item);
path_msg(opt, path, 0, path_msg(opt, path, 0,
_("Failed to merge submodule %s, but a possible merge " _("Failed to merge submodule %s, but a possible merge "
@ -1670,7 +1660,7 @@ static int merge_submodule(struct merge_options *opt,
break; break;
default: default:
for (i = 0; i < merges.nr; i++) for (i = 0; i < merges.nr; i++)
format_commit(&sb, 4, format_commit(&sb, 4, &subrepo,
(struct commit *)merges.objects[i].item); (struct commit *)merges.objects[i].item);
path_msg(opt, path, 0, path_msg(opt, path, 0,
_("Failed to merge submodule %s, but multiple " _("Failed to merge submodule %s, but multiple "

View File

@ -334,7 +334,9 @@ static void output(struct merge_options *opt, int v, const char *fmt, ...)
flush_output(opt); flush_output(opt);
} }
static void output_commit_title(struct merge_options *opt, struct commit *commit) static void repo_output_commit_title(struct merge_options *opt,
struct repository *repo,
struct commit *commit)
{ {
struct merge_remote_desc *desc; struct merge_remote_desc *desc;
@ -343,23 +345,29 @@ static void output_commit_title(struct merge_options *opt, struct commit *commit
if (desc) if (desc)
strbuf_addf(&opt->obuf, "virtual %s\n", desc->name); strbuf_addf(&opt->obuf, "virtual %s\n", desc->name);
else { else {
strbuf_add_unique_abbrev(&opt->obuf, &commit->object.oid, strbuf_repo_add_unique_abbrev(&opt->obuf, repo,
&commit->object.oid,
DEFAULT_ABBREV); DEFAULT_ABBREV);
strbuf_addch(&opt->obuf, ' '); strbuf_addch(&opt->obuf, ' ');
if (parse_commit(commit) != 0) if (repo_parse_commit(repo, commit) != 0)
strbuf_addstr(&opt->obuf, _("(bad commit)\n")); strbuf_addstr(&opt->obuf, _("(bad commit)\n"));
else { else {
const char *title; const char *title;
const char *msg = get_commit_buffer(commit, NULL); const char *msg = repo_get_commit_buffer(repo, commit, NULL);
int len = find_commit_subject(msg, &title); int len = find_commit_subject(msg, &title);
if (len) if (len)
strbuf_addf(&opt->obuf, "%.*s\n", len, title); strbuf_addf(&opt->obuf, "%.*s\n", len, title);
unuse_commit_buffer(commit, msg); repo_unuse_commit_buffer(repo, commit, msg);
} }
} }
flush_output(opt); flush_output(opt);
} }
static void output_commit_title(struct merge_options *opt, struct commit *commit)
{
repo_output_commit_title(opt, the_repository, commit);
}
static int add_cacheinfo(struct merge_options *opt, static int add_cacheinfo(struct merge_options *opt,
const struct diff_filespec *blob, const struct diff_filespec *blob,
const char *path, int stage, int refresh, int options) const char *path, int stage, int refresh, int options)
@ -1152,14 +1160,14 @@ static int find_first_merges(struct repository *repo,
return result->nr; return result->nr;
} }
static void print_commit(struct commit *commit) static void print_commit(struct repository *repo, struct commit *commit)
{ {
struct strbuf sb = STRBUF_INIT; struct strbuf sb = STRBUF_INIT;
struct pretty_print_context ctx = {0}; struct pretty_print_context ctx = {0};
ctx.date_mode.type = DATE_NORMAL; ctx.date_mode.type = DATE_NORMAL;
/* FIXME: Merge this with output_commit_title() */ /* FIXME: Merge this with output_commit_title() */
assert(!merge_remote_util(commit)); assert(!merge_remote_util(commit));
format_commit_message(commit, " %h: %m %s", &sb, &ctx); repo_format_commit_message(repo, commit, " %h: %m %s", &sb, &ctx);
fprintf(stderr, "%s\n", sb.buf); fprintf(stderr, "%s\n", sb.buf);
strbuf_release(&sb); strbuf_release(&sb);
} }
@ -1199,15 +1207,6 @@ static int merge_submodule(struct merge_options *opt,
if (is_null_oid(b)) if (is_null_oid(b))
return 0; return 0;
/*
* NEEDSWORK: Remove this when all submodule object accesses are
* through explicitly specified repositores.
*/
if (add_submodule_odb(path)) {
output(opt, 1, _("Failed to merge submodule %s (not checked out)"), path);
return 0;
}
if (repo_submodule_init(&subrepo, opt->repo, path, null_oid())) { if (repo_submodule_init(&subrepo, opt->repo, path, null_oid())) {
output(opt, 1, _("Failed to merge submodule %s (not checked out)"), path); output(opt, 1, _("Failed to merge submodule %s (not checked out)"), path);
return 0; return 0;
@ -1232,7 +1231,7 @@ static int merge_submodule(struct merge_options *opt,
oidcpy(result, b); oidcpy(result, b);
if (show(opt, 3)) { if (show(opt, 3)) {
output(opt, 3, _("Fast-forwarding submodule %s to the following commit:"), path); output(opt, 3, _("Fast-forwarding submodule %s to the following commit:"), path);
output_commit_title(opt, commit_b); repo_output_commit_title(opt, &subrepo, commit_b);
} else if (show(opt, 2)) } else if (show(opt, 2))
output(opt, 2, _("Fast-forwarding submodule %s"), path); output(opt, 2, _("Fast-forwarding submodule %s"), path);
else else
@ -1245,7 +1244,7 @@ static int merge_submodule(struct merge_options *opt,
oidcpy(result, a); oidcpy(result, a);
if (show(opt, 3)) { if (show(opt, 3)) {
output(opt, 3, _("Fast-forwarding submodule %s to the following commit:"), path); output(opt, 3, _("Fast-forwarding submodule %s to the following commit:"), path);
output_commit_title(opt, commit_a); repo_output_commit_title(opt, &subrepo, commit_a);
} else if (show(opt, 2)) } else if (show(opt, 2))
output(opt, 2, _("Fast-forwarding submodule %s"), path); output(opt, 2, _("Fast-forwarding submodule %s"), path);
else else
@ -1277,7 +1276,7 @@ static int merge_submodule(struct merge_options *opt,
case 1: case 1:
output(opt, 1, _("Failed to merge submodule %s (not fast-forward)"), path); output(opt, 1, _("Failed to merge submodule %s (not fast-forward)"), path);
output(opt, 2, _("Found a possible merge resolution for the submodule:\n")); output(opt, 2, _("Found a possible merge resolution for the submodule:\n"));
print_commit((struct commit *) merges.objects[0].item); print_commit(&subrepo, (struct commit *) merges.objects[0].item);
output(opt, 2, _( output(opt, 2, _(
"If this is correct simply add it to the index " "If this is correct simply add it to the index "
"for example\n" "for example\n"
@ -1290,7 +1289,7 @@ static int merge_submodule(struct merge_options *opt,
default: default:
output(opt, 1, _("Failed to merge submodule %s (multiple merges found)"), path); output(opt, 1, _("Failed to merge submodule %s (multiple merges found)"), path);
for (i = 0; i < merges.nr; i++) for (i = 0; i < merges.nr; i++)
print_commit((struct commit *) merges.objects[i].item); print_commit(&subrepo, (struct commit *) merges.objects[i].item);
} }
object_array_clear(&merges); object_array_clear(&merges);

View File

@ -1528,7 +1528,14 @@ static int do_oid_object_info_extended(struct repository *r,
break; break;
} }
if (register_all_submodule_odb_as_alternates()) /*
* If r is the_repository, this might be an attempt at
* accessing a submodule object as if it were in the_repository
* (having called add_submodule_odb() on that submodule's ODB).
* If any such ODBs exist, register them and try again.
*/
if (r == the_repository &&
register_all_submodule_odb_as_alternates())
/* We added some alternates; retry */ /* We added some alternates; retry */
continue; continue;

32
refs.c
View File

@ -251,12 +251,13 @@ int refname_is_safe(const char *refname)
* does not exist, emit a warning and return false. * does not exist, emit a warning and return false.
*/ */
int ref_resolves_to_object(const char *refname, int ref_resolves_to_object(const char *refname,
struct repository *repo,
const struct object_id *oid, const struct object_id *oid,
unsigned int flags) unsigned int flags)
{ {
if (flags & REF_ISBROKEN) if (flags & REF_ISBROKEN)
return 0; return 0;
if (!has_object_file(oid)) { if (!repo_has_object_file(repo, oid)) {
error(_("%s does not point to a valid object!"), refname); error(_("%s does not point to a valid object!"), refname);
return 0; return 0;
} }
@ -1870,7 +1871,8 @@ static struct ref_store *lookup_ref_store_map(struct hashmap *map,
* Create, record, and return a ref_store instance for the specified * Create, record, and return a ref_store instance for the specified
* gitdir. * gitdir.
*/ */
static struct ref_store *ref_store_init(const char *gitdir, static struct ref_store *ref_store_init(struct repository *repo,
const char *gitdir,
unsigned int flags) unsigned int flags)
{ {
const char *be_name = "files"; const char *be_name = "files";
@ -1880,7 +1882,7 @@ static struct ref_store *ref_store_init(const char *gitdir,
if (!be) if (!be)
BUG("reference backend %s is unknown", be_name); BUG("reference backend %s is unknown", be_name);
refs = be->init(gitdir, flags); refs = be->init(repo, gitdir, flags);
return refs; return refs;
} }
@ -1892,7 +1894,7 @@ struct ref_store *get_main_ref_store(struct repository *r)
if (!r->gitdir) if (!r->gitdir)
BUG("attempting to get main_ref_store outside of repository"); BUG("attempting to get main_ref_store outside of repository");
r->refs_private = ref_store_init(r->gitdir, REF_STORE_ALL_CAPS); r->refs_private = ref_store_init(r, r->gitdir, REF_STORE_ALL_CAPS);
r->refs_private = maybe_debug_wrap_ref_store(r->gitdir, r->refs_private); r->refs_private = maybe_debug_wrap_ref_store(r->gitdir, r->refs_private);
return r->refs_private; return r->refs_private;
} }
@ -1922,6 +1924,7 @@ struct ref_store *get_submodule_ref_store(const char *submodule)
struct ref_store *refs; struct ref_store *refs;
char *to_free = NULL; char *to_free = NULL;
size_t len; size_t len;
struct repository *subrepo;
if (!submodule) if (!submodule)
return NULL; return NULL;
@ -1947,8 +1950,19 @@ struct ref_store *get_submodule_ref_store(const char *submodule)
if (submodule_to_gitdir(&submodule_sb, submodule)) if (submodule_to_gitdir(&submodule_sb, submodule))
goto done; goto done;
/* assume that add_submodule_odb() has been called */ subrepo = xmalloc(sizeof(*subrepo));
refs = ref_store_init(submodule_sb.buf, /*
* 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,
null_oid())) {
free(subrepo);
goto done;
}
refs = ref_store_init(subrepo, submodule_sb.buf,
REF_STORE_READ | REF_STORE_ODB); REF_STORE_READ | REF_STORE_ODB);
register_ref_store_map(&submodule_ref_stores, "submodule", register_ref_store_map(&submodule_ref_stores, "submodule",
refs, submodule); refs, submodule);
@ -1974,10 +1988,12 @@ struct ref_store *get_worktree_ref_store(const struct worktree *wt)
return refs; return refs;
if (wt->id) if (wt->id)
refs = ref_store_init(git_common_path("worktrees/%s", wt->id), refs = ref_store_init(the_repository,
git_common_path("worktrees/%s", wt->id),
REF_STORE_ALL_CAPS); REF_STORE_ALL_CAPS);
else else
refs = ref_store_init(get_git_common_dir(), refs = ref_store_init(the_repository,
get_git_common_dir(),
REF_STORE_ALL_CAPS); REF_STORE_ALL_CAPS);
if (refs) if (refs)

View File

@ -79,13 +79,15 @@ static void clear_loose_ref_cache(struct files_ref_store *refs)
* Create a new submodule ref cache and add it to the internal * Create a new submodule ref cache and add it to the internal
* set of caches. * set of caches.
*/ */
static struct ref_store *files_ref_store_create(const char *gitdir, static struct ref_store *files_ref_store_create(struct repository *repo,
const char *gitdir,
unsigned int flags) unsigned int flags)
{ {
struct files_ref_store *refs = xcalloc(1, sizeof(*refs)); struct files_ref_store *refs = xcalloc(1, sizeof(*refs));
struct ref_store *ref_store = (struct ref_store *)refs; struct ref_store *ref_store = (struct ref_store *)refs;
struct strbuf sb = STRBUF_INIT; struct strbuf sb = STRBUF_INIT;
ref_store->repo = repo;
ref_store->gitdir = xstrdup(gitdir); ref_store->gitdir = xstrdup(gitdir);
base_ref_store_init(ref_store, &refs_be_files); base_ref_store_init(ref_store, &refs_be_files);
refs->store_flags = flags; refs->store_flags = flags;
@ -93,7 +95,7 @@ static struct ref_store *files_ref_store_create(const char *gitdir,
get_common_dir_noenv(&sb, gitdir); get_common_dir_noenv(&sb, gitdir);
refs->gitcommondir = strbuf_detach(&sb, NULL); refs->gitcommondir = strbuf_detach(&sb, NULL);
strbuf_addf(&sb, "%s/packed-refs", refs->gitcommondir); strbuf_addf(&sb, "%s/packed-refs", refs->gitcommondir);
refs->packed_ref_store = packed_ref_store_create(sb.buf, flags); refs->packed_ref_store = packed_ref_store_create(repo, sb.buf, flags);
strbuf_release(&sb); strbuf_release(&sb);
chdir_notify_reparent("files-backend $GIT_DIR", &refs->base.gitdir); chdir_notify_reparent("files-backend $GIT_DIR", &refs->base.gitdir);
@ -730,6 +732,7 @@ struct files_ref_iterator {
struct ref_iterator base; struct ref_iterator base;
struct ref_iterator *iter0; struct ref_iterator *iter0;
struct repository *repo;
unsigned int flags; unsigned int flags;
}; };
@ -751,6 +754,7 @@ static int files_ref_iterator_advance(struct ref_iterator *ref_iterator)
if (!(iter->flags & DO_FOR_EACH_INCLUDE_BROKEN) && if (!(iter->flags & DO_FOR_EACH_INCLUDE_BROKEN) &&
!ref_resolves_to_object(iter->iter0->refname, !ref_resolves_to_object(iter->iter0->refname,
iter->repo,
iter->iter0->oid, iter->iter0->oid,
iter->iter0->flags)) iter->iter0->flags))
continue; continue;
@ -829,7 +833,7 @@ static struct ref_iterator *files_ref_iterator_begin(
*/ */
loose_iter = cache_ref_iterator_begin(get_loose_ref_cache(refs), loose_iter = cache_ref_iterator_begin(get_loose_ref_cache(refs),
prefix, 1); prefix, ref_store->repo, 1);
/* /*
* The packed-refs file might contain broken references, for * The packed-refs file might contain broken references, for
@ -853,6 +857,7 @@ static struct ref_iterator *files_ref_iterator_begin(
base_ref_iterator_init(ref_iterator, &files_ref_iterator_vtable, base_ref_iterator_init(ref_iterator, &files_ref_iterator_vtable,
overlay_iter->ordered); overlay_iter->ordered);
iter->iter0 = overlay_iter; iter->iter0 = overlay_iter;
iter->repo = ref_store->repo;
iter->flags = flags; iter->flags = flags;
return ref_iterator; return ref_iterator;
@ -1169,7 +1174,7 @@ static int should_pack_ref(const char *refname,
return 0; return 0;
/* Do not pack broken refs: */ /* Do not pack broken refs: */
if (!ref_resolves_to_object(refname, oid, ref_flags)) if (!ref_resolves_to_object(refname, the_repository, oid, ref_flags))
return 0; return 0;
return 1; return 1;
@ -1192,7 +1197,8 @@ static int files_pack_refs(struct ref_store *ref_store, unsigned int flags)
packed_refs_lock(refs->packed_ref_store, LOCK_DIE_ON_ERROR, &err); packed_refs_lock(refs->packed_ref_store, LOCK_DIE_ON_ERROR, &err);
iter = cache_ref_iterator_begin(get_loose_ref_cache(refs), NULL, 0); iter = cache_ref_iterator_begin(get_loose_ref_cache(refs), NULL,
the_repository, 0);
while ((ok = ref_iterator_advance(iter)) == ITER_OK) { while ((ok = ref_iterator_advance(iter)) == ITER_OK) {
/* /*
* If the loose reference can be packed, add an entry * If the loose reference can be packed, add an entry

View File

@ -193,13 +193,15 @@ static int release_snapshot(struct snapshot *snapshot)
} }
} }
struct ref_store *packed_ref_store_create(const char *path, struct ref_store *packed_ref_store_create(struct repository *repo,
const char *path,
unsigned int store_flags) unsigned int store_flags)
{ {
struct packed_ref_store *refs = xcalloc(1, sizeof(*refs)); struct packed_ref_store *refs = xcalloc(1, sizeof(*refs));
struct ref_store *ref_store = (struct ref_store *)refs; struct ref_store *ref_store = (struct ref_store *)refs;
base_ref_store_init(ref_store, &refs_be_packed); base_ref_store_init(ref_store, &refs_be_packed);
ref_store->repo = repo;
ref_store->gitdir = xstrdup(path); ref_store->gitdir = xstrdup(path);
refs->store_flags = store_flags; refs->store_flags = store_flags;
@ -776,6 +778,7 @@ struct packed_ref_iterator {
struct object_id oid, peeled; struct object_id oid, peeled;
struct strbuf refname_buf; struct strbuf refname_buf;
struct repository *repo;
unsigned int flags; unsigned int flags;
}; };
@ -864,8 +867,8 @@ static int packed_ref_iterator_advance(struct ref_iterator *ref_iterator)
continue; continue;
if (!(iter->flags & DO_FOR_EACH_INCLUDE_BROKEN) && if (!(iter->flags & DO_FOR_EACH_INCLUDE_BROKEN) &&
!ref_resolves_to_object(iter->base.refname, &iter->oid, !ref_resolves_to_object(iter->base.refname, iter->repo,
iter->flags)) &iter->oid, iter->flags))
continue; continue;
return ITER_OK; return ITER_OK;
@ -883,6 +886,9 @@ static int packed_ref_iterator_peel(struct ref_iterator *ref_iterator,
struct packed_ref_iterator *iter = struct packed_ref_iterator *iter =
(struct packed_ref_iterator *)ref_iterator; (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)) { if ((iter->base.flags & REF_KNOWS_PEELED)) {
oidcpy(peeled, &iter->peeled); oidcpy(peeled, &iter->peeled);
return is_null_oid(&iter->peeled) ? -1 : 0; return is_null_oid(&iter->peeled) ? -1 : 0;
@ -954,6 +960,7 @@ static struct ref_iterator *packed_ref_iterator_begin(
iter->base.oid = &iter->oid; iter->base.oid = &iter->oid;
iter->repo = ref_store->repo;
iter->flags = flags; iter->flags = flags;
if (prefix && *prefix) if (prefix && *prefix)

View File

@ -1,6 +1,7 @@
#ifndef REFS_PACKED_BACKEND_H #ifndef REFS_PACKED_BACKEND_H
#define REFS_PACKED_BACKEND_H #define REFS_PACKED_BACKEND_H
struct repository;
struct ref_transaction; struct ref_transaction;
/* /*
@ -12,7 +13,8 @@ struct ref_transaction;
* even among packed refs. * even among packed refs.
*/ */
struct ref_store *packed_ref_store_create(const char *path, struct ref_store *packed_ref_store_create(struct repository *repo,
const char *path,
unsigned int store_flags); unsigned int store_flags);
/* /*

View File

@ -378,6 +378,8 @@ struct cache_ref_iterator {
* on from there.) * on from there.)
*/ */
struct cache_ref_iterator_level *levels; struct cache_ref_iterator_level *levels;
struct repository *repo;
}; };
static int cache_ref_iterator_advance(struct ref_iterator *ref_iterator) static int cache_ref_iterator_advance(struct ref_iterator *ref_iterator)
@ -434,6 +436,11 @@ static int cache_ref_iterator_advance(struct ref_iterator *ref_iterator)
static int cache_ref_iterator_peel(struct ref_iterator *ref_iterator, static int cache_ref_iterator_peel(struct ref_iterator *ref_iterator,
struct object_id *peeled) struct object_id *peeled)
{ {
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(ref_iterator->oid, peeled) ? -1 : 0;
} }
@ -456,6 +463,7 @@ static struct ref_iterator_vtable cache_ref_iterator_vtable = {
struct ref_iterator *cache_ref_iterator_begin(struct ref_cache *cache, struct ref_iterator *cache_ref_iterator_begin(struct ref_cache *cache,
const char *prefix, const char *prefix,
struct repository *repo,
int prime_dir) int prime_dir)
{ {
struct ref_dir *dir; struct ref_dir *dir;
@ -490,5 +498,7 @@ struct ref_iterator *cache_ref_iterator_begin(struct ref_cache *cache,
level->prefix_state = PREFIX_CONTAINS_DIR; level->prefix_state = PREFIX_CONTAINS_DIR;
} }
iter->repo = repo;
return ref_iterator; return ref_iterator;
} }

View File

@ -214,6 +214,7 @@ struct ref_entry *find_ref_entry(struct ref_dir *dir, const char *refname);
*/ */
struct ref_iterator *cache_ref_iterator_begin(struct ref_cache *cache, struct ref_iterator *cache_ref_iterator_begin(struct ref_cache *cache,
const char *prefix, const char *prefix,
struct repository *repo,
int prime_dir); int prime_dir);
#endif /* REFS_REF_CACHE_H */ #endif /* REFS_REF_CACHE_H */

View File

@ -66,6 +66,7 @@ int refname_is_safe(const char *refname);
* referred-to object does not exist, emit a warning and return false. * referred-to object does not exist, emit a warning and return false.
*/ */
int ref_resolves_to_object(const char *refname, int ref_resolves_to_object(const char *refname,
struct repository *repo,
const struct object_id *oid, const struct object_id *oid,
unsigned int flags); unsigned int flags);
@ -539,7 +540,8 @@ struct ref_store;
* should call base_ref_store_init() to initialize the shared part of * should call base_ref_store_init() to initialize the shared part of
* the ref_store and to record the ref_store for later lookup. * the ref_store and to record the ref_store for later lookup.
*/ */
typedef struct ref_store *ref_store_init_fn(const char *gitdir, typedef struct ref_store *ref_store_init_fn(struct repository *repo,
const char *gitdir,
unsigned int flags); unsigned int flags);
typedef int ref_init_db_fn(struct ref_store *refs, struct strbuf *err); typedef int ref_init_db_fn(struct ref_store *refs, struct strbuf *err);
@ -701,7 +703,12 @@ struct ref_store {
/* The backend describing this ref_store's storage scheme: */ /* The backend describing this ref_store's storage scheme: */
const struct ref_storage_be *be; const struct ref_storage_be *be;
/* The gitdir that this ref_store applies to: */ struct repository *repo;
/*
* The gitdir that this ref_store applies to. Note that this is not
* necessarily repo->gitdir if the repo has multiple worktrees.
*/
char *gitdir; char *gitdir;
}; };

View File

@ -1059,15 +1059,21 @@ void strbuf_addftime(struct strbuf *sb, const char *fmt, const struct tm *tm,
strbuf_setlen(sb, sb->len + len); strbuf_setlen(sb, sb->len + len);
} }
void strbuf_add_unique_abbrev(struct strbuf *sb, const struct object_id *oid, void strbuf_repo_add_unique_abbrev(struct strbuf *sb, struct repository *repo,
int abbrev_len) const struct object_id *oid, int abbrev_len)
{ {
int r; int r;
strbuf_grow(sb, GIT_MAX_HEXSZ + 1); strbuf_grow(sb, GIT_MAX_HEXSZ + 1);
r = find_unique_abbrev_r(sb->buf + sb->len, oid, abbrev_len); r = repo_find_unique_abbrev_r(repo, sb->buf + sb->len, oid, abbrev_len);
strbuf_setlen(sb, sb->len + r); strbuf_setlen(sb, sb->len + r);
} }
void strbuf_add_unique_abbrev(struct strbuf *sb, const struct object_id *oid,
int abbrev_len)
{
strbuf_repo_add_unique_abbrev(sb, the_repository, oid, abbrev_len);
}
/* /*
* Returns the length of a line, without trailing spaces. * Returns the length of a line, without trailing spaces.
* *

View File

@ -634,8 +634,10 @@ void strbuf_list_free(struct strbuf **list);
* Add the abbreviation, as generated by find_unique_abbrev, of `sha1` to * Add the abbreviation, as generated by find_unique_abbrev, of `sha1` to
* the strbuf `sb`. * the strbuf `sb`.
*/ */
void strbuf_add_unique_abbrev(struct strbuf *sb, struct repository;
const struct object_id *oid, void strbuf_repo_add_unique_abbrev(struct strbuf *sb, struct repository *repo,
const struct object_id *oid, int abbrev_len);
void strbuf_add_unique_abbrev(struct strbuf *sb, const struct object_id *oid,
int abbrev_len); int abbrev_len);
/** /**

View File

@ -201,6 +201,8 @@ int register_all_submodule_odb_as_alternates(void)
add_to_alternates_memory(added_submodule_odb_paths.items[i].string); add_to_alternates_memory(added_submodule_odb_paths.items[i].string);
if (ret) { if (ret) {
string_list_clear(&added_submodule_odb_paths, 0); string_list_clear(&added_submodule_odb_paths, 0);
trace2_data_intmax("submodule", the_repository,
"register_all_submodule_odb_as_alternates/registered", ret);
if (git_env_bool("GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB", 0)) if (git_env_bool("GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB", 0))
BUG("register_all_submodule_odb_as_alternates() called"); BUG("register_all_submodule_odb_as_alternates() called");
} }
@ -928,23 +930,33 @@ struct has_commit_data {
static int check_has_commit(const struct object_id *oid, void *data) static int check_has_commit(const struct object_id *oid, void *data)
{ {
struct has_commit_data *cb = data; struct has_commit_data *cb = data;
struct repository subrepo;
enum object_type type;
enum object_type type = oid_object_info(cb->repo, oid, NULL); if (repo_submodule_init(&subrepo, cb->repo, cb->path, null_oid())) {
cb->result = 0;
goto cleanup;
}
type = oid_object_info(&subrepo, oid, NULL);
switch (type) { switch (type) {
case OBJ_COMMIT: case OBJ_COMMIT:
return 0; goto cleanup;
case OBJ_BAD: case OBJ_BAD:
/* /*
* Object is missing or invalid. If invalid, an error message * Object is missing or invalid. If invalid, an error message
* has already been printed. * has already been printed.
*/ */
cb->result = 0; cb->result = 0;
return 0; goto cleanup;
default: default:
die(_("submodule entry '%s' (%s) is a %s, not a commit"), die(_("submodule entry '%s' (%s) is a %s, not a commit"),
cb->path, oid_to_hex(oid), type_name(type)); cb->path, oid_to_hex(oid), type_name(type));
} }
cleanup:
repo_clear(&subrepo);
return 0;
} }
static int submodule_has_commits(struct repository *r, static int submodule_has_commits(struct repository *r,

View File

@ -463,11 +463,8 @@ GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB=<boolean>, when true, makes
registering submodule ODBs as alternates a fatal action. Support for registering submodule ODBs as alternates a fatal action. Support for
this environment variable can be removed once the migration to this environment variable can be removed once the migration to
explicitly providing repositories when accessing submodule objects is explicitly providing repositories when accessing submodule objects is
complete (in which case we might want to replace this with a trace2 complete or needs to be abandoned for whatever reason (in which case the
call so that users can make it visible if accessing submodule objects migrated codepaths still retain their performance benefits).
without an explicit repository still happens) or needs to be abandoned
for whatever reason (in which case the migrated codepaths still retain
their performance benefits).
Naming Tests Naming Tests
------------ ------------

View File

@ -6,6 +6,9 @@ test_description='Recursive "git fetch" for submodules'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB=1
export GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB
. ./test-lib.sh . ./test-lib.sh
pwd=$(pwd) pwd=$(pwd)

View File

@ -5,6 +5,9 @@ test_description='test push with submodules'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB=1
export GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB
. ./test-lib.sh . ./test-lib.sh
test_expect_success setup ' test_expect_success setup '

View File

@ -5,6 +5,9 @@ test_description='pushing to a repository using push options'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB=1
export GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB
. ./test-lib.sh . ./test-lib.sh
mk_repo_pair () { mk_repo_pair () {

View File

@ -2,6 +2,9 @@
test_description='pull can handle submodules' test_description='pull can handle submodules'
GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB=1
export GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB
. ./test-lib.sh . ./test-lib.sh
. "$TEST_DIRECTORY"/lib-submodule-update.sh . "$TEST_DIRECTORY"/lib-submodule-update.sh

View File

@ -5,6 +5,9 @@ test_description='merging with submodules'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB=1
export GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB
. ./test-lib.sh . ./test-lib.sh
. "$TEST_DIRECTORY"/lib-merge.sh . "$TEST_DIRECTORY"/lib-merge.sh

View File

@ -12,6 +12,9 @@ The test setup uses a sparse checkout, however the same scenario can be set up
also by committing .gitmodules and then just removing it from the filesystem. also by committing .gitmodules and then just removing it from the filesystem.
' '
GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB=1
export GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB
. ./test-lib.sh . ./test-lib.sh
test_expect_success 'sparse checkout setup which hides .gitmodules' ' test_expect_success 'sparse checkout setup which hides .gitmodules' '