Merge branch 'jt/add-submodule-odb-clean-up' into jt/no-abuse-alternate-odb-for-submodules

* jt/add-submodule-odb-clean-up:
  revision: remove "submodule" from opt struct
  repository: support unabsorbed in repo_submodule_init
  submodule: remove unnecessary unabsorbed fallback
This commit is contained in:
Junio C Hamano 2021-09-22 17:11:09 -07:00
commit 6295f87b5f
11 changed files with 103 additions and 98 deletions

View File

@ -433,17 +433,14 @@ static int grep_submodule(struct grep_opt *opt,
{
struct repository *subrepo;
struct repository *superproject = opt->repo;
const struct submodule *sub;
struct grep_opt subopt;
int hit = 0;
sub = submodule_from_path(superproject, null_oid(), path);
if (!is_submodule_active(superproject, path))
return 0;
subrepo = xmalloc(sizeof(*subrepo));
if (repo_submodule_init(subrepo, superproject, sub)) {
if (repo_submodule_init(subrepo, superproject, path, null_oid())) {
free(subrepo);
return 0;
}

View File

@ -209,10 +209,8 @@ static void show_submodule(struct repository *superproject,
struct dir_struct *dir, const char *path)
{
struct repository subrepo;
const struct submodule *sub = submodule_from_path(superproject,
null_oid(), path);
if (repo_submodule_init(&subrepo, superproject, sub))
if (repo_submodule_init(&subrepo, superproject, path, null_oid()))
return;
if (repo_read_index(&subrepo) < 0)

View File

@ -2760,7 +2760,6 @@ static int push_check(int argc, const char **argv, const char *prefix)
static int ensure_core_worktree(int argc, const char **argv, const char *prefix)
{
const struct submodule *sub;
const char *path;
const char *cw;
struct repository subrepo;
@ -2770,11 +2769,7 @@ static int ensure_core_worktree(int argc, const char **argv, const char *prefix)
path = argv[1];
sub = submodule_from_path(the_repository, null_oid(), path);
if (!sub)
BUG("We could get the submodule handle before?");
if (repo_submodule_init(&subrepo, the_repository, sub))
if (repo_submodule_init(&subrepo, the_repository, path, null_oid()))
die(_("could not get a repository handle for submodule '%s'"), path);
if (!repo_config_get_string_tmp(&subrepo, "core.worktree", &cw)) {

View File

@ -32,6 +32,7 @@
#include "promisor-remote.h"
#include "revision.h"
#include "strmap.h"
#include "submodule-config.h"
#include "submodule.h"
#include "tree.h"
#include "unpack-trees.h"
@ -1511,7 +1512,6 @@ static int find_first_merges(struct repository *repo,
xsnprintf(merged_revision, sizeof(merged_revision), "^%s",
oid_to_hex(&a->object.oid));
repo_init_revisions(repo, &revs, NULL);
rev_opts.submodule = path;
/* FIXME: can't handle linked worktrees in submodules yet */
revs.single_worktree = path != NULL;
setup_revisions(ARRAY_SIZE(rev_args)-1, rev_args, &revs, &rev_opts);
@ -1521,7 +1521,7 @@ static int find_first_merges(struct repository *repo,
die("revision walk setup failed");
while ((commit = get_revision(&revs)) != NULL) {
struct object *o = &(commit->object);
if (in_merge_bases(b, commit))
if (repo_in_merge_bases(repo, b, commit))
add_object_array(o, NULL, &merges);
}
reset_revision_walk();
@ -1536,7 +1536,7 @@ static int find_first_merges(struct repository *repo,
contains_another = 0;
for (j = 0; j < merges.nr; j++) {
struct commit *m2 = (struct commit *) merges.objects[j].item;
if (i != j && in_merge_bases(m2, m1)) {
if (i != j && repo_in_merge_bases(repo, m2, m1)) {
contains_another = 1;
break;
}
@ -1557,10 +1557,12 @@ static int merge_submodule(struct merge_options *opt,
const struct object_id *b,
struct object_id *result)
{
struct repository subrepo;
struct strbuf sb = STRBUF_INIT;
int ret = 0;
struct commit *commit_o, *commit_a, *commit_b;
int parent_count;
struct object_array merges;
struct strbuf sb = STRBUF_INIT;
int i;
int search = !opt->priv->call_depth;
@ -1576,6 +1578,10 @@ static int merge_submodule(struct merge_options *opt,
if (is_null_oid(b))
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)"),
@ -1583,39 +1589,48 @@ static int merge_submodule(struct merge_options *opt,
return 0;
}
if (!(commit_o = lookup_commit_reference(opt->repo, o)) ||
!(commit_a = lookup_commit_reference(opt->repo, a)) ||
!(commit_b = lookup_commit_reference(opt->repo, b))) {
if (repo_submodule_init(&subrepo, opt->repo, path, null_oid())) {
path_msg(opt, path, 0,
_("Failed to merge submodule %s (commits not present)"),
_("Failed to merge submodule %s (not checked out)"),
path);
return 0;
}
if (!(commit_o = lookup_commit_reference(&subrepo, o)) ||
!(commit_a = lookup_commit_reference(&subrepo, a)) ||
!(commit_b = lookup_commit_reference(&subrepo, b))) {
path_msg(opt, path, 0,
_("Failed to merge submodule %s (commits not present)"),
path);
goto cleanup;
}
/* check whether both changes are forward */
if (!in_merge_bases(commit_o, commit_a) ||
!in_merge_bases(commit_o, commit_b)) {
if (!repo_in_merge_bases(&subrepo, commit_o, commit_a) ||
!repo_in_merge_bases(&subrepo, commit_o, commit_b)) {
path_msg(opt, path, 0,
_("Failed to merge submodule %s "
"(commits don't follow merge-base)"),
path);
return 0;
goto cleanup;
}
/* Case #1: a is contained in b or vice versa */
if (in_merge_bases(commit_a, commit_b)) {
if (repo_in_merge_bases(&subrepo, commit_a, commit_b)) {
oidcpy(result, b);
path_msg(opt, path, 1,
_("Note: Fast-forwarding submodule %s to %s"),
path, oid_to_hex(b));
return 1;
ret = 1;
goto cleanup;
}
if (in_merge_bases(commit_b, commit_a)) {
if (repo_in_merge_bases(&subrepo, commit_b, commit_a)) {
oidcpy(result, a);
path_msg(opt, path, 1,
_("Note: Fast-forwarding submodule %s to %s"),
path, oid_to_hex(a));
return 1;
ret = 1;
goto cleanup;
}
/*
@ -1627,10 +1642,10 @@ static int merge_submodule(struct merge_options *opt,
/* Skip the search if makes no sense to the calling context. */
if (!search)
return 0;
goto cleanup;
/* find commit which merges them */
parent_count = find_first_merges(opt->repo, path, commit_a, commit_b,
parent_count = find_first_merges(&subrepo, path, commit_a, commit_b,
&merges);
switch (parent_count) {
case 0:
@ -1664,7 +1679,9 @@ static int merge_submodule(struct merge_options *opt,
}
object_array_clear(&merges);
return 0;
cleanup:
repo_clear(&subrepo);
return ret;
}
static void initialize_attr_index(struct merge_options *opt)

View File

@ -24,6 +24,7 @@
#include "repository.h"
#include "revision.h"
#include "string-list.h"
#include "submodule-config.h"
#include "submodule.h"
#include "tag.h"
#include "tree-walk.h"
@ -1110,7 +1111,6 @@ static int find_first_merges(struct repository *repo,
xsnprintf(merged_revision, sizeof(merged_revision), "^%s",
oid_to_hex(&a->object.oid));
repo_init_revisions(repo, &revs, NULL);
rev_opts.submodule = path;
/* FIXME: can't handle linked worktrees in submodules yet */
revs.single_worktree = path != NULL;
setup_revisions(ARRAY_SIZE(rev_args)-1, rev_args, &revs, &rev_opts);
@ -1120,7 +1120,7 @@ static int find_first_merges(struct repository *repo,
die("revision walk setup failed");
while ((commit = get_revision(&revs)) != NULL) {
struct object *o = &(commit->object);
if (in_merge_bases(b, commit))
if (repo_in_merge_bases(repo, b, commit))
add_object_array(o, NULL, &merges);
}
reset_revision_walk();
@ -1135,7 +1135,7 @@ static int find_first_merges(struct repository *repo,
contains_another = 0;
for (j = 0; j < merges.nr; j++) {
struct commit *m2 = (struct commit *) merges.objects[j].item;
if (i != j && in_merge_bases(m2, m1)) {
if (i != j && repo_in_merge_bases(repo, m2, m1)) {
contains_another = 1;
break;
}
@ -1171,6 +1171,8 @@ static int merge_submodule(struct merge_options *opt,
const struct object_id *base, const struct object_id *a,
const struct object_id *b)
{
struct repository subrepo;
int ret = 0;
struct commit *commit_base, *commit_a, *commit_b;
int parent_count;
struct object_array merges;
@ -1194,27 +1196,36 @@ static int merge_submodule(struct merge_options *opt,
if (is_null_oid(b))
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 (!(commit_base = lookup_commit_reference(opt->repo, base)) ||
!(commit_a = lookup_commit_reference(opt->repo, a)) ||
!(commit_b = lookup_commit_reference(opt->repo, b))) {
output(opt, 1, _("Failed to merge submodule %s (commits not present)"), path);
if (repo_submodule_init(&subrepo, opt->repo, path, null_oid())) {
output(opt, 1, _("Failed to merge submodule %s (not checked out)"), path);
return 0;
}
if (!(commit_base = lookup_commit_reference(&subrepo, base)) ||
!(commit_a = lookup_commit_reference(&subrepo, a)) ||
!(commit_b = lookup_commit_reference(&subrepo, b))) {
output(opt, 1, _("Failed to merge submodule %s (commits not present)"), path);
goto cleanup;
}
/* check whether both changes are forward */
if (!in_merge_bases(commit_base, commit_a) ||
!in_merge_bases(commit_base, commit_b)) {
if (!repo_in_merge_bases(&subrepo, commit_base, commit_a) ||
!repo_in_merge_bases(&subrepo, commit_base, commit_b)) {
output(opt, 1, _("Failed to merge submodule %s (commits don't follow merge-base)"), path);
return 0;
goto cleanup;
}
/* Case #1: a is contained in b or vice versa */
if (in_merge_bases(commit_a, commit_b)) {
if (repo_in_merge_bases(&subrepo, commit_a, commit_b)) {
oidcpy(result, b);
if (show(opt, 3)) {
output(opt, 3, _("Fast-forwarding submodule %s to the following commit:"), path);
@ -1224,9 +1235,10 @@ static int merge_submodule(struct merge_options *opt,
else
; /* no output */
return 1;
ret = 1;
goto cleanup;
}
if (in_merge_bases(commit_b, commit_a)) {
if (repo_in_merge_bases(&subrepo, commit_b, commit_a)) {
oidcpy(result, a);
if (show(opt, 3)) {
output(opt, 3, _("Fast-forwarding submodule %s to the following commit:"), path);
@ -1236,7 +1248,8 @@ static int merge_submodule(struct merge_options *opt,
else
; /* no output */
return 1;
ret = 1;
goto cleanup;
}
/*
@ -1248,10 +1261,10 @@ static int merge_submodule(struct merge_options *opt,
/* Skip the search if makes no sense to the calling context. */
if (!search)
return 0;
goto cleanup;
/* find commit which merges them */
parent_count = find_first_merges(opt->repo, &merges, path,
parent_count = find_first_merges(&subrepo, &merges, path,
commit_a, commit_b);
switch (parent_count) {
case 0:
@ -1278,7 +1291,9 @@ static int merge_submodule(struct merge_options *opt,
}
object_array_clear(&merges);
return 0;
cleanup:
repo_clear(&subrepo);
return ret;
}
static int merge_mode_and_contents(struct merge_options *opt,

View File

@ -190,19 +190,15 @@ error:
int repo_submodule_init(struct repository *subrepo,
struct repository *superproject,
const struct submodule *sub)
const char *path,
const struct object_id *treeish_name)
{
struct strbuf gitdir = STRBUF_INIT;
struct strbuf worktree = STRBUF_INIT;
int ret = 0;
if (!sub) {
ret = -1;
goto out;
}
strbuf_repo_worktree_path(&gitdir, superproject, "%s/.git", sub->path);
strbuf_repo_worktree_path(&worktree, superproject, "%s", sub->path);
strbuf_repo_worktree_path(&gitdir, superproject, "%s/.git", path);
strbuf_repo_worktree_path(&worktree, superproject, "%s", path);
if (repo_init(subrepo, gitdir.buf, worktree.buf)) {
/*
@ -212,6 +208,13 @@ int repo_submodule_init(struct repository *subrepo,
* in the superproject's 'modules' directory. In this case the
* submodule would not have a worktree.
*/
const struct submodule *sub =
submodule_from_path(superproject, treeish_name, path);
if (!sub) {
ret = -1;
goto out;
}
strbuf_reset(&gitdir);
strbuf_repo_git_path(&gitdir, superproject,
"modules/%s", sub->name);
@ -225,7 +228,7 @@ int repo_submodule_init(struct repository *subrepo,
subrepo->submodule_prefix = xstrfmt("%s%s/",
superproject->submodule_prefix ?
superproject->submodule_prefix :
"", sub->path);
"", path);
out:
strbuf_release(&gitdir);

View File

@ -172,15 +172,18 @@ void initialize_the_repository(void);
int repo_init(struct repository *r, const char *gitdir, const char *worktree);
/*
* Initialize the repository 'subrepo' as the submodule given by the
* struct submodule 'sub' in parent repository 'superproject'.
* Return 0 upon success and a non-zero value upon failure, which may happen
* if the submodule is not found, or 'sub' is NULL.
* Initialize the repository 'subrepo' as the submodule at the given path. If
* the submodule's gitdir cannot be found at <path>/.git, this function calls
* submodule_from_path() to try to find it. treeish_name is only used if
* submodule_from_path() needs to be called; see its documentation for more
* information.
* Return 0 upon success and a non-zero value upon failure.
*/
struct submodule;
struct object_id;
int repo_submodule_init(struct repository *subrepo,
struct repository *superproject,
const struct submodule *sub);
const char *path,
const struct object_id *treeish_name);
void repo_clear(struct repository *repo);
/*

View File

@ -2563,8 +2563,7 @@ static int for_each_good_bisect_ref(struct ref_store *refs, each_ref_fn fn, void
return for_each_bisect_ref(refs, fn, cb_data, term_good);
}
static int handle_revision_pseudo_opt(const char *submodule,
struct rev_info *revs,
static int handle_revision_pseudo_opt(struct rev_info *revs,
const char **argv, int *flags)
{
const char *arg = argv[0];
@ -2572,7 +2571,7 @@ static int handle_revision_pseudo_opt(const char *submodule,
struct ref_store *refs;
int argcount;
if (submodule) {
if (revs->repo != the_repository) {
/*
* We need some something like get_submodule_worktrees()
* before we can go through all worktrees of a submodule,
@ -2581,8 +2580,7 @@ static int handle_revision_pseudo_opt(const char *submodule,
*/
if (!revs->single_worktree)
BUG("--single-worktree cannot be used together with submodule");
refs = get_submodule_ref_store(submodule);
} else
}
refs = get_main_ref_store(revs->repo);
/*
@ -2707,12 +2705,8 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
{
int i, flags, left, seen_dashdash, revarg_opt;
struct strvec prune_data = STRVEC_INIT;
const char *submodule = NULL;
int seen_end_of_options = 0;
if (opt)
submodule = opt->submodule;
/* First, search for "--" */
if (opt && opt->assume_dashdash) {
seen_dashdash = 1;
@ -2741,7 +2735,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
if (!seen_end_of_options && *arg == '-') {
int opts;
opts = handle_revision_pseudo_opt(submodule,
opts = handle_revision_pseudo_opt(
revs, argv + i,
&flags);
if (opts > 0) {

View File

@ -336,7 +336,6 @@ extern volatile show_early_output_fn_t show_early_output;
struct setup_revision_opt {
const char *def;
void (*tweak)(struct rev_info *, struct setup_revision_opt *);
const char *submodule; /* TODO: drop this and use rev_info->repo */
unsigned int assume_dashdash:1,
allow_exclude_promisor_objects:1;
unsigned revarg_opt;

View File

@ -525,9 +525,6 @@ static void prepare_submodule_repo_env_in_gitdir(struct strvec *out)
/*
* Initialize a repository struct for a submodule based on the provided 'path'.
*
* Unlike repo_submodule_init, this tolerates submodules not present
* in .gitmodules. This function exists only to preserve historical behavior,
*
* Returns the repository struct on success,
* NULL when the submodule is not present.
*/
@ -1421,25 +1418,14 @@ static void fetch_task_release(struct fetch_task *p)
}
static struct repository *get_submodule_repo_for(struct repository *r,
const struct submodule *sub)
const char *path)
{
struct repository *ret = xmalloc(sizeof(*ret));
if (repo_submodule_init(ret, r, sub)) {
/*
* No entry in .gitmodules? Technically not a submodule,
* but historically we supported repositories that happen to be
* in-place where a gitlink is. Keep supporting them.
*/
struct strbuf gitdir = STRBUF_INIT;
strbuf_repo_worktree_path(&gitdir, r, "%s/.git", sub->path);
if (repo_init(ret, gitdir.buf, NULL)) {
strbuf_release(&gitdir);
if (repo_submodule_init(ret, r, path, null_oid())) {
free(ret);
return NULL;
}
strbuf_release(&gitdir);
}
return ret;
}
@ -1480,7 +1466,7 @@ static int get_next_submodule(struct child_process *cp,
continue;
}
task->repo = get_submodule_repo_for(spf->r, task->sub);
task->repo = get_submodule_repo_for(spf->r, task->sub->path);
if (task->repo) {
struct strbuf submodule_prefix = STRBUF_INIT;
child_process_init(cp);

View File

@ -11,15 +11,13 @@ static void die_usage(const char **argv, const char *msg)
int cmd__submodule_nested_repo_config(int argc, const char **argv)
{
struct repository subrepo;
const struct submodule *sub;
if (argc < 3)
die_usage(argv, "Wrong number of arguments.");
setup_git_directory();
sub = submodule_from_path(the_repository, null_oid(), argv[1]);
if (repo_submodule_init(&subrepo, the_repository, sub)) {
if (repo_submodule_init(&subrepo, the_repository, argv[1], null_oid())) {
die_usage(argv, "Submodule not found.");
}