From: Junio C Hamano <gitster@pobox.com>
To: Usman Akinyemi <usmanakinyemi202@gmail.com>,
Patrick Steinhardt <ps@pks.im>
Cc: Okhuomon Ajayi <okhuomonajayi54@gmail.com>,
git@vger.kernel.org, christian.couder@gmail.com,
siddharthasthana31@gmail.com, kaartic.sivaraam@gmail.com
Subject: Re: [Outreachy PATCH] merge: stop using the_repository
Date: Fri, 06 Nov 2026 17:07:40 -0800 [thread overview]
Message-ID: <xmqq33tdcuub.fsf@gitster.g> (raw)
In-Reply-To: <CAPSxiM_2Dd86rBKPj7jaT8Wmazo3PFZajJaaL2bVhB1GFsfnbg@mail.gmail.com> (Usman Akinyemi's message of "Thu, 15 Oct 2026 17:59:20 +0100")
Usman Akinyemi <usmanakinyemi202@gmail.com> writes:
>> merge.c | 16 +++++++---------
>> 1 file changed, 7 insertions(+), 9 deletions(-)
>
>> + strvec_push(&cmd.args, merge_argument(r, j->item));
>> strvec_push(&cmd.args, "--");
>> strvec_push(&cmd.args, head_arg);
>> for (j = remotes; j; j = j->next)
>> - strvec_push(&cmd.args, merge_argument(j->item));
>> + strvec_push(&cmd.args, merge_argument(r, j->item));
>>
>> cmd.git_cmd = 1;
>> ret = run_command(&cmd);
>> @@ -68,18 +66,18 @@ int checkout_fast_forward(struct repository *r,
>> memset(&trees, 0, sizeof(trees));
>> memset(&t, 0, sizeof(t));
>> }
>> for (i = 0; i < nr_trees; i++) {
>> - if (repo_parse_tree(the_repository, trees[i]) < 0) {
>> + if (repo_parse_tree(r, trees[i]) < 0) {
>> rollback_lock_file(&lock_file);
>> return -1;
>> }
This shows one thing that I really hate about the current
USE_THE_REPOSITORY model.
This function still calls unpack_trees(), which explicitly refers to
and depends on the_repository. It is somewhat misleading to claim
that merge.c no longer depends on the_repository because of that.
Even if you pass an arbitrary repository to checkout_fast_forward(),
the call would not work as intended because unpack_trees() called by
it will only work with the_repository under the hood.
Yet, this file now compiles without USE_THE_REPOSITORY defined,
giving a false sense of achievement.
The attached patch is what I did while reviewing your patch, trying
to get unpack_trees.c to compile without USE_THE_REPOSITORY. This
was done on top of 'seen', so it is more of an RFC or technology
demonstration than a serious patch to be applied (yet).
Note that I did not say that the patch allows unpack_trees() to work
on a repository other than the_repository. That is because many
code paths called by unpack_trees() may still have hidden, hardcoded
dependencies on the_repository.
Again, that is why I really hate the USE_THE_REPOSITORY macro. It
does not help us measure our progress incrementally. Perhaps we
could hide certain symbols from their header files (like the
functions I converted in this demonstration patch to rid them of
the_repository dependency) for those who do not define the macro,
so we can get a more accurate picture of our progress. However,
an earlier attempt to do exactly that on notes-utils.h in
https://lore.kernel.org/git/xmqqjymt94l3.fsf@gitster.g/ was shot
down by Patrick, so I am not sure what a good direction would be
to provide a real incremental progress indicator.
Anyway, provided that we will someday make the functions called by
the functions your patch touched to remove the references to
the_repository also work on arbitrary repositories (and the attached
patch could be one of the changes necessary to go there), I think
your patch is taking us in a better direction. Let's mark the topic
as ready for 'next'.
Thanks.
unpack-trees.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 76 insertions(+), 18 deletions(-)
diff --git c/unpack-trees.c w/unpack-trees.c
index 2e40537dd4..7419793cda 100644
--- c/unpack-trees.c
+++ w/unpack-trees.c
@@ -1,4 +1,3 @@
-#define USE_THE_REPOSITORY_VARIABLE
#define DISABLE_SIGN_COMPARE_WARNINGS
#include "git-compat-util.h"
@@ -82,6 +81,56 @@ static const char *unpack_plumbing_errors[NB_UNPACK_TREES_WARNING_TYPES] = {
? ((o)->internal.msgs[(type)]) \
: (unpack_plumbing_errors[(type)]) )
+
+/*
+ * Some functions in these code paths get unpack_trees_options, which
+ * has up to two istates, and some get an istate. These istates can
+ * be used to find the repository to be used for this operation.
+ *
+ * As these are all working on the same repository, they must match.
+ * For now, with a super paranoid check, make sure all potential
+ * sources of the information match before using it.
+ *
+ * Once this proves working well, we could just use the first one we
+ * find in a production setting.
+ */
+static struct repository *unpack_repo(struct index_state *istate,
+ struct unpack_trees_options *o)
+{
+ struct repository *repo = NULL;
+ const char *camefrom = NULL;
+
+ if (istate) {
+ if (!istate->repo)
+ BUG("istate->repo == NULL");
+ repo = istate->repo;
+ camefrom = "istate->repo";
+ }
+ if (o) {
+ if (o->src_index) {
+ if (!o->src_index->repo)
+ BUG("o->src_index->repo == NULL");
+ if (repo && repo != o->src_index->repo)
+ BUG("%s != o->src_index->repo", camefrom);
+ repo = o->src_index->repo;
+ camefrom = "o->src_index->repo";
+ }
+
+ if (o->dst_index) {
+ if (!o->dst_index->repo)
+ BUG("o->dst_index->repo == NULL");
+ if (repo && repo != o->dst_index->repo)
+ BUG("%s != o->dst_index->repo", camefrom);
+ repo = o->dst_index->repo;
+ }
+ }
+ if (!repo)
+ BUG("no repository for unpack_trees()?");
+ return repo;
+
+}
+
+
static const char *super_prefixed(const char *path, const char *super_prefix)
{
/*
@@ -345,15 +394,16 @@ static void load_gitmodules_file(struct index_state *index,
struct checkout *state)
{
int pos = index_name_pos(index, GITMODULES_FILE, strlen(GITMODULES_FILE));
+ struct repository *repo = unpack_repo(index, NULL);
if (pos >= 0) {
struct cache_entry *ce = index->cache[pos];
if (!state && ce->ce_flags & CE_WT_REMOVE) {
- repo_read_gitmodules(the_repository, 0);
+ repo_read_gitmodules(repo, 0);
} else if (state && (ce->ce_flags & CE_UPDATE)) {
- submodule_free(the_repository);
+ submodule_free(repo);
checkout_entry(ce, state, NULL, NULL);
- repo_read_gitmodules(the_repository, 0);
+ repo_read_gitmodules(repo, 0);
}
}
}
@@ -362,6 +412,7 @@ static struct progress *get_progress(struct unpack_trees_options *o,
struct index_state *index)
{
unsigned cnt = 0, total = 0;
+ struct repository *repo = unpack_repo(index, o);
if (!o->update || !o->verbose_update)
return NULL;
@@ -372,7 +423,7 @@ static struct progress *get_progress(struct unpack_trees_options *o,
total++;
}
- return start_delayed_progress(the_repository,
+ return start_delayed_progress(repo,
_("Updating files"), total);
}
@@ -430,6 +481,7 @@ static int check_updates(struct unpack_trees_options *o,
struct progress *progress;
struct checkout state = CHECKOUT_INIT;
int i, pc_workers, pc_threshold;
+ struct repository *repo = unpack_repo(index, o);
trace_performance_enter();
state.super_prefix = o->super_prefix;
@@ -473,7 +525,7 @@ static int check_updates(struct unpack_trees_options *o,
if (should_update_submodules())
load_gitmodules_file(index, &state);
- if (repo_has_promisor_remote(the_repository))
+ if (repo_has_promisor_remote(repo))
/*
* Prefetch the objects that are to be checked out in the loop
* below.
@@ -879,6 +931,7 @@ static int traverse_trees_recursive(int n, unsigned long dirmask,
struct traverse_info newinfo;
struct name_entry *p;
int nr_entries;
+ struct repository *repo = unpack_repo(NULL, o);
nr_entries = all_trees_same_as_cache_tree(n, dirmask, names, info);
if (nr_entries > 0) {
@@ -940,7 +993,7 @@ static int traverse_trees_recursive(int n, unsigned long dirmask,
const struct object_id *oid = NULL;
if (dirmask & 1)
oid = &names[i].oid;
- buf[nr_buf++] = fill_tree_descriptor(the_repository, t + i, oid);
+ buf[nr_buf++] = fill_tree_descriptor(repo, t + i, oid);
}
}
@@ -1773,24 +1826,25 @@ static int clear_ce_flags(struct index_state *istate,
static struct strbuf prefix = STRBUF_INIT;
char label[100];
int rval;
+ struct repository *repo = unpack_repo(istate, NULL);
strbuf_reset(&prefix);
if (show_progress)
istate->progress = start_delayed_progress(
- the_repository,
+ repo,
_("Updating index flags"),
istate->cache_nr);
xsnprintf(label, sizeof(label), "clear_ce_flags(0x%08lx,0x%08lx)",
(unsigned long)select_mask, (unsigned long)clear_mask);
- trace2_region_enter("unpack_trees", label, istate->repo);
+ trace2_region_enter("unpack_trees", label, repo);
rval = clear_ce_flags_1(istate,
istate->cache,
istate->cache_nr,
&prefix,
select_mask, clear_mask,
pl, 0, 0);
- trace2_region_leave("unpack_trees", label, istate->repo);
+ trace2_region_leave("unpack_trees", label, repo);
stop_progress(&istate->progress);
return rval;
@@ -1885,13 +1939,13 @@ static int verify_absent(const struct cache_entry *,
*/
int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options *o)
{
- struct repository *repo = o->src_index->repo;
+ struct repository *repo = unpack_repo(NULL, o);
int i, ret;
static struct cache_entry *dfc;
struct pattern_list pl;
int free_pattern_list = 0;
struct dir_struct dir = DIR_INIT;
- struct repo_config_values *cfg = repo_config_values(the_repository);
+ struct repo_config_values *cfg = repo_config_values(repo);
if (o->reset == UNPACK_RESET_INVALID)
BUG("o->reset had a value of 1; should be UNPACK_TREES_*_UNTRACKED");
@@ -1936,7 +1990,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
populate_from_existing_patterns(o, &pl);
}
- index_state_init(&o->internal.result, o->src_index->repo);
+ index_state_init(&o->internal.result, repo);
o->internal.result.initialized = 1;
o->internal.result.timestamp.sec = o->src_index->timestamp.sec;
o->internal.result.timestamp.nsec = o->src_index->timestamp.nsec;
@@ -2081,7 +2135,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
move_index_extensions(&o->internal.result, o->src_index);
if (!ret) {
if (git_env_bool("GIT_TEST_CHECK_CACHE_TREE", 0) &&
- cache_tree_verify(the_repository,
+ cache_tree_verify(repo,
&o->internal.result) < 0) {
ret = -1;
goto done;
@@ -2137,10 +2191,11 @@ enum update_sparsity_result update_sparsity(struct unpack_trees_options *o,
int i;
unsigned old_show_all_errors;
int free_pattern_list = 0;
+ struct repository *repo = unpack_repo(NULL, o);
old_show_all_errors = o->internal.show_all_errors;
o->internal.show_all_errors = 1;
- index_state_init(&o->internal.result, o->src_index->repo);
+ index_state_init(&o->internal.result, repo);
/* Sanity checks */
if (!o->update || o->index_only || o->skip_sparse_checkout)
@@ -2333,10 +2388,11 @@ static int verify_clean_subdirectory(const struct cache_entry *ce,
struct dir_struct d;
char *pathbuf;
int cnt = 0;
+ struct repository *repo = unpack_repo(NULL, o);
if (S_ISGITLINK(ce->ce_mode)) {
struct object_id oid;
- int sub_head = repo_resolve_gitlink_ref(the_repository, ce->name,
+ int sub_head = repo_resolve_gitlink_ref(repo, ce->name,
"HEAD", &oid);
/*
* If we are not going to update the submodule, then
@@ -2424,6 +2480,7 @@ static int check_ok_to_remove(const char *name, int len, int dtype,
struct unpack_trees_options *o)
{
const struct cache_entry *result;
+ struct repository *repo = unpack_repo(NULL, o);
/*
* It may be that the 'lstat()' succeeded even though
@@ -2432,7 +2489,7 @@ static int check_ok_to_remove(const char *name, int len, int dtype,
*
* Ignore that lstat() if it matches.
*/
- if (repo_ignore_case(the_repository) && icase_exists(o, name, len, st))
+ if (repo_ignore_case(repo) && icase_exists(o, name, len, st))
return 0;
if (o->internal.dir &&
@@ -2652,6 +2709,7 @@ static int merged_sparse_dir(const struct cache_entry * const *src, int n,
void * tree_bufs[MAX_UNPACK_TREES + 1];
struct traverse_info info;
int i, ret;
+ struct repository *repo = unpack_repo(NULL, o);
/*
* Create the tree traversal information for traversing into *only* the
@@ -2665,7 +2723,7 @@ static int merged_sparse_dir(const struct cache_entry * const *src, int n,
/* Get the tree descriptors of the sparse directory in each of the merging trees */
for (i = 0; i < n; i++)
- tree_bufs[i] = fill_tree_descriptor(o->src_index->repo, &t[i],
+ tree_bufs[i] = fill_tree_descriptor(repo, &t[i],
src[i] && !is_null_oid(&src[i]->oid) ? &src[i]->oid : NULL);
ret = traverse_trees(o->src_index, n, t, &info);
next prev parent reply other threads:[~2026-11-07 1:07 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-15 14:25 [Outreachy PATCH] merge: stop using the_repository Okhuomon Ajayi
2026-10-15 16:59 ` Usman Akinyemi
2026-10-15 17:20 ` Okhuomon Ajayi
2026-11-07 1:07 ` Junio C Hamano [this message]
2026-11-09 8:17 ` Patrick Steinhardt
2026-10-15 19:20 ` Junio C Hamano
2026-10-15 19:56 ` Okhuomon Ajayi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=xmqq33tdcuub.fsf@gitster.g \
--to=gitster@pobox.com \
--cc=christian.couder@gmail.com \
--cc=git@vger.kernel.org \
--cc=kaartic.sivaraam@gmail.com \
--cc=okhuomonajayi54@gmail.com \
--cc=ps@pks.im \
--cc=siddharthasthana31@gmail.com \
--cc=usmanakinyemi202@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox