* [PATCH 01/14] fsck: drop `the_repository` in `fsck_walk()`
2026-03-20 11:47 [PATCH 00/14] fsck: drop use of `the_repository` Patrick Steinhardt
@ 2026-03-20 11:47 ` Patrick Steinhardt
2026-03-20 23:09 ` Junio C Hamano
2026-03-20 11:47 ` [PATCH 02/14] fsck: drop `the_repository` in `fsck_finish()` Patrick Steinhardt
` (13 subsequent siblings)
14 siblings, 1 reply; 33+ messages in thread
From: Patrick Steinhardt @ 2026-03-20 11:47 UTC (permalink / raw)
To: git
The function `fsck_walk()` and its object type specific functions
`fsck_walk_tree()` et al implicitly rely on `the_repository`. Remove
this dependency by injecting the repository as a parameter instead.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
builtin/fsck.c | 6 +++---
builtin/index-pack.c | 2 +-
builtin/unpack-objects.c | 2 +-
fsck.c | 40 ++++++++++++++++++++++++++--------------
fsck.h | 15 ++++++++++++---
5 files changed, 43 insertions(+), 22 deletions(-)
diff --git a/builtin/fsck.c b/builtin/fsck.c
index 9bab32effe..15477767c7 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -186,7 +186,7 @@ static void mark_object_reachable(struct object *obj)
static int traverse_one_object(struct object *obj)
{
- int result = fsck_walk(obj, obj, &fsck_walk_options);
+ int result = fsck_walk(the_repository, obj, obj, &fsck_walk_options);
if (obj->type == OBJ_TREE) {
struct tree *tree = (struct tree *)obj;
@@ -244,7 +244,7 @@ static int mark_unreachable_referents(const struct object_id *oid,
}
options.walk = mark_used;
- fsck_walk(obj, NULL, &options);
+ fsck_walk(the_repository, obj, NULL, &options);
if (obj->type == OBJ_TREE)
free_tree_buffer((struct tree *)obj);
@@ -413,7 +413,7 @@ static int fsck_obj(struct object *obj, void *buffer, unsigned long size)
printable_type(&obj->oid, obj->type),
describe_object(&obj->oid));
- if (fsck_walk(obj, NULL, &fsck_obj_options))
+ if (fsck_walk(the_repository, obj, NULL, &fsck_obj_options))
objerror(obj, _("broken links"));
err = fsck_object(obj, buffer, size, &fsck_obj_options);
if (err)
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index d1e47279a8..a3d37d34cc 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -954,7 +954,7 @@ static void sha1_object(const void *data, struct object_entry *obj_entry,
if (do_fsck_object &&
fsck_object(obj, buf, size, &fsck_options))
die(_("fsck error in packed object"));
- if (strict && fsck_walk(obj, NULL, &fsck_options))
+ if (strict && fsck_walk(the_repository, obj, NULL, &fsck_options))
die(_("Not all child objects of %s are reachable"), oid_to_hex(&obj->oid));
if (record_outgoing_links)
do_record_outgoing_links(obj);
diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c
index 6fc64e9e4b..52b62ff6d4 100644
--- a/builtin/unpack-objects.c
+++ b/builtin/unpack-objects.c
@@ -244,7 +244,7 @@ static int check_object(struct object *obj, enum object_type type,
if (fsck_object(obj, obj_buf->buffer, obj_buf->size, &fsck_options))
die("fsck error in packed object");
fsck_options.walk = check_object;
- if (fsck_walk(obj, NULL, &fsck_options))
+ if (fsck_walk(the_repository, obj, NULL, &fsck_options))
die("Error on reachable objects of %s", oid_to_hex(&obj->oid));
write_cached_object(obj, obj_buf);
return 0;
diff --git a/fsck.c b/fsck.c
index 0f02cf8f77..c6b6f533be 100644
--- a/fsck.c
+++ b/fsck.c
@@ -353,14 +353,17 @@ const char *fsck_describe_object(struct fsck_options *options,
return buf->buf;
}
-static int fsck_walk_tree(struct tree *tree, void *data, struct fsck_options *options)
+static int fsck_walk_tree(struct repository *repo,
+ struct tree *tree,
+ void *data,
+ struct fsck_options *options)
{
struct tree_desc desc;
struct name_entry entry;
int res = 0;
const char *name;
- if (repo_parse_tree(the_repository, tree))
+ if (repo_parse_tree(repo, tree))
return -1;
name = fsck_get_object_name(options, &tree->object.oid);
@@ -375,14 +378,14 @@ static int fsck_walk_tree(struct tree *tree, void *data, struct fsck_options *op
continue;
if (S_ISDIR(entry.mode)) {
- obj = (struct object *)lookup_tree(the_repository, &entry.oid);
+ obj = (struct object *)lookup_tree(repo, &entry.oid);
if (name && obj)
fsck_put_object_name(options, &entry.oid, "%s%s/",
name, entry.path);
result = options->walk(obj, OBJ_TREE, data, options);
}
else if (S_ISREG(entry.mode) || S_ISLNK(entry.mode)) {
- obj = (struct object *)lookup_blob(the_repository, &entry.oid);
+ obj = (struct object *)lookup_blob(repo, &entry.oid);
if (name && obj)
fsck_put_object_name(options, &entry.oid, "%s%s",
name, entry.path);
@@ -401,7 +404,10 @@ static int fsck_walk_tree(struct tree *tree, void *data, struct fsck_options *op
return res;
}
-static int fsck_walk_commit(struct commit *commit, void *data, struct fsck_options *options)
+static int fsck_walk_commit(struct repository *repo,
+ struct commit *commit,
+ void *data,
+ struct fsck_options *options)
{
int counter = 0, generation = 0, name_prefix_len = 0;
struct commit_list *parents;
@@ -409,7 +415,7 @@ static int fsck_walk_commit(struct commit *commit, void *data, struct fsck_optio
int result;
const char *name;
- if (repo_parse_commit(the_repository, commit))
+ if (repo_parse_commit(repo, commit))
return -1;
name = fsck_get_object_name(options, &commit->object.oid);
@@ -417,7 +423,7 @@ static int fsck_walk_commit(struct commit *commit, void *data, struct fsck_optio
fsck_put_object_name(options, get_commit_tree_oid(commit),
"%s:", name);
- result = options->walk((struct object *) repo_get_commit_tree(the_repository, commit),
+ result = options->walk((struct object *) repo_get_commit_tree(repo, commit),
OBJ_TREE, data, options);
if (result < 0)
return result;
@@ -470,34 +476,40 @@ static int fsck_walk_commit(struct commit *commit, void *data, struct fsck_optio
return res;
}
-static int fsck_walk_tag(struct tag *tag, void *data, struct fsck_options *options)
+static int fsck_walk_tag(struct repository *repo,
+ struct tag *tag,
+ void *data,
+ struct fsck_options *options)
{
const char *name = fsck_get_object_name(options, &tag->object.oid);
- if (parse_tag(the_repository, tag))
+ if (parse_tag(repo, tag))
return -1;
if (name)
fsck_put_object_name(options, &tag->tagged->oid, "%s", name);
return options->walk(tag->tagged, OBJ_ANY, data, options);
}
-int fsck_walk(struct object *obj, void *data, struct fsck_options *options)
+int fsck_walk(struct repository *repo,
+ struct object *obj,
+ void *data,
+ struct fsck_options *options)
{
if (!obj)
return -1;
if (obj->type == OBJ_NONE)
- parse_object(the_repository, &obj->oid);
+ parse_object(repo, &obj->oid);
switch (obj->type) {
case OBJ_BLOB:
return 0;
case OBJ_TREE:
- return fsck_walk_tree((struct tree *)obj, data, options);
+ return fsck_walk_tree(repo, (struct tree *)obj, data, options);
case OBJ_COMMIT:
- return fsck_walk_commit((struct commit *)obj, data, options);
+ return fsck_walk_commit(repo, (struct commit *)obj, data, options);
case OBJ_TAG:
- return fsck_walk_tag((struct tag *)obj, data, options);
+ return fsck_walk_tag(repo, (struct tag *)obj, data, options);
default:
error("Unknown object type for %s",
fsck_describe_object(options, &obj->oid));
diff --git a/fsck.h b/fsck.h
index 65ecbb7fe1..4bd54865fe 100644
--- a/fsck.h
+++ b/fsck.h
@@ -208,14 +208,23 @@ struct fsck_options {
.error_func = fsck_refs_error_function, \
}
-/* descend in all linked child objects
- * the return value is:
+/*
+ * Perform consistency checks for the given object and all of its decendents.
+ *
+ * If set, the `walk` callback function in the options structure will be called
+ * for every commit. The data parameter will be passed as callback data.
+ *
+ * Returns:
+ *
* -1 error in processing the object
* <0 return value of the callback, which lead to an abort
* >0 return value of the first signaled error >0 (in the case of no other errors)
* 0 everything OK
*/
-int fsck_walk(struct object *obj, void *data, struct fsck_options *options);
+int fsck_walk(struct repository *repo,
+ struct object *obj,
+ void *data,
+ struct fsck_options *options);
/*
* Blob objects my pass a NULL data pointer, which indicates they are too large
--
2.53.0.1055.ga2ffed1127.dirty
^ permalink raw reply related [flat|nested] 33+ messages in thread* Re: [PATCH 01/14] fsck: drop `the_repository` in `fsck_walk()`
2026-03-20 11:47 ` [PATCH 01/14] fsck: drop `the_repository` in `fsck_walk()` Patrick Steinhardt
@ 2026-03-20 23:09 ` Junio C Hamano
2026-03-23 12:22 ` Patrick Steinhardt
0 siblings, 1 reply; 33+ messages in thread
From: Junio C Hamano @ 2026-03-20 23:09 UTC (permalink / raw)
To: Patrick Steinhardt; +Cc: git
Patrick Steinhardt <ps@pks.im> writes:
> The function `fsck_walk()` and its object type specific functions
> `fsck_walk_tree()` et al implicitly rely on `the_repository`. Remove
> this dependency by injecting the repository as a parameter instead.
>
> Signed-off-by: Patrick Steinhardt <ps@pks.im>
> ---
> builtin/fsck.c | 6 +++---
> builtin/index-pack.c | 2 +-
> builtin/unpack-objects.c | 2 +-
> fsck.c | 40 ++++++++++++++++++++++++++--------------
> fsck.h | 15 ++++++++++++---
> 5 files changed, 43 insertions(+), 22 deletions(-)
OK.
While the conversion is cleanly done, the resulting code makes me
wonder if fsck_options struct
struct fsck_options {
fsck_walk_func walk;
fsck_error error_func;
unsigned strict;
unsigned verbose;
enum fsck_msg_type *msg_type;
struct oidset skip_oids;
struct oidset gitmodules_found;
struct oidset gitmodules_done;
struct oidset gitattributes_found;
struct oidset gitattributes_done;
kh_oid_map_t *object_names;
};
should gain a repository pointer. After all, these oidset and oidmap
are about objects in one particular repository.
^ permalink raw reply [flat|nested] 33+ messages in thread* Re: [PATCH 01/14] fsck: drop `the_repository` in `fsck_walk()`
2026-03-20 23:09 ` Junio C Hamano
@ 2026-03-23 12:22 ` Patrick Steinhardt
0 siblings, 0 replies; 33+ messages in thread
From: Patrick Steinhardt @ 2026-03-23 12:22 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
On Fri, Mar 20, 2026 at 04:09:24PM -0700, Junio C Hamano wrote:
> Patrick Steinhardt <ps@pks.im> writes:
>
> > The function `fsck_walk()` and its object type specific functions
> > `fsck_walk_tree()` et al implicitly rely on `the_repository`. Remove
> > this dependency by injecting the repository as a parameter instead.
> >
> > Signed-off-by: Patrick Steinhardt <ps@pks.im>
> > ---
> > builtin/fsck.c | 6 +++---
> > builtin/index-pack.c | 2 +-
> > builtin/unpack-objects.c | 2 +-
> > fsck.c | 40 ++++++++++++++++++++++++++--------------
> > fsck.h | 15 ++++++++++++---
> > 5 files changed, 43 insertions(+), 22 deletions(-)
>
> OK.
>
> While the conversion is cleanly done, the resulting code makes me
> wonder if fsck_options struct
>
> struct fsck_options {
> fsck_walk_func walk;
> fsck_error error_func;
> unsigned strict;
> unsigned verbose;
> enum fsck_msg_type *msg_type;
> struct oidset skip_oids;
> struct oidset gitmodules_found;
> struct oidset gitmodules_done;
> struct oidset gitattributes_found;
> struct oidset gitattributes_done;
> kh_oid_map_t *object_names;
> };
>
> should gain a repository pointer. After all, these oidset and oidmap
> are about objects in one particular repository.
That's fair, and indeed this was my first attempt at solving the
dependency on `the_repository`. The reason why I discarded that approach
though is the way that we currenlty initialize `struct fsck_options` via
a set of macros. And as we often do this in file-static scope we don't
have a repository available there.
I had a second look at this though and have now introduced a new
function to initialize the options instead. It's a tiny bit ugly, and
ideally we'd just not have the options in global scope in the first
place. But I guess that overall it's okayish.
Will update and send the revised version soonish.
Thanks!
Patrick
^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 02/14] fsck: drop `the_repository` in `fsck_finish()`
2026-03-20 11:47 [PATCH 00/14] fsck: drop use of `the_repository` Patrick Steinhardt
2026-03-20 11:47 ` [PATCH 01/14] fsck: drop `the_repository` in `fsck_walk()` Patrick Steinhardt
@ 2026-03-20 11:47 ` Patrick Steinhardt
2026-03-20 11:47 ` [PATCH 03/14] fsck: refactor interface to parse fsck options Patrick Steinhardt
` (12 subsequent siblings)
14 siblings, 0 replies; 33+ messages in thread
From: Patrick Steinhardt @ 2026-03-20 11:47 UTC (permalink / raw)
To: git
The function `fsck_finish()` and its transitively called function
`fsck_blobs()` implicitly rely on `the_repository`. Remove this
dependency by injecting the repository as a parameter instead.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
builtin/fsck.c | 2 +-
builtin/index-pack.c | 2 +-
builtin/unpack-objects.c | 2 +-
fetch-pack.c | 4 ++--
fsck.c | 13 +++++++------
fsck.h | 2 +-
object-file.c | 2 +-
7 files changed, 14 insertions(+), 13 deletions(-)
diff --git a/builtin/fsck.c b/builtin/fsck.c
index 15477767c7..8f994010da 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -1075,7 +1075,7 @@ int cmd_fsck(int argc,
stop_progress(&progress);
}
- if (fsck_finish(&fsck_obj_options))
+ if (fsck_finish(the_repository, &fsck_obj_options))
errors_found |= ERROR_OBJECT;
}
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index a3d37d34cc..3d1f7dbd5f 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -2123,7 +2123,7 @@ int cmd_index_pack(int argc,
die(_("cannot perform queued object checks outside "
"of a repository"));
- if (fsck_finish(&fsck_options))
+ if (fsck_finish(the_repository, &fsck_options))
die(_("fsck error in pack objects"));
}
diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c
index 52b62ff6d4..9596b3ea4f 100644
--- a/builtin/unpack-objects.c
+++ b/builtin/unpack-objects.c
@@ -676,7 +676,7 @@ int cmd_unpack_objects(int argc,
git_hash_final_oid(&oid, &tmp_ctx);
if (strict) {
write_rest();
- if (fsck_finish(&fsck_options))
+ if (fsck_finish(the_repository, &fsck_options))
die(_("fsck error in pack objects"));
}
if (!hasheq(fill(the_hash_algo->rawsz), oid.hash,
diff --git a/fetch-pack.c b/fetch-pack.c
index 6ecd468ef7..6fd534633d 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -1231,7 +1231,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
if (get_pack(args, fd, pack_lockfiles, NULL, sought, nr_sought,
&fsck_options.gitmodules_found))
die(_("git fetch-pack: fetch failed."));
- if (fsck_finish(&fsck_options))
+ if (fsck_finish(the_repository, &fsck_options))
die("fsck failed");
all_done:
@@ -1876,7 +1876,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
string_list_clear(&packfile_uris, 0);
strvec_clear(&index_pack_args);
- if (fsck_finish(&fsck_options))
+ if (fsck_finish(the_repository, &fsck_options))
die("fsck failed");
if (negotiator)
diff --git a/fsck.c b/fsck.c
index c6b6f533be..1f7d568acf 100644
--- a/fsck.c
+++ b/fsck.c
@@ -1331,7 +1331,8 @@ int fsck_refs_error_function(struct fsck_options *options UNUSED,
return ret;
}
-static int fsck_blobs(struct oidset *blobs_found, struct oidset *blobs_done,
+static int fsck_blobs(struct repository *repo,
+ struct oidset *blobs_found, struct oidset *blobs_done,
enum fsck_msg_id msg_missing, enum fsck_msg_id msg_type,
struct fsck_options *options, const char *blob_type)
{
@@ -1348,9 +1349,9 @@ static int fsck_blobs(struct oidset *blobs_found, struct oidset *blobs_done,
if (oidset_contains(blobs_done, oid))
continue;
- buf = odb_read_object(the_repository->objects, oid, &type, &size);
+ buf = odb_read_object(repo->objects, oid, &type, &size);
if (!buf) {
- if (is_promisor_object(the_repository, oid))
+ if (is_promisor_object(repo, oid))
continue;
ret |= report(options,
oid, OBJ_BLOB, msg_missing,
@@ -1372,14 +1373,14 @@ static int fsck_blobs(struct oidset *blobs_found, struct oidset *blobs_done,
return ret;
}
-int fsck_finish(struct fsck_options *options)
+int fsck_finish(struct repository *repo, struct fsck_options *options)
{
int ret = 0;
- ret |= fsck_blobs(&options->gitmodules_found, &options->gitmodules_done,
+ ret |= fsck_blobs(repo, &options->gitmodules_found, &options->gitmodules_done,
FSCK_MSG_GITMODULES_MISSING, FSCK_MSG_GITMODULES_BLOB,
options, ".gitmodules");
- ret |= fsck_blobs(&options->gitattributes_found, &options->gitattributes_done,
+ ret |= fsck_blobs(repo, &options->gitattributes_found, &options->gitattributes_done,
FSCK_MSG_GITATTRIBUTES_MISSING, FSCK_MSG_GITATTRIBUTES_BLOB,
options, ".gitattributes");
diff --git a/fsck.h b/fsck.h
index 4bd54865fe..bfe9b3ffc9 100644
--- a/fsck.h
+++ b/fsck.h
@@ -255,7 +255,7 @@ int fsck_tag_standalone(const struct object_id *oid, const char *buffer,
* after completing all fsck_object() calls in order to resolve any remaining
* checks.
*/
-int fsck_finish(struct fsck_options *options);
+int fsck_finish(struct repository *repo, struct fsck_options *options);
/*
* Check whether there are any checks that have been queued up and that still
diff --git a/object-file.c b/object-file.c
index c62e5496e0..ecbcc501dd 100644
--- a/object-file.c
+++ b/object-file.c
@@ -1285,7 +1285,7 @@ static int index_mem(struct index_state *istate,
opts.error_func = hash_format_check_report;
if (fsck_buffer(null_oid(istate->repo->hash_algo), type, buf, size, &opts))
die(_("refusing to create malformed object"));
- fsck_finish(&opts);
+ fsck_finish(the_repository, &opts);
}
if (write_object)
--
2.53.0.1055.ga2ffed1127.dirty
^ permalink raw reply related [flat|nested] 33+ messages in thread* [PATCH 03/14] fsck: refactor interface to parse fsck options
2026-03-20 11:47 [PATCH 00/14] fsck: drop use of `the_repository` Patrick Steinhardt
2026-03-20 11:47 ` [PATCH 01/14] fsck: drop `the_repository` in `fsck_walk()` Patrick Steinhardt
2026-03-20 11:47 ` [PATCH 02/14] fsck: drop `the_repository` in `fsck_finish()` Patrick Steinhardt
@ 2026-03-20 11:47 ` Patrick Steinhardt
2026-03-20 11:47 ` [PATCH 04/14] fsck: drop `the_repository` in `fsck_set_msg_types()` Patrick Steinhardt
` (11 subsequent siblings)
14 siblings, 0 replies; 33+ messages in thread
From: Patrick Steinhardt @ 2026-03-20 11:47 UTC (permalink / raw)
To: git
The function `git_fsck_config()` is supposed to be used as a callback
function for `repo_config()`. It expects the caller to provide a
repository as callback payload, which is easy to miss. Furthermore, in
the next commit we're about to refactor the function to not rely on
global state anymore, which will require callers to pass a different
payload.
Prepare for this change by refactoring the interface to be fully
self-contained. Like this, callers know exactly which parameters are
expected.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
builtin/fsck.c | 2 +-
builtin/mktag.c | 3 ++-
builtin/refs.c | 2 +-
fsck.c | 11 +++++++++--
fsck.h | 9 ++++-----
5 files changed, 17 insertions(+), 10 deletions(-)
diff --git a/builtin/fsck.c b/builtin/fsck.c
index 8f994010da..fd689a1e14 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -1023,7 +1023,7 @@ int cmd_fsck(int argc,
if (name_objects)
fsck_enable_object_names(&fsck_walk_options);
- repo_config(the_repository, git_fsck_config, &fsck_obj_options);
+ fsck_options_parse_config(&fsck_obj_options, the_repository);
prepare_repo_settings(the_repository);
if (check_references)
diff --git a/builtin/mktag.c b/builtin/mktag.c
index 7cf6e1230a..2cf843c195 100644
--- a/builtin/mktag.c
+++ b/builtin/mktag.c
@@ -98,7 +98,8 @@ int cmd_mktag(int argc,
fsck_set_msg_type_from_ids(&fsck_options, FSCK_MSG_EXTRA_HEADER_ENTRY,
FSCK_WARN);
/* config might set fsck.extraHeaderEntry=* again */
- repo_config(the_repository, git_fsck_config, &fsck_options);
+ fsck_options_parse_config(&fsck_options, the_repository);
+
if (fsck_tag_standalone(NULL, buf.buf, buf.len, &fsck_options,
&tagged_oid, &tagged_type))
die(_("tag on stdin did not pass our strict fsck check"));
diff --git a/builtin/refs.c b/builtin/refs.c
index 3064f888b2..c0a3b475e9 100644
--- a/builtin/refs.c
+++ b/builtin/refs.c
@@ -97,7 +97,7 @@ static int cmd_refs_verify(int argc, const char **argv, const char *prefix,
if (argc)
usage(_("'git refs verify' takes no arguments"));
- repo_config(the_repository, git_fsck_config, &fsck_refs_options);
+ fsck_options_parse_config(&fsck_refs_options, the_repository);
prepare_repo_settings(the_repository);
worktrees = get_worktrees_without_reading_head();
diff --git a/fsck.c b/fsck.c
index 1f7d568acf..a7ebab9581 100644
--- a/fsck.c
+++ b/fsck.c
@@ -1404,8 +1404,9 @@ void fsck_options_clear(struct fsck_options *options)
kh_clear_oid_map(options->object_names);
}
-int git_fsck_config(const char *var, const char *value,
- const struct config_context *ctx, void *cb)
+static int fsck_options_parse_config_key(const char *var, const char *value,
+ const struct config_context *ctx,
+ void *cb)
{
struct fsck_options *options = cb;
const char *msg_id;
@@ -1435,6 +1436,12 @@ int git_fsck_config(const char *var, const char *value,
return git_default_config(var, value, ctx, cb);
}
+void fsck_options_parse_config(struct fsck_options *options,
+ struct repository *repo)
+{
+ repo_config(repo, fsck_options_parse_config_key, options);
+}
+
/*
* Custom error callbacks that are used in more than one place.
*/
diff --git a/fsck.h b/fsck.h
index bfe9b3ffc9..7d0d876103 100644
--- a/fsck.h
+++ b/fsck.h
@@ -304,12 +304,11 @@ void fsck_put_object_name(struct fsck_options *options,
const char *fsck_describe_object(struct fsck_options *options,
const struct object_id *oid);
-struct key_value_info;
/*
- * repo_config() callback for use by fsck-y tools that want to support
- * fsck.<msg> fsck.skipList etc.
+ * Parse fsck options from the gitconfig. This covers settings like for example
+ * fsck.<msg> fsck.skipList.
*/
-int git_fsck_config(const char *var, const char *value,
- const struct config_context *ctx, void *cb);
+void fsck_options_parse_config(struct fsck_options *options,
+ struct repository *repo);
#endif
--
2.53.0.1055.ga2ffed1127.dirty
^ permalink raw reply related [flat|nested] 33+ messages in thread* [PATCH 04/14] fsck: drop `the_repository` in `fsck_set_msg_types()`
2026-03-20 11:47 [PATCH 00/14] fsck: drop use of `the_repository` Patrick Steinhardt
` (2 preceding siblings ...)
2026-03-20 11:47 ` [PATCH 03/14] fsck: refactor interface to parse fsck options Patrick Steinhardt
@ 2026-03-20 11:47 ` Patrick Steinhardt
2026-03-20 11:47 ` [PATCH 05/14] fsck: stop relying on global state via `parse_oid_hex()` Patrick Steinhardt
` (10 subsequent siblings)
14 siblings, 0 replies; 33+ messages in thread
From: Patrick Steinhardt @ 2026-03-20 11:47 UTC (permalink / raw)
To: git
We implicitly rely on `the_repository` in `fsck_set_msg_types()` because
of our reliance on `the_hash_algo`. Fix this dependency on global state
by requiring the callers to provide the hash function.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
builtin/index-pack.c | 6 ++++--
builtin/unpack-objects.c | 3 ++-
fsck.c | 27 +++++++++++++++++++--------
fsck.h | 3 ++-
4 files changed, 27 insertions(+), 12 deletions(-)
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index 3d1f7dbd5f..c4117e5970 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -1932,13 +1932,15 @@ int cmd_index_pack(int argc,
} else if (skip_to_optional_arg(arg, "--strict", &arg)) {
strict = 1;
do_fsck_object = 1;
- fsck_set_msg_types(&fsck_options, arg);
+ fsck_set_msg_types(&fsck_options, arg,
+ the_hash_algo);
} else if (!strcmp(arg, "--check-self-contained-and-connected")) {
strict = 1;
check_self_contained_and_connected = 1;
} else if (skip_to_optional_arg(arg, "--fsck-objects", &arg)) {
do_fsck_object = 1;
- fsck_set_msg_types(&fsck_options, arg);
+ fsck_set_msg_types(&fsck_options, arg,
+ the_hash_algo);
} else if (!strcmp(arg, "--verify")) {
verify = 1;
} else if (!strcmp(arg, "--verify-stat")) {
diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c
index 9596b3ea4f..3e748a55d9 100644
--- a/builtin/unpack-objects.c
+++ b/builtin/unpack-objects.c
@@ -649,7 +649,8 @@ int cmd_unpack_objects(int argc,
}
if (skip_prefix(arg, "--strict=", &arg)) {
strict = 1;
- fsck_set_msg_types(&fsck_options, arg);
+ fsck_set_msg_types(&fsck_options, arg,
+ the_hash_algo);
continue;
}
if (skip_prefix(arg, "--pack_header=", &arg)) {
diff --git a/fsck.c b/fsck.c
index a7ebab9581..efd987dd2b 100644
--- a/fsck.c
+++ b/fsck.c
@@ -182,7 +182,8 @@ void fsck_set_msg_type(struct fsck_options *options,
free(to_free);
}
-void fsck_set_msg_types(struct fsck_options *options, const char *values)
+void fsck_set_msg_types(struct fsck_options *options, const char *values,
+ const struct git_hash_algo *algo)
{
char *buf = xstrdup(values), *to_free = buf;
int done = 0;
@@ -207,7 +208,7 @@ void fsck_set_msg_types(struct fsck_options *options, const char *values)
if (equal == len)
die("skiplist requires a path");
oidset_parse_file(&options->skip_oids, buf + equal + 1,
- the_repository->hash_algo);
+ algo);
buf += len + 1;
continue;
}
@@ -1404,11 +1405,16 @@ void fsck_options_clear(struct fsck_options *options)
kh_clear_oid_map(options->object_names);
}
+struct fsck_options_parse_config_key_data {
+ struct repository *repo;
+ struct fsck_options *options;
+};
+
static int fsck_options_parse_config_key(const char *var, const char *value,
const struct config_context *ctx,
- void *cb)
+ void *cb_data)
{
- struct fsck_options *options = cb;
+ struct fsck_options_parse_config_key_data *data = cb_data;
const char *msg_id;
if (strcmp(var, "fsck.skiplist") == 0) {
@@ -1420,7 +1426,8 @@ static int fsck_options_parse_config_key(const char *var, const char *value,
struct strbuf sb = STRBUF_INIT;
strbuf_addf(&sb, "skiplist=%s", path);
free(path);
- fsck_set_msg_types(options, sb.buf);
+ fsck_set_msg_types(data->options, sb.buf,
+ data->repo->hash_algo);
strbuf_release(&sb);
}
return 0;
@@ -1429,17 +1436,21 @@ static int fsck_options_parse_config_key(const char *var, const char *value,
if (skip_prefix(var, "fsck.", &msg_id)) {
if (!value)
return config_error_nonbool(var);
- fsck_set_msg_type(options, msg_id, value);
+ fsck_set_msg_type(data->options, msg_id, value);
return 0;
}
- return git_default_config(var, value, ctx, cb);
+ return git_default_config(var, value, ctx, cb_data);
}
void fsck_options_parse_config(struct fsck_options *options,
struct repository *repo)
{
- repo_config(repo, fsck_options_parse_config_key, options);
+ struct fsck_options_parse_config_key_data data = {
+ .repo = repo,
+ .options = options,
+ };
+ repo_config(repo, fsck_options_parse_config_key, &data);
}
/*
diff --git a/fsck.h b/fsck.h
index 7d0d876103..3ca1683f74 100644
--- a/fsck.h
+++ b/fsck.h
@@ -118,7 +118,8 @@ void fsck_set_msg_type_from_ids(struct fsck_options *options,
enum fsck_msg_type msg_type);
void fsck_set_msg_type(struct fsck_options *options,
const char *msg_id, const char *msg_type);
-void fsck_set_msg_types(struct fsck_options *options, const char *values);
+void fsck_set_msg_types(struct fsck_options *options, const char *values,
+ const struct git_hash_algo *algo);
int is_valid_msg_type(const char *msg_id, const char *msg_type);
/*
--
2.53.0.1055.ga2ffed1127.dirty
^ permalink raw reply related [flat|nested] 33+ messages in thread* [PATCH 05/14] fsck: stop relying on global state via `parse_oid_hex()`
2026-03-20 11:47 [PATCH 00/14] fsck: drop use of `the_repository` Patrick Steinhardt
` (3 preceding siblings ...)
2026-03-20 11:47 ` [PATCH 04/14] fsck: drop `the_repository` in `fsck_set_msg_types()` Patrick Steinhardt
@ 2026-03-20 11:47 ` Patrick Steinhardt
2026-03-20 11:47 ` [PATCH 06/14] builtin/fsck: fix trivial dependence on `the_repository` Patrick Steinhardt
` (9 subsequent siblings)
14 siblings, 0 replies; 33+ messages in thread
From: Patrick Steinhardt @ 2026-03-20 11:47 UTC (permalink / raw)
To: git
The function `parse_oid_hex()` implicitly relies on global state, as it
uses the hash algorithm of `the_repository` to parse the input string.
Refactor "fsck.c" to use `parse_oid_hex_algop()` instead and make the
repository available via parameters as required.
This was the last dependency on `the_repository` in "fsck.c", so we can
now drop `USE_THE_REPOSITORY_VARIABLE`.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
builtin/fsck.c | 2 +-
builtin/index-pack.c | 5 +++--
builtin/mktag.c | 4 ++--
builtin/unpack-objects.c | 2 +-
fsck.c | 33 ++++++++++++++++++---------------
fsck.h | 11 +++++++----
object-file.c | 3 ++-
7 files changed, 34 insertions(+), 26 deletions(-)
diff --git a/builtin/fsck.c b/builtin/fsck.c
index fd689a1e14..ff9951c10c 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -415,7 +415,7 @@ static int fsck_obj(struct object *obj, void *buffer, unsigned long size)
if (fsck_walk(the_repository, obj, NULL, &fsck_obj_options))
objerror(obj, _("broken links"));
- err = fsck_object(obj, buffer, size, &fsck_obj_options);
+ err = fsck_object(the_repository, obj, buffer, size, &fsck_obj_options);
if (err)
goto out;
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index c4117e5970..031e4697d9 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -933,7 +933,8 @@ static void sha1_object(const void *data, struct object_entry *obj_entry,
else
die(_("invalid blob object %s"), oid_to_hex(oid));
if (do_fsck_object &&
- fsck_object(&blob->object, (void *)data, size, &fsck_options))
+ fsck_object(the_repository, &blob->object, (void *)data,
+ size, &fsck_options))
die(_("fsck error in packed object"));
} else {
struct object *obj;
@@ -952,7 +953,7 @@ static void sha1_object(const void *data, struct object_entry *obj_entry,
if (!obj)
die(_("invalid %s"), type_name(type));
if (do_fsck_object &&
- fsck_object(obj, buf, size, &fsck_options))
+ fsck_object(the_repository, obj, buf, size, &fsck_options))
die(_("fsck error in packed object"));
if (strict && fsck_walk(the_repository, obj, NULL, &fsck_options))
die(_("Not all child objects of %s are reachable"), oid_to_hex(&obj->oid));
diff --git a/builtin/mktag.c b/builtin/mktag.c
index 2cf843c195..1925f04321 100644
--- a/builtin/mktag.c
+++ b/builtin/mktag.c
@@ -100,8 +100,8 @@ int cmd_mktag(int argc,
/* config might set fsck.extraHeaderEntry=* again */
fsck_options_parse_config(&fsck_options, the_repository);
- if (fsck_tag_standalone(NULL, buf.buf, buf.len, &fsck_options,
- &tagged_oid, &tagged_type))
+ if (fsck_tag_standalone(the_repository, NULL, buf.buf, buf.len,
+ &fsck_options, &tagged_oid, &tagged_type))
die(_("tag on stdin did not pass our strict fsck check"));
if (verify_object_in_tag(&tagged_oid, &tagged_type) < 0)
diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c
index 3e748a55d9..dadc2ba65f 100644
--- a/builtin/unpack-objects.c
+++ b/builtin/unpack-objects.c
@@ -241,7 +241,7 @@ static int check_object(struct object *obj, enum object_type type,
obj_buf = lookup_object_buffer(obj);
if (!obj_buf)
die("Whoops! Cannot find object '%s'", oid_to_hex(&obj->oid));
- if (fsck_object(obj, obj_buf->buffer, obj_buf->size, &fsck_options))
+ if (fsck_object(the_repository, obj, obj_buf->buffer, obj_buf->size, &fsck_options))
die("fsck error in packed object");
fsck_options.walk = check_object;
if (fsck_walk(the_repository, obj, NULL, &fsck_options))
diff --git a/fsck.c b/fsck.c
index efd987dd2b..edf7a0618f 100644
--- a/fsck.c
+++ b/fsck.c
@@ -1,5 +1,3 @@
-#define USE_THE_REPOSITORY_VARIABLE
-
#include "git-compat-util.h"
#include "date.h"
#include "dir.h"
@@ -962,7 +960,8 @@ static int fsck_ident(const char **ident, const char *ident_end,
return 0;
}
-static int fsck_commit(const struct object_id *oid,
+static int fsck_commit(struct repository *repo,
+ const struct object_id *oid,
const char *buffer, unsigned long size,
struct fsck_options *options)
{
@@ -983,14 +982,14 @@ static int fsck_commit(const struct object_id *oid,
if (buffer >= buffer_end || !skip_prefix(buffer, "tree ", &buffer))
return report(options, oid, OBJ_COMMIT, FSCK_MSG_MISSING_TREE, "invalid format - expected 'tree' line");
- if (parse_oid_hex(buffer, &tree_oid, &p) || *p != '\n') {
+ if (parse_oid_hex_algop(buffer, &tree_oid, &p, repo->hash_algo) || *p != '\n') {
err = report(options, oid, OBJ_COMMIT, FSCK_MSG_BAD_TREE_SHA1, "invalid 'tree' line format - bad sha1");
if (err)
return err;
}
buffer = p + 1;
while (buffer < buffer_end && skip_prefix(buffer, "parent ", &buffer)) {
- if (parse_oid_hex(buffer, &parent_oid, &p) || *p != '\n') {
+ if (parse_oid_hex_algop(buffer, &parent_oid, &p, repo->hash_algo) || *p != '\n') {
err = report(options, oid, OBJ_COMMIT, FSCK_MSG_BAD_PARENT_SHA1, "invalid 'parent' line format - bad sha1");
if (err)
return err;
@@ -1024,16 +1023,18 @@ static int fsck_commit(const struct object_id *oid,
return 0;
}
-static int fsck_tag(const struct object_id *oid, const char *buffer,
+static int fsck_tag(struct repository *repo,
+ const struct object_id *oid, const char *buffer,
unsigned long size, struct fsck_options *options)
{
struct object_id tagged_oid;
int tagged_type;
- return fsck_tag_standalone(oid, buffer, size, options, &tagged_oid,
- &tagged_type);
+ return fsck_tag_standalone(repo, oid, buffer, size, options,
+ &tagged_oid, &tagged_type);
}
-int fsck_tag_standalone(const struct object_id *oid, const char *buffer,
+int fsck_tag_standalone(struct repository *repo,
+ const struct object_id *oid, const char *buffer,
unsigned long size, struct fsck_options *options,
struct object_id *tagged_oid,
int *tagged_type)
@@ -1057,7 +1058,7 @@ int fsck_tag_standalone(const struct object_id *oid, const char *buffer,
ret = report(options, oid, OBJ_TAG, FSCK_MSG_MISSING_OBJECT, "invalid format - expected 'object' line");
goto done;
}
- if (parse_oid_hex(buffer, tagged_oid, &p) || *p != '\n') {
+ if (parse_oid_hex_algop(buffer, tagged_oid, &p, repo->hash_algo) || *p != '\n') {
ret = report(options, oid, OBJ_TAG, FSCK_MSG_BAD_OBJECT_SHA1, "invalid 'object' line format - bad sha1");
if (ret)
goto done;
@@ -1266,16 +1267,18 @@ static int fsck_blob(const struct object_id *oid, const char *buf,
return ret;
}
-int fsck_object(struct object *obj, void *data, unsigned long size,
+int fsck_object(struct repository *repo,
+ struct object *obj, void *data, unsigned long size,
struct fsck_options *options)
{
if (!obj)
return report(options, NULL, OBJ_NONE, FSCK_MSG_BAD_OBJECT_SHA1, "no valid object to fsck");
- return fsck_buffer(&obj->oid, obj->type, data, size, options);
+ return fsck_buffer(repo, &obj->oid, obj->type, data, size, options);
}
-int fsck_buffer(const struct object_id *oid, enum object_type type,
+int fsck_buffer(struct repository *repo,
+ const struct object_id *oid, enum object_type type,
const void *data, unsigned long size,
struct fsck_options *options)
{
@@ -1284,9 +1287,9 @@ int fsck_buffer(const struct object_id *oid, enum object_type type,
if (type == OBJ_TREE)
return fsck_tree(oid, data, size, options);
if (type == OBJ_COMMIT)
- return fsck_commit(oid, data, size, options);
+ return fsck_commit(repo, oid, data, size, options);
if (type == OBJ_TAG)
- return fsck_tag(oid, data, size, options);
+ return fsck_tag(repo, oid, data, size, options);
return report(options, oid, type,
FSCK_MSG_UNKNOWN_TYPE,
diff --git a/fsck.h b/fsck.h
index 3ca1683f74..62b7c3c93a 100644
--- a/fsck.h
+++ b/fsck.h
@@ -231,14 +231,16 @@ int fsck_walk(struct repository *repo,
* Blob objects my pass a NULL data pointer, which indicates they are too large
* to fit in memory. All other types must pass a real buffer.
*/
-int fsck_object(struct object *obj, void *data, unsigned long size,
- struct fsck_options *options);
+int fsck_object(struct repository *repo,
+ struct object *obj, void *data, unsigned long size,
+ struct fsck_options *options);
/*
* Same as fsck_object(), but for when the caller doesn't have an object
* struct.
*/
-int fsck_buffer(const struct object_id *oid, enum object_type,
+int fsck_buffer(struct repository *repo,
+ const struct object_id *oid, enum object_type,
const void *data, unsigned long size,
struct fsck_options *options);
@@ -246,7 +248,8 @@ int fsck_buffer(const struct object_id *oid, enum object_type,
* fsck a tag, and pass info about it back to the caller. This is
* exposed fsck_object() internals for git-mktag(1).
*/
-int fsck_tag_standalone(const struct object_id *oid, const char *buffer,
+int fsck_tag_standalone(struct repository *repo,
+ const struct object_id *oid, const char *buffer,
unsigned long size, struct fsck_options *options,
struct object_id *tagged_oid,
int *tag_type);
diff --git a/object-file.c b/object-file.c
index ecbcc501dd..f58acaa939 100644
--- a/object-file.c
+++ b/object-file.c
@@ -1283,7 +1283,8 @@ static int index_mem(struct index_state *istate,
opts.strict = 1;
opts.error_func = hash_format_check_report;
- if (fsck_buffer(null_oid(istate->repo->hash_algo), type, buf, size, &opts))
+ if (fsck_buffer(the_repository, null_oid(istate->repo->hash_algo),
+ type, buf, size, &opts))
die(_("refusing to create malformed object"));
fsck_finish(the_repository, &opts);
}
--
2.53.0.1055.ga2ffed1127.dirty
^ permalink raw reply related [flat|nested] 33+ messages in thread* [PATCH 06/14] builtin/fsck: fix trivial dependence on `the_repository`
2026-03-20 11:47 [PATCH 00/14] fsck: drop use of `the_repository` Patrick Steinhardt
` (4 preceding siblings ...)
2026-03-20 11:47 ` [PATCH 05/14] fsck: stop relying on global state via `parse_oid_hex()` Patrick Steinhardt
@ 2026-03-20 11:47 ` Patrick Steinhardt
2026-03-20 11:47 ` [PATCH 07/14] builtin/fsck: stop using `the_repository` when snapshotting refs Patrick Steinhardt
` (8 subsequent siblings)
14 siblings, 0 replies; 33+ messages in thread
From: Patrick Steinhardt @ 2026-03-20 11:47 UTC (permalink / raw)
To: git
We have a bunch of sites in "builtin/fsck.c" that depend on
`the_repository` even though we already have a repository available, or
in cases where we can trivially make it available.
Refactor such sites to use the context-provided repository instead.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
builtin/fsck.c | 116 +++++++++++++++++++++++++++++----------------------------
1 file changed, 59 insertions(+), 57 deletions(-)
diff --git a/builtin/fsck.c b/builtin/fsck.c
index ff9951c10c..8a52ad02ae 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -184,9 +184,9 @@ static void mark_object_reachable(struct object *obj)
mark_object(obj, OBJ_ANY, NULL, NULL);
}
-static int traverse_one_object(struct object *obj)
+static int traverse_one_object(struct repository *repo, struct object *obj)
{
- int result = fsck_walk(the_repository, obj, obj, &fsck_walk_options);
+ int result = fsck_walk(repo, obj, obj, &fsck_walk_options);
if (obj->type == OBJ_TREE) {
struct tree *tree = (struct tree *)obj;
@@ -195,16 +195,16 @@ static int traverse_one_object(struct object *obj)
return result;
}
-static int traverse_reachable(void)
+static int traverse_reachable(struct repository *repo)
{
struct progress *progress = NULL;
unsigned int nr = 0;
int result = 0;
if (show_progress)
- progress = start_delayed_progress(the_repository,
+ progress = start_delayed_progress(repo,
_("Checking connectivity"), 0);
while (pending.nr) {
- result |= traverse_one_object(object_array_pop(&pending));
+ result |= traverse_one_object(repo, object_array_pop(&pending));
display_progress(progress, ++nr);
}
stop_progress(&progress);
@@ -254,7 +254,7 @@ static int mark_unreachable_referents(const struct object_id *oid,
/*
* Check a single reachable object
*/
-static void check_reachable_object(struct object *obj)
+static void check_reachable_object(struct repository *repo, struct object *obj)
{
/*
* We obviously want the object to be parsed,
@@ -262,9 +262,9 @@ static void check_reachable_object(struct object *obj)
* do a full fsck
*/
if (!(obj->flags & HAS_OBJ)) {
- if (is_promisor_object(the_repository, &obj->oid))
+ if (is_promisor_object(repo, &obj->oid))
return;
- if (has_object_pack(the_repository, &obj->oid))
+ if (has_object_pack(repo, &obj->oid))
return; /* it is in pack - forget about it */
printf_ln(_("missing %s %s"),
printable_type(&obj->oid, obj->type),
@@ -277,7 +277,7 @@ static void check_reachable_object(struct object *obj)
/*
* Check a single unreachable object
*/
-static void check_unreachable_object(struct object *obj)
+static void check_unreachable_object(struct repository *repo, struct object *obj)
{
/*
* Missing unreachable object? Ignore it. It's not like
@@ -317,19 +317,19 @@ static void check_unreachable_object(struct object *obj)
printable_type(&obj->oid, obj->type),
describe_object(&obj->oid));
if (write_lost_and_found) {
- char *filename = repo_git_path(the_repository, "lost-found/%s/%s",
+ char *filename = repo_git_path(repo, "lost-found/%s/%s",
obj->type == OBJ_COMMIT ? "commit" : "other",
describe_object(&obj->oid));
FILE *f;
- if (safe_create_leading_directories_const(the_repository, filename)) {
+ if (safe_create_leading_directories_const(repo, filename)) {
error(_("could not create lost-found"));
free(filename);
return;
}
f = xfopen(filename, "w");
if (obj->type == OBJ_BLOB) {
- if (odb_stream_blob_to_fd(the_repository->objects, fileno(f),
+ if (odb_stream_blob_to_fd(repo->objects, fileno(f),
&obj->oid, NULL, 1))
die_errno(_("could not write '%s'"), filename);
} else
@@ -349,23 +349,23 @@ static void check_unreachable_object(struct object *obj)
*/
}
-static void check_object(struct object *obj)
+static void check_object(struct repository *repo, struct object *obj)
{
if (verbose)
fprintf_ln(stderr, _("Checking %s"), describe_object(&obj->oid));
if (obj->flags & REACHABLE)
- check_reachable_object(obj);
+ check_reachable_object(repo, obj);
else
- check_unreachable_object(obj);
+ check_unreachable_object(repo, obj);
}
-static void check_connectivity(void)
+static void check_connectivity(struct repository *repo)
{
int i, max;
/* Traverse the pending reachable objects */
- traverse_reachable();
+ traverse_reachable(repo);
/*
* With --connectivity-only, we won't have actually opened and marked
@@ -383,20 +383,20 @@ static void check_connectivity(void)
* and ignore any that weren't present in our earlier
* traversal.
*/
- odb_for_each_object(the_repository->objects, NULL,
+ odb_for_each_object(repo->objects, NULL,
mark_unreachable_referents, NULL, 0);
}
/* Look up all the requirements, warn about missing objects.. */
- max = get_max_object_index(the_repository);
+ max = get_max_object_index(repo);
if (verbose)
fprintf_ln(stderr, _("Checking connectivity (%d objects)"), max);
for (i = 0; i < max; i++) {
- struct object *obj = get_indexed_object(the_repository, i);
+ struct object *obj = get_indexed_object(repo, i);
if (obj)
- check_object(obj);
+ check_object(repo, obj);
}
}
@@ -580,7 +580,8 @@ static int fsck_handle_ref(const struct reference *ref, void *cb_data UNUSED)
return 0;
}
-static void snapshot_refs(struct snapshot *snap, int argc, const char **argv)
+static void snapshot_refs(struct repository *repo, struct snapshot *snap,
+ int argc, const char **argv)
{
struct refs_for_each_ref_options opts = {
.flags = REFS_FOR_EACH_INCLUDE_BROKEN,
@@ -592,7 +593,7 @@ static void snapshot_refs(struct snapshot *snap, int argc, const char **argv)
for (int i = 0; i < argc; i++) {
const char *arg = argv[i];
struct object_id oid;
- if (!repo_get_oid(the_repository, arg, &oid)) {
+ if (!repo_get_oid(repo, arg, &oid)) {
struct reference ref = {
.name = arg,
.oid = &oid,
@@ -610,7 +611,7 @@ static void snapshot_refs(struct snapshot *snap, int argc, const char **argv)
return;
}
- refs_for_each_ref_ext(get_main_ref_store(the_repository),
+ refs_for_each_ref_ext(get_main_ref_store(repo),
snapshot_ref, snap, &opts);
worktrees = get_worktrees();
@@ -620,7 +621,7 @@ static void snapshot_refs(struct snapshot *snap, int argc, const char **argv)
strbuf_worktree_ref(wt, &refname, "HEAD");
- head_points_at = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
+ head_points_at = refs_resolve_ref_unsafe(get_main_ref_store(repo),
refname.buf, 0, &head_oid, NULL);
if (head_points_at && !is_null_oid(&head_oid)) {
@@ -780,7 +781,7 @@ static void fsck_source(struct odb_source *source)
fprintf_ln(stderr, _("Checking object directory"));
if (show_progress)
- progress = start_progress(the_repository,
+ progress = start_progress(source->odb->repo,
_("Checking object directories"), 256);
for_each_loose_file_in_source(source, fsck_loose,
@@ -789,7 +790,8 @@ static void fsck_source(struct odb_source *source)
stop_progress(&progress);
}
-static int fsck_cache_tree(struct cache_tree *it, const char *index_path)
+static int fsck_cache_tree(struct repository *repo, struct cache_tree *it,
+ const char *index_path)
{
int i;
int err = 0;
@@ -798,7 +800,7 @@ static int fsck_cache_tree(struct cache_tree *it, const char *index_path)
fprintf_ln(stderr, _("Checking cache tree of %s"), index_path);
if (0 <= it->entry_count) {
- struct object *obj = parse_object(the_repository, &it->oid);
+ struct object *obj = parse_object(repo, &it->oid);
if (!obj) {
error(_("%s: invalid sha1 pointer in cache-tree of %s"),
oid_to_hex(&it->oid), index_path);
@@ -812,7 +814,7 @@ static int fsck_cache_tree(struct cache_tree *it, const char *index_path)
err |= objerror(obj, _("non-tree in cache-tree"));
}
for (i = 0; i < it->subtree_nr; i++)
- err |= fsck_cache_tree(it->down[i]->cache_tree, index_path);
+ err |= fsck_cache_tree(repo, it->down[i]->cache_tree, index_path);
return err;
}
@@ -838,7 +840,7 @@ static int fsck_resolve_undo(struct index_state *istate,
if (!ru->mode[i] || !S_ISREG(ru->mode[i]))
continue;
- obj = parse_object(the_repository, &ru->oid[i]);
+ obj = parse_object(istate->repo, &ru->oid[i]);
if (!obj) {
error(_("%s: invalid sha1 pointer in resolve-undo of %s"),
oid_to_hex(&ru->oid[i]),
@@ -870,7 +872,7 @@ static void fsck_index(struct index_state *istate, const char *index_path,
mode = istate->cache[i]->ce_mode;
if (S_ISGITLINK(mode))
continue;
- blob = lookup_blob(the_repository,
+ blob = lookup_blob(istate->repo,
&istate->cache[i]->oid);
if (!blob)
continue;
@@ -883,7 +885,7 @@ static void fsck_index(struct index_state *istate, const char *index_path,
mark_object_reachable(obj);
}
if (istate->cache_tree)
- fsck_cache_tree(istate->cache_tree, index_path);
+ fsck_cache_tree(istate->repo, istate->cache_tree, index_path);
fsck_resolve_undo(istate, index_path);
}
@@ -906,7 +908,7 @@ static int check_pack_rev_indexes(struct repository *r, int show_progress)
if (show_progress) {
repo_for_each_pack(r, p)
pack_count++;
- progress = start_delayed_progress(the_repository,
+ progress = start_delayed_progress(r,
"Verifying reverse pack-indexes", pack_count);
pack_count = 0;
}
@@ -986,7 +988,7 @@ static struct option fsck_opts[] = {
int cmd_fsck(int argc,
const char **argv,
const char *prefix,
- struct repository *repo UNUSED)
+ struct repository *repo)
{
struct odb_source *source;
struct snapshot snap = {
@@ -1023,11 +1025,11 @@ int cmd_fsck(int argc,
if (name_objects)
fsck_enable_object_names(&fsck_walk_options);
- fsck_options_parse_config(&fsck_obj_options, the_repository);
- prepare_repo_settings(the_repository);
+ fsck_options_parse_config(&fsck_obj_options, repo);
+ prepare_repo_settings(repo);
if (check_references)
- fsck_refs(the_repository);
+ fsck_refs(repo);
/*
* Take a snapshot of the refs before walking objects to avoid looking
@@ -1035,17 +1037,17 @@ int cmd_fsck(int argc,
* objects. We can still walk over new objects that are added during the
* execution of fsck but won't miss any objects that were reachable.
*/
- snapshot_refs(&snap, argc, argv);
+ snapshot_refs(repo, &snap, argc, argv);
/* Ensure we get a "fresh" view of the odb */
- odb_reprepare(the_repository->objects);
+ odb_reprepare(repo->objects);
if (connectivity_only) {
- odb_for_each_object(the_repository->objects, NULL,
+ odb_for_each_object(repo->objects, NULL,
mark_object_for_connectivity, NULL, 0);
} else {
- odb_prepare_alternates(the_repository->objects);
- for (source = the_repository->objects->sources; source; source = source->next)
+ odb_prepare_alternates(repo->objects);
+ for (source = repo->objects->sources; source; source = source->next)
fsck_source(source);
if (check_full) {
@@ -1054,19 +1056,19 @@ int cmd_fsck(int argc,
struct progress *progress = NULL;
if (show_progress) {
- repo_for_each_pack(the_repository, p) {
+ repo_for_each_pack(repo, p) {
if (open_pack_index(p))
continue;
total += p->num_objects;
}
- progress = start_progress(the_repository,
+ progress = start_progress(repo,
_("Checking objects"), total);
}
- repo_for_each_pack(the_repository, p) {
+ repo_for_each_pack(repo, p) {
/* verify gives error messages itself */
- if (verify_pack(the_repository,
+ if (verify_pack(repo,
p, fsck_obj_buffer,
progress, count))
errors_found |= ERROR_PACK;
@@ -1075,7 +1077,7 @@ int cmd_fsck(int argc,
stop_progress(&progress);
}
- if (fsck_finish(the_repository, &fsck_obj_options))
+ if (fsck_finish(repo, &fsck_obj_options))
errors_found |= ERROR_OBJECT;
}
@@ -1100,7 +1102,7 @@ int cmd_fsck(int argc,
for (p = worktrees; *p; p++) {
struct worktree *wt = *p;
struct index_state istate =
- INDEX_STATE_INIT(the_repository);
+ INDEX_STATE_INIT(repo);
char *path, *wt_gitdir;
/*
@@ -1121,17 +1123,17 @@ int cmd_fsck(int argc,
free_worktrees(worktrees);
}
- errors_found |= check_pack_rev_indexes(the_repository, show_progress);
- if (verify_bitmap_files(the_repository))
+ errors_found |= check_pack_rev_indexes(repo, show_progress);
+ if (verify_bitmap_files(repo))
errors_found |= ERROR_BITMAP;
- check_connectivity();
+ check_connectivity(repo);
- if (the_repository->settings.core_commit_graph) {
+ if (repo->settings.core_commit_graph) {
struct child_process commit_graph_verify = CHILD_PROCESS_INIT;
- odb_prepare_alternates(the_repository->objects);
- for (source = the_repository->objects->sources; source; source = source->next) {
+ odb_prepare_alternates(repo->objects);
+ for (source = repo->objects->sources; source; source = source->next) {
child_process_init(&commit_graph_verify);
commit_graph_verify.git_cmd = 1;
strvec_pushl(&commit_graph_verify.args, "commit-graph",
@@ -1145,11 +1147,11 @@ int cmd_fsck(int argc,
}
}
- if (the_repository->settings.core_multi_pack_index) {
+ if (repo->settings.core_multi_pack_index) {
struct child_process midx_verify = CHILD_PROCESS_INIT;
- odb_prepare_alternates(the_repository->objects);
- for (source = the_repository->objects->sources; source; source = source->next) {
+ odb_prepare_alternates(repo->objects);
+ for (source = repo->objects->sources; source; source = source->next) {
child_process_init(&midx_verify);
midx_verify.git_cmd = 1;
strvec_pushl(&midx_verify.args, "multi-pack-index",
--
2.53.0.1055.ga2ffed1127.dirty
^ permalink raw reply related [flat|nested] 33+ messages in thread* [PATCH 07/14] builtin/fsck: stop using `the_repository` when snapshotting refs
2026-03-20 11:47 [PATCH 00/14] fsck: drop use of `the_repository` Patrick Steinhardt
` (5 preceding siblings ...)
2026-03-20 11:47 ` [PATCH 06/14] builtin/fsck: fix trivial dependence on `the_repository` Patrick Steinhardt
@ 2026-03-20 11:47 ` Patrick Steinhardt
2026-03-20 11:47 ` [PATCH 08/14] builtin/fsck: stop using `the_repository` when checking refs Patrick Steinhardt
` (7 subsequent siblings)
14 siblings, 0 replies; 33+ messages in thread
From: Patrick Steinhardt @ 2026-03-20 11:47 UTC (permalink / raw)
To: git
We depedn on `the_repository` when snapshotting refs. Refactor this to
use a context-provided repository instead that is injected via the
`struct snapshot_ref_data`.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
builtin/fsck.c | 22 ++++++++++++++++------
1 file changed, 16 insertions(+), 6 deletions(-)
diff --git a/builtin/fsck.c b/builtin/fsck.c
index 8a52ad02ae..00476bb921 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -532,14 +532,20 @@ struct snapshot {
/* TODO: Consider also snapshotting the index of each worktree. */
};
+struct snapshot_ref_data {
+ struct repository *repo;
+ struct snapshot *snap;
+};
+
static int snapshot_ref(const struct reference *ref, void *cb_data)
{
- struct snapshot *snap = cb_data;
+ struct snapshot_ref_data *data = cb_data;
+ struct snapshot *snap = data->snap;
struct object *obj;
- obj = parse_object(the_repository, ref->oid);
+ obj = parse_object(data->repo, ref->oid);
if (!obj) {
- if (is_promisor_object(the_repository, ref->oid)) {
+ if (is_promisor_object(data->repo, ref->oid)) {
/*
* Increment default_refs anyway, because this is a
* valid ref.
@@ -586,6 +592,10 @@ static void snapshot_refs(struct repository *repo, struct snapshot *snap,
struct refs_for_each_ref_options opts = {
.flags = REFS_FOR_EACH_INCLUDE_BROKEN,
};
+ struct snapshot_ref_data data = {
+ .repo = repo,
+ .snap = snap,
+ };
struct worktree **worktrees, **p;
const char *head_points_at;
struct object_id head_oid;
@@ -599,7 +609,7 @@ static void snapshot_refs(struct repository *repo, struct snapshot *snap,
.oid = &oid,
};
- snapshot_ref(&ref, snap);
+ snapshot_ref(&ref, &data);
continue;
}
error(_("invalid parameter: expected sha1, got '%s'"), arg);
@@ -612,7 +622,7 @@ static void snapshot_refs(struct repository *repo, struct snapshot *snap,
}
refs_for_each_ref_ext(get_main_ref_store(repo),
- snapshot_ref, snap, &opts);
+ snapshot_ref, &data, &opts);
worktrees = get_worktrees();
for (p = worktrees; *p; p++) {
@@ -630,7 +640,7 @@ static void snapshot_refs(struct repository *repo, struct snapshot *snap,
.oid = &head_oid,
};
- snapshot_ref(&ref, snap);
+ snapshot_ref(&ref, &data);
}
strbuf_release(&refname);
--
2.53.0.1055.ga2ffed1127.dirty
^ permalink raw reply related [flat|nested] 33+ messages in thread* [PATCH 08/14] builtin/fsck: stop using `the_repository` when checking refs
2026-03-20 11:47 [PATCH 00/14] fsck: drop use of `the_repository` Patrick Steinhardt
` (6 preceding siblings ...)
2026-03-20 11:47 ` [PATCH 07/14] builtin/fsck: stop using `the_repository` when snapshotting refs Patrick Steinhardt
@ 2026-03-20 11:47 ` Patrick Steinhardt
2026-03-20 11:47 ` [PATCH 09/14] builtin/fsck: stop using `the_repository` when checking reflogs Patrick Steinhardt
` (6 subsequent siblings)
14 siblings, 0 replies; 33+ messages in thread
From: Patrick Steinhardt @ 2026-03-20 11:47 UTC (permalink / raw)
To: git
We implicitly rely on `the_repository` when checking refs. Refactor this
to instead inject the repository via the callback payload.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
builtin/fsck.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/builtin/fsck.c b/builtin/fsck.c
index 00476bb921..63cd58e58b 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -573,11 +573,12 @@ static int snapshot_ref(const struct reference *ref, void *cb_data)
return 0;
}
-static int fsck_handle_ref(const struct reference *ref, void *cb_data UNUSED)
+static int fsck_handle_ref(const struct reference *ref, void *cb_data)
{
+ struct repository *repo = cb_data;
struct object *obj;
- obj = parse_object(the_repository, ref->oid);
+ obj = parse_object(repo, ref->oid);
obj->flags |= USED;
fsck_put_object_name(&fsck_walk_options,
ref->oid, "%s", ref->name);
@@ -664,7 +665,7 @@ static void free_snapshot_refs(struct snapshot *snap)
free(snap->ref);
}
-static void process_refs(struct snapshot *snap)
+static void process_refs(struct repository *repo, struct snapshot *snap)
{
struct worktree **worktrees, **p;
@@ -673,7 +674,7 @@ static void process_refs(struct snapshot *snap)
.name = snap->ref[i].refname,
.oid = &snap->ref[i].oid,
};
- fsck_handle_ref(&ref, NULL);
+ fsck_handle_ref(&ref, repo);
}
if (include_reflogs) {
@@ -1092,7 +1093,7 @@ int cmd_fsck(int argc,
}
/* Process the snapshotted refs and the reflogs. */
- process_refs(&snap);
+ process_refs(repo, &snap);
/* If not given any explicit objects, process index files too. */
if (!argc)
--
2.53.0.1055.ga2ffed1127.dirty
^ permalink raw reply related [flat|nested] 33+ messages in thread* [PATCH 09/14] builtin/fsck: stop using `the_repository` when checking reflogs
2026-03-20 11:47 [PATCH 00/14] fsck: drop use of `the_repository` Patrick Steinhardt
` (7 preceding siblings ...)
2026-03-20 11:47 ` [PATCH 08/14] builtin/fsck: stop using `the_repository` when checking refs Patrick Steinhardt
@ 2026-03-20 11:47 ` Patrick Steinhardt
2026-03-20 11:47 ` [PATCH 10/14] builtin/fsck: stop using `the_repository` with loose objects Patrick Steinhardt
` (5 subsequent siblings)
14 siblings, 0 replies; 33+ messages in thread
From: Patrick Steinhardt @ 2026-03-20 11:47 UTC (permalink / raw)
To: git
We implicitly rely on `the_repository` when checking reflogs. Refactor
this to instead inject the repository via the callback payload.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
builtin/fsck.c | 24 ++++++++++++++----------
1 file changed, 14 insertions(+), 10 deletions(-)
diff --git a/builtin/fsck.c b/builtin/fsck.c
index 63cd58e58b..ea441b072e 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -467,13 +467,14 @@ static int fsck_obj_buffer(const struct object_id *oid, enum object_type type,
static int default_refs;
-static void fsck_handle_reflog_oid(const char *refname, struct object_id *oid,
- timestamp_t timestamp)
+static void fsck_handle_reflog_oid(struct repository *repo,
+ const char *refname, struct object_id *oid,
+ timestamp_t timestamp)
{
struct object *obj;
if (!is_null_oid(oid)) {
- obj = lookup_object(the_repository, oid);
+ obj = lookup_object(repo, oid);
if (obj && (obj->flags & HAS_OBJ)) {
if (timestamp)
fsck_put_object_name(&fsck_walk_options, oid,
@@ -481,7 +482,7 @@ static void fsck_handle_reflog_oid(const char *refname, struct object_id *oid,
refname, timestamp);
obj->flags |= USED;
mark_object_reachable(obj);
- } else if (!is_promisor_object(the_repository, oid)) {
+ } else if (!is_promisor_object(repo, oid)) {
error(_("%s: invalid reflog entry %s"),
refname, oid_to_hex(oid));
errors_found |= ERROR_REACHABLE;
@@ -493,8 +494,10 @@ static int fsck_handle_reflog_ent(const char *refname,
struct object_id *ooid, struct object_id *noid,
const char *email UNUSED,
timestamp_t timestamp, int tz UNUSED,
- const char *message UNUSED, void *cb_data UNUSED)
+ const char *message UNUSED, void *cb_data)
{
+ struct repository *repo = cb_data;
+
if (now && timestamp > now)
return 0;
@@ -502,19 +505,20 @@ static int fsck_handle_reflog_ent(const char *refname,
fprintf_ln(stderr, _("Checking reflog %s->%s"),
oid_to_hex(ooid), oid_to_hex(noid));
- fsck_handle_reflog_oid(refname, ooid, 0);
- fsck_handle_reflog_oid(refname, noid, timestamp);
+ fsck_handle_reflog_oid(repo, refname, ooid, 0);
+ fsck_handle_reflog_oid(repo, refname, noid, timestamp);
return 0;
}
static int fsck_handle_reflog(const char *logname, void *cb_data)
{
struct strbuf refname = STRBUF_INIT;
+ struct worktree *wt = cb_data;
- strbuf_worktree_ref(cb_data, &refname, logname);
- refs_for_each_reflog_ent(get_main_ref_store(the_repository),
+ strbuf_worktree_ref(wt, &refname, logname);
+ refs_for_each_reflog_ent(get_main_ref_store(wt->repo),
refname.buf, fsck_handle_reflog_ent,
- NULL);
+ wt->repo);
strbuf_release(&refname);
return 0;
}
--
2.53.0.1055.ga2ffed1127.dirty
^ permalink raw reply related [flat|nested] 33+ messages in thread* [PATCH 10/14] builtin/fsck: stop using `the_repository` with loose objects
2026-03-20 11:47 [PATCH 00/14] fsck: drop use of `the_repository` Patrick Steinhardt
` (8 preceding siblings ...)
2026-03-20 11:47 ` [PATCH 09/14] builtin/fsck: stop using `the_repository` when checking reflogs Patrick Steinhardt
@ 2026-03-20 11:47 ` Patrick Steinhardt
2026-03-20 11:47 ` [PATCH 11/14] builtin/fsck: stop using `the_repository` when checking packed objects Patrick Steinhardt
` (4 subsequent siblings)
14 siblings, 0 replies; 33+ messages in thread
From: Patrick Steinhardt @ 2026-03-20 11:47 UTC (permalink / raw)
To: git
We depend on `the_repository` when performing consistency checks for
loose objects. Refactor this to use a context-provided repository
instead that is injected via the `struct for_each_loose_cb`.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
builtin/fsck.c | 26 +++++++++++++++-----------
1 file changed, 15 insertions(+), 11 deletions(-)
diff --git a/builtin/fsck.c b/builtin/fsck.c
index ea441b072e..83299c583e 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -400,7 +400,9 @@ static void check_connectivity(struct repository *repo)
}
}
-static int fsck_obj(struct object *obj, void *buffer, unsigned long size)
+static int fsck_obj(struct repository *repo,
+ struct object *obj,
+ void *buffer, unsigned long size)
{
int err;
@@ -413,9 +415,9 @@ static int fsck_obj(struct object *obj, void *buffer, unsigned long size)
printable_type(&obj->oid, obj->type),
describe_object(&obj->oid));
- if (fsck_walk(the_repository, obj, NULL, &fsck_obj_options))
+ if (fsck_walk(repo, obj, NULL, &fsck_obj_options))
objerror(obj, _("broken links"));
- err = fsck_object(the_repository, obj, buffer, size, &fsck_obj_options);
+ err = fsck_object(repo, obj, buffer, size, &fsck_obj_options);
if (err)
goto out;
@@ -462,7 +464,7 @@ static int fsck_obj_buffer(const struct object_id *oid, enum object_type type,
}
obj->flags &= ~(REACHABLE | SEEN);
obj->flags |= HAS_OBJ;
- return fsck_obj(obj, buffer, size);
+ return fsck_obj(the_repository, obj, buffer, size);
}
static int default_refs;
@@ -710,27 +712,28 @@ static void process_refs(struct repository *repo, struct snapshot *snap)
}
}
-struct for_each_loose_cb
-{
+struct for_each_loose_cb {
+ struct repository *repo;
struct progress *progress;
};
static int fsck_loose(const struct object_id *oid, const char *path,
- void *data UNUSED)
+ void *cb_data)
{
+ struct for_each_loose_cb *data = cb_data;
struct object *obj;
enum object_type type = OBJ_NONE;
unsigned long size;
void *contents = NULL;
int eaten;
struct object_info oi = OBJECT_INFO_INIT;
- struct object_id real_oid = *null_oid(the_hash_algo);
+ struct object_id real_oid = *null_oid(data->repo->hash_algo);
int err = 0;
oi.sizep = &size;
oi.typep = &type;
- if (read_loose_object(the_repository, path, oid, &real_oid, &contents, &oi) < 0) {
+ if (read_loose_object(data->repo, path, oid, &real_oid, &contents, &oi) < 0) {
if (contents && !oideq(&real_oid, oid))
err = error(_("%s: hash-path mismatch, found at: %s"),
oid_to_hex(&real_oid), path);
@@ -747,7 +750,7 @@ static int fsck_loose(const struct object_id *oid, const char *path,
if (!contents && type != OBJ_BLOB)
BUG("read_loose_object streamed a non-blob");
- obj = parse_object_buffer(the_repository, oid, type, size,
+ obj = parse_object_buffer(data->repo, oid, type, size,
contents, &eaten);
if (!obj) {
@@ -761,7 +764,7 @@ static int fsck_loose(const struct object_id *oid, const char *path,
obj->flags &= ~(REACHABLE | SEEN);
obj->flags |= HAS_OBJ;
- if (fsck_obj(obj, contents, size))
+ if (fsck_obj(data->repo, obj, contents, size))
errors_found |= ERROR_OBJECT;
if (!eaten)
@@ -789,6 +792,7 @@ static void fsck_source(struct odb_source *source)
{
struct progress *progress = NULL;
struct for_each_loose_cb cb_data = {
+ .repo = source->odb->repo,
.progress = progress,
};
--
2.53.0.1055.ga2ffed1127.dirty
^ permalink raw reply related [flat|nested] 33+ messages in thread* [PATCH 11/14] builtin/fsck: stop using `the_repository` when checking packed objects
2026-03-20 11:47 [PATCH 00/14] fsck: drop use of `the_repository` Patrick Steinhardt
` (9 preceding siblings ...)
2026-03-20 11:47 ` [PATCH 10/14] builtin/fsck: stop using `the_repository` with loose objects Patrick Steinhardt
@ 2026-03-20 11:47 ` Patrick Steinhardt
2026-03-20 11:47 ` [PATCH 12/14] builtin/fsck: stop using `the_repository` when marking objects Patrick Steinhardt
` (3 subsequent siblings)
14 siblings, 0 replies; 33+ messages in thread
From: Patrick Steinhardt @ 2026-03-20 11:47 UTC (permalink / raw)
To: git
We implicitly rely on `the_repository` when checking objects part of a
packfile. These objects are iterated over via `verify_pack()`, which is
provided by the packfile subsystem, and a callback function is then
invoked for each of the objects in that specific pack.
Unfortunately, it is not possible to provide a payload to the callback
function. Refactor `verify_pack()` to accept a payload that is passed
through to the callback so that we can inject the repository and get rid
of the use of `the_repository`.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
builtin/fsck.c | 13 +++++++------
pack-check.c | 7 ++++---
pack.h | 9 +++++++--
3 files changed, 18 insertions(+), 11 deletions(-)
diff --git a/builtin/fsck.c b/builtin/fsck.c
index 83299c583e..874af76e05 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -448,15 +448,16 @@ static int fsck_obj(struct repository *repo,
}
static int fsck_obj_buffer(const struct object_id *oid, enum object_type type,
- unsigned long size, void *buffer, int *eaten)
+ unsigned long size, void *buffer, int *eaten, void *cb_data)
{
+ struct repository *repo = cb_data;
+ struct object *obj;
+
/*
* Note, buffer may be NULL if type is OBJ_BLOB. See
* verify_packfile(), data_valid variable for details.
*/
- struct object *obj;
- obj = parse_object_buffer(the_repository, oid, type, size, buffer,
- eaten);
+ obj = parse_object_buffer(repo, oid, type, size, buffer, eaten);
if (!obj) {
errors_found |= ERROR_OBJECT;
return error(_("%s: object corrupt or missing"),
@@ -464,7 +465,7 @@ static int fsck_obj_buffer(const struct object_id *oid, enum object_type type,
}
obj->flags &= ~(REACHABLE | SEEN);
obj->flags |= HAS_OBJ;
- return fsck_obj(the_repository, obj, buffer, size);
+ return fsck_obj(repo, obj, buffer, size);
}
static int default_refs;
@@ -1088,7 +1089,7 @@ int cmd_fsck(int argc,
repo_for_each_pack(repo, p) {
/* verify gives error messages itself */
if (verify_pack(repo,
- p, fsck_obj_buffer,
+ p, fsck_obj_buffer, repo,
progress, count))
errors_found |= ERROR_PACK;
count += p->num_objects;
diff --git a/pack-check.c b/pack-check.c
index 7378c80730..79992bb509 100644
--- a/pack-check.c
+++ b/pack-check.c
@@ -53,6 +53,7 @@ static int verify_packfile(struct repository *r,
struct packed_git *p,
struct pack_window **w_curs,
verify_fn fn,
+ void *fn_data,
struct progress *progress, uint32_t base_count)
{
@@ -161,7 +162,7 @@ static int verify_packfile(struct repository *r,
oid_to_hex(&oid), p->pack_name);
else if (fn) {
int eaten = 0;
- err |= fn(&oid, type, size, data, &eaten);
+ err |= fn(&oid, type, size, data, &eaten, fn_data);
if (eaten)
data = NULL;
}
@@ -192,7 +193,7 @@ int verify_pack_index(struct packed_git *p)
return err;
}
-int verify_pack(struct repository *r, struct packed_git *p, verify_fn fn,
+int verify_pack(struct repository *r, struct packed_git *p, verify_fn fn, void *fn_data,
struct progress *progress, uint32_t base_count)
{
int err = 0;
@@ -202,7 +203,7 @@ int verify_pack(struct repository *r, struct packed_git *p, verify_fn fn,
if (!p->index_data)
return -1;
- err |= verify_packfile(r, p, &w_curs, fn, progress, base_count);
+ err |= verify_packfile(r, p, &w_curs, fn, fn_data, progress, base_count);
unuse_pack(&w_curs);
return err;
diff --git a/pack.h b/pack.h
index ec76472e49..1cde92082b 100644
--- a/pack.h
+++ b/pack.h
@@ -85,7 +85,11 @@ struct pack_idx_entry {
struct progress;
/* Note, the data argument could be NULL if object type is blob */
-typedef int (*verify_fn)(const struct object_id *, enum object_type, unsigned long, void*, int*);
+typedef int (*verify_fn)(const struct object_id *oid,
+ enum object_type type,
+ unsigned long size,
+ void *buffer, int *eaten,
+ void *fn_data);
const char *write_idx_file(struct repository *repo,
const char *index_name,
@@ -95,7 +99,8 @@ const char *write_idx_file(struct repository *repo,
const unsigned char *sha1);
int check_pack_crc(struct packed_git *p, struct pack_window **w_curs, off_t offset, off_t len, unsigned int nr);
int verify_pack_index(struct packed_git *);
-int verify_pack(struct repository *, struct packed_git *, verify_fn fn, struct progress *, uint32_t);
+int verify_pack(struct repository *, struct packed_git *, verify_fn fn, void *fn_data,
+ struct progress *, uint32_t);
off_t write_pack_header(struct hashfile *f, uint32_t);
void fixup_pack_header_footer(const struct git_hash_algo *, int,
unsigned char *, const char *, uint32_t,
--
2.53.0.1055.ga2ffed1127.dirty
^ permalink raw reply related [flat|nested] 33+ messages in thread* [PATCH 12/14] builtin/fsck: stop using `the_repository` when marking objects
2026-03-20 11:47 [PATCH 00/14] fsck: drop use of `the_repository` Patrick Steinhardt
` (10 preceding siblings ...)
2026-03-20 11:47 ` [PATCH 11/14] builtin/fsck: stop using `the_repository` when checking packed objects Patrick Steinhardt
@ 2026-03-20 11:47 ` Patrick Steinhardt
2026-03-20 11:47 ` [PATCH 13/14] fsck: provide repository in `struct fsck_report_object` Patrick Steinhardt
` (2 subsequent siblings)
14 siblings, 0 replies; 33+ messages in thread
From: Patrick Steinhardt @ 2026-03-20 11:47 UTC (permalink / raw)
To: git
We implicitly rely on `the_repository` when marking objects for
connectivity. Refactor this to instead inject the repository via the
callback payload.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
builtin/fsck.c | 55 +++++++++++++++++++++++++++++++++++--------------------
1 file changed, 35 insertions(+), 20 deletions(-)
diff --git a/builtin/fsck.c b/builtin/fsck.c
index 874af76e05..b15708d155 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -123,10 +123,16 @@ static int fsck_objects_error_func(struct fsck_options *o UNUSED,
static struct object_array pending;
+struct mark_object_data {
+ struct repository *repo;
+ struct object *parent;
+};
+
static int mark_object(struct object *obj, enum object_type type,
- void *data, struct fsck_options *options UNUSED)
+ void *cb_data, struct fsck_options *options UNUSED)
{
- struct object *parent = data;
+ struct mark_object_data *data = cb_data;
+ struct object *parent = data->parent;
/*
* The only case data is NULL or type is OBJ_ANY is when
@@ -153,7 +159,7 @@ static int mark_object(struct object *obj, enum object_type type,
return 0;
obj->flags |= REACHABLE;
- if (is_promisor_object(the_repository, &obj->oid))
+ if (is_promisor_object(data->repo, &obj->oid))
/*
* Further recursion does not need to be performed on this
* object since it is a promisor object (so it does not need to
@@ -162,7 +168,7 @@ static int mark_object(struct object *obj, enum object_type type,
return 0;
if (!(obj->flags & HAS_OBJ)) {
- if (parent && !odb_has_object(the_repository->objects, &obj->oid,
+ if (parent && !odb_has_object(data->repo->objects, &obj->oid,
HAS_OBJECT_RECHECK_PACKED)) {
printf_ln(_("broken link from %7s %s\n"
" to %7s %s"),
@@ -179,14 +185,21 @@ static int mark_object(struct object *obj, enum object_type type,
return 0;
}
-static void mark_object_reachable(struct object *obj)
+static void mark_object_reachable(struct repository *repo, struct object *obj)
{
- mark_object(obj, OBJ_ANY, NULL, NULL);
+ struct mark_object_data data = {
+ .repo = repo,
+ };
+ mark_object(obj, OBJ_ANY, &data, NULL);
}
static int traverse_one_object(struct repository *repo, struct object *obj)
{
- int result = fsck_walk(repo, obj, obj, &fsck_walk_options);
+ struct mark_object_data data = {
+ .repo = repo,
+ .parent = obj,
+ };
+ int result = fsck_walk(repo, obj, &data, &fsck_walk_options);
if (obj->type == OBJ_TREE) {
struct tree *tree = (struct tree *)obj;
@@ -222,10 +235,11 @@ static int mark_used(struct object *obj, enum object_type type UNUSED,
static int mark_unreachable_referents(const struct object_id *oid,
struct object_info *oi UNUSED,
- void *data UNUSED)
+ void *data)
{
+ struct repository *repo = data;
struct fsck_options options = FSCK_OPTIONS_DEFAULT;
- struct object *obj = lookup_object(the_repository, oid);
+ struct object *obj = lookup_object(repo, oid);
if (!obj || !(obj->flags & HAS_OBJ))
return 0; /* not part of our original set */
@@ -237,14 +251,14 @@ static int mark_unreachable_referents(const struct object_id *oid,
* (and we want to avoid parsing blobs).
*/
if (obj->type == OBJ_NONE) {
- enum object_type type = odb_read_object_info(the_repository->objects,
+ enum object_type type = odb_read_object_info(repo->objects,
&obj->oid, NULL);
if (type > 0)
object_as_type(obj, type, 0);
}
options.walk = mark_used;
- fsck_walk(the_repository, obj, NULL, &options);
+ fsck_walk(repo, obj, NULL, &options);
if (obj->type == OBJ_TREE)
free_tree_buffer((struct tree *)obj);
@@ -384,7 +398,7 @@ static void check_connectivity(struct repository *repo)
* traversal.
*/
odb_for_each_object(repo->objects, NULL,
- mark_unreachable_referents, NULL, 0);
+ mark_unreachable_referents, repo, 0);
}
/* Look up all the requirements, warn about missing objects.. */
@@ -484,7 +498,7 @@ static void fsck_handle_reflog_oid(struct repository *repo,
"%s@{%"PRItime"}",
refname, timestamp);
obj->flags |= USED;
- mark_object_reachable(obj);
+ mark_object_reachable(repo, obj);
} else if (!is_promisor_object(repo, oid)) {
error(_("%s: invalid reflog entry %s"),
refname, oid_to_hex(oid));
@@ -589,7 +603,7 @@ static int fsck_handle_ref(const struct reference *ref, void *cb_data)
obj->flags |= USED;
fsck_put_object_name(&fsck_walk_options,
ref->oid, "%s", ref->name);
- mark_object_reachable(obj);
+ mark_object_reachable(repo, obj);
return 0;
}
@@ -829,7 +843,7 @@ static int fsck_cache_tree(struct repository *repo, struct cache_tree *it,
}
obj->flags |= USED;
fsck_put_object_name(&fsck_walk_options, &it->oid, ":");
- mark_object_reachable(obj);
+ mark_object_reachable(repo, obj);
if (obj->type != OBJ_TREE)
err |= objerror(obj, _("non-tree in cache-tree"));
}
@@ -871,7 +885,7 @@ static int fsck_resolve_undo(struct index_state *istate,
obj->flags |= USED;
fsck_put_object_name(&fsck_walk_options, &ru->oid[i],
":(%d):%s", i, path);
- mark_object_reachable(obj);
+ mark_object_reachable(istate->repo, obj);
}
}
return 0;
@@ -902,7 +916,7 @@ static void fsck_index(struct index_state *istate, const char *index_path,
"%s:%s",
is_current_worktree ? "" : index_path,
istate->cache[i]->name);
- mark_object_reachable(obj);
+ mark_object_reachable(istate->repo, obj);
}
if (istate->cache_tree)
fsck_cache_tree(istate->repo, istate->cache_tree, index_path);
@@ -911,9 +925,10 @@ static void fsck_index(struct index_state *istate, const char *index_path,
static int mark_object_for_connectivity(const struct object_id *oid,
struct object_info *oi UNUSED,
- void *cb_data UNUSED)
+ void *cb_data)
{
- struct object *obj = lookup_unknown_object(the_repository, oid);
+ struct repository *repo = cb_data;
+ struct object *obj = lookup_unknown_object(repo, oid);
obj->flags |= HAS_OBJ;
return 0;
}
@@ -1064,7 +1079,7 @@ int cmd_fsck(int argc,
if (connectivity_only) {
odb_for_each_object(repo->objects, NULL,
- mark_object_for_connectivity, NULL, 0);
+ mark_object_for_connectivity, repo, 0);
} else {
odb_prepare_alternates(repo->objects);
for (source = repo->objects->sources; source; source = source->next)
--
2.53.0.1055.ga2ffed1127.dirty
^ permalink raw reply related [flat|nested] 33+ messages in thread* [PATCH 13/14] fsck: provide repository in `struct fsck_report_object`
2026-03-20 11:47 [PATCH 00/14] fsck: drop use of `the_repository` Patrick Steinhardt
` (11 preceding siblings ...)
2026-03-20 11:47 ` [PATCH 12/14] builtin/fsck: stop using `the_repository` when marking objects Patrick Steinhardt
@ 2026-03-20 11:47 ` Patrick Steinhardt
2026-03-20 23:13 ` Junio C Hamano
2026-03-20 11:47 ` [PATCH 14/14] builtin/fsck: stop using `the_repository` in error reporting Patrick Steinhardt
2026-03-23 15:02 ` [PATCH v2 00/12] fsck: drop use of `the_repository` Patrick Steinhardt
14 siblings, 1 reply; 33+ messages in thread
From: Patrick Steinhardt @ 2026-03-20 11:47 UTC (permalink / raw)
To: git
The `report()` function invokes a callback function with a `struct
fsck_report_object` for every object that failed at least one of our
checks. This report doesn't give the caller enough context though, and
thus they have to rely on global state for `the_repository`.
Refactor the code and inject the repository into the report.
As this requires us to touch up all callsites, rename the `report()`
function to `fsck_report_object()` to align it with `fsck_report_ref()`.
We have already discussed this rename in the past, but we decided to not
do it because it required us to adapt too many callsites.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
fsck.c | 365 ++++++++++++++++++++++++++++++++++++++---------------------------
fsck.h | 1 +
2 files changed, 214 insertions(+), 152 deletions(-)
diff --git a/fsck.c b/fsck.c
index edf7a0618f..59b9163598 100644
--- a/fsck.c
+++ b/fsck.c
@@ -258,13 +258,15 @@ static int fsck_vreport(struct fsck_options *options,
return result;
}
-__attribute__((format (printf, 5, 6)))
-static int report(struct fsck_options *options,
- const struct object_id *oid, enum object_type object_type,
- enum fsck_msg_id msg_id, const char *fmt, ...)
+__attribute__((format (printf, 6, 7)))
+static int fsck_report_object(struct repository *repo,
+ struct fsck_options *options,
+ const struct object_id *oid, enum object_type object_type,
+ enum fsck_msg_id msg_id, const char *fmt, ...)
{
va_list ap;
struct fsck_object_report report = {
+ .repo = repo,
.oid = oid,
.object_type = object_type
};
@@ -626,7 +628,8 @@ static int verify_ordered(unsigned mode1, const char *name1,
return c1 < c2 ? 0 : TREE_UNORDERED;
}
-static int fsck_tree(const struct object_id *tree_oid,
+static int fsck_tree(struct repository *repo,
+ const struct object_id *tree_oid,
const char *buffer, unsigned long size,
struct fsck_options *options)
{
@@ -649,9 +652,9 @@ static int fsck_tree(const struct object_id *tree_oid,
if (init_tree_desc_gently(&desc, tree_oid, buffer, size,
TREE_DESC_RAW_MODES)) {
- retval += report(options, tree_oid, OBJ_TREE,
- FSCK_MSG_BAD_TREE,
- "cannot be parsed as a tree");
+ retval += fsck_report_object(repo, options, tree_oid, OBJ_TREE,
+ FSCK_MSG_BAD_TREE,
+ "cannot be parsed as a tree");
return retval;
}
@@ -679,10 +682,10 @@ static int fsck_tree(const struct object_id *tree_oid,
oidset_insert(&options->gitmodules_found,
entry_oid);
else
- retval += report(options,
- tree_oid, OBJ_TREE,
- FSCK_MSG_GITMODULES_SYMLINK,
- ".gitmodules is a symbolic link");
+ retval += fsck_report_object(repo, options,
+ tree_oid, OBJ_TREE,
+ FSCK_MSG_GITMODULES_SYMLINK,
+ ".gitmodules is a symbolic link");
}
if (is_hfs_dotgitattributes(name) || is_ntfs_dotgitattributes(name)) {
@@ -690,22 +693,22 @@ static int fsck_tree(const struct object_id *tree_oid,
oidset_insert(&options->gitattributes_found,
entry_oid);
else
- retval += report(options, tree_oid, OBJ_TREE,
- FSCK_MSG_GITATTRIBUTES_SYMLINK,
- ".gitattributes is a symlink");
+ retval += fsck_report_object(repo, options, tree_oid, OBJ_TREE,
+ FSCK_MSG_GITATTRIBUTES_SYMLINK,
+ ".gitattributes is a symlink");
}
if (S_ISLNK(mode)) {
if (is_hfs_dotgitignore(name) ||
is_ntfs_dotgitignore(name))
- retval += report(options, tree_oid, OBJ_TREE,
- FSCK_MSG_GITIGNORE_SYMLINK,
- ".gitignore is a symlink");
+ retval += fsck_report_object(repo, options, tree_oid, OBJ_TREE,
+ FSCK_MSG_GITIGNORE_SYMLINK,
+ ".gitignore is a symlink");
if (is_hfs_dotmailmap(name) ||
is_ntfs_dotmailmap(name))
- retval += report(options, tree_oid, OBJ_TREE,
- FSCK_MSG_MAILMAP_SYMLINK,
- ".mailmap is a symlink");
+ retval += fsck_report_object(repo, options, tree_oid, OBJ_TREE,
+ FSCK_MSG_MAILMAP_SYMLINK,
+ ".mailmap is a symlink");
}
if ((backslash = strchr(name, '\\'))) {
@@ -717,18 +720,18 @@ static int fsck_tree(const struct object_id *tree_oid,
oidset_insert(&options->gitmodules_found,
entry_oid);
else
- retval += report(options, tree_oid, OBJ_TREE,
- FSCK_MSG_GITMODULES_SYMLINK,
- ".gitmodules is a symbolic link");
+ retval += fsck_report_object(repo, options, tree_oid, OBJ_TREE,
+ FSCK_MSG_GITMODULES_SYMLINK,
+ ".gitmodules is a symbolic link");
}
backslash = strchr(backslash, '\\');
}
}
if (update_tree_entry_gently(&desc)) {
- retval += report(options, tree_oid, OBJ_TREE,
- FSCK_MSG_BAD_TREE,
- "cannot be parsed as a tree");
+ retval += fsck_report_object(repo, options, tree_oid, OBJ_TREE,
+ FSCK_MSG_BAD_TREE,
+ "cannot be parsed as a tree");
break;
}
@@ -776,49 +779,49 @@ static int fsck_tree(const struct object_id *tree_oid,
name_stack_clear(&df_dup_candidates);
if (has_null_sha1)
- retval += report(options, tree_oid, OBJ_TREE,
- FSCK_MSG_NULL_SHA1,
- "contains entries pointing to null sha1");
+ retval += fsck_report_object(repo, options, tree_oid, OBJ_TREE,
+ FSCK_MSG_NULL_SHA1,
+ "contains entries pointing to null sha1");
if (has_full_path)
- retval += report(options, tree_oid, OBJ_TREE,
- FSCK_MSG_FULL_PATHNAME,
- "contains full pathnames");
+ retval += fsck_report_object(repo, options, tree_oid, OBJ_TREE,
+ FSCK_MSG_FULL_PATHNAME,
+ "contains full pathnames");
if (has_empty_name)
- retval += report(options, tree_oid, OBJ_TREE,
- FSCK_MSG_EMPTY_NAME,
- "contains empty pathname");
+ retval += fsck_report_object(repo, options, tree_oid, OBJ_TREE,
+ FSCK_MSG_EMPTY_NAME,
+ "contains empty pathname");
if (has_dot)
- retval += report(options, tree_oid, OBJ_TREE,
- FSCK_MSG_HAS_DOT,
- "contains '.'");
+ retval += fsck_report_object(repo, options, tree_oid, OBJ_TREE,
+ FSCK_MSG_HAS_DOT,
+ "contains '.'");
if (has_dotdot)
- retval += report(options, tree_oid, OBJ_TREE,
- FSCK_MSG_HAS_DOTDOT,
- "contains '..'");
+ retval += fsck_report_object(repo, options, tree_oid, OBJ_TREE,
+ FSCK_MSG_HAS_DOTDOT,
+ "contains '..'");
if (has_dotgit)
- retval += report(options, tree_oid, OBJ_TREE,
- FSCK_MSG_HAS_DOTGIT,
- "contains '.git'");
+ retval += fsck_report_object(repo, options, tree_oid, OBJ_TREE,
+ FSCK_MSG_HAS_DOTGIT,
+ "contains '.git'");
if (has_zero_pad)
- retval += report(options, tree_oid, OBJ_TREE,
- FSCK_MSG_ZERO_PADDED_FILEMODE,
- "contains zero-padded file modes");
+ retval += fsck_report_object(repo, options, tree_oid, OBJ_TREE,
+ FSCK_MSG_ZERO_PADDED_FILEMODE,
+ "contains zero-padded file modes");
if (has_bad_modes)
- retval += report(options, tree_oid, OBJ_TREE,
- FSCK_MSG_BAD_FILEMODE,
- "contains bad file modes");
+ retval += fsck_report_object(repo, options, tree_oid, OBJ_TREE,
+ FSCK_MSG_BAD_FILEMODE,
+ "contains bad file modes");
if (has_dup_entries)
- retval += report(options, tree_oid, OBJ_TREE,
- FSCK_MSG_DUPLICATE_ENTRIES,
- "contains duplicate file entries");
+ retval += fsck_report_object(repo, options, tree_oid, OBJ_TREE,
+ FSCK_MSG_DUPLICATE_ENTRIES,
+ "contains duplicate file entries");
if (not_properly_sorted)
- retval += report(options, tree_oid, OBJ_TREE,
- FSCK_MSG_TREE_NOT_SORTED,
- "not properly sorted");
+ retval += fsck_report_object(repo, options, tree_oid, OBJ_TREE,
+ FSCK_MSG_TREE_NOT_SORTED,
+ "not properly sorted");
if (has_large_name)
- retval += report(options, tree_oid, OBJ_TREE,
- FSCK_MSG_LARGE_PATHNAME,
- "contains excessively large pathname");
+ retval += fsck_report_object(repo, options, tree_oid, OBJ_TREE,
+ FSCK_MSG_LARGE_PATHNAME,
+ "contains excessively large pathname");
return retval;
}
@@ -839,7 +842,8 @@ static int fsck_tree(const struct object_id *tree_oid,
* case hit the newline we found here as the end-of-header. This makes it
* OK for them to use helpers like parse_oid_hex(), or even skip_prefix().
*/
-static int verify_headers(const void *data, unsigned long size,
+static int verify_headers(struct repository *repo,
+ const void *data, unsigned long size,
const struct object_id *oid, enum object_type type,
struct fsck_options *options)
{
@@ -849,9 +853,9 @@ static int verify_headers(const void *data, unsigned long size,
for (i = 0; i < size; i++) {
switch (buffer[i]) {
case '\0':
- return report(options, oid, type,
- FSCK_MSG_NUL_IN_HEADER,
- "unterminated header: NUL at offset %ld", i);
+ return fsck_report_object(repo, options, oid, type,
+ FSCK_MSG_NUL_IN_HEADER,
+ "unterminated header: NUL at offset %ld", i);
case '\n':
if (i + 1 < size && buffer[i + 1] == '\n')
return 0;
@@ -867,8 +871,9 @@ static int verify_headers(const void *data, unsigned long size,
if (size && buffer[size - 1] == '\n')
return 0;
- return report(options, oid, type,
- FSCK_MSG_UNTERMINATED_HEADER, "unterminated header");
+ return fsck_report_object(repo, options, oid, type,
+ FSCK_MSG_UNTERMINATED_HEADER,
+ "unterminated header");
}
static timestamp_t parse_timestamp_from_buf(const char **start, const char *end)
@@ -887,7 +892,8 @@ static timestamp_t parse_timestamp_from_buf(const char **start, const char *end)
return parse_timestamp(buf, NULL, 10);
}
-static int fsck_ident(const char **ident, const char *ident_end,
+static int fsck_ident(struct repository *repo,
+ const char **ident, const char *ident_end,
const struct object_id *oid, enum object_type type,
struct fsck_options *options)
{
@@ -900,12 +906,18 @@ static int fsck_ident(const char **ident, const char *ident_end,
*ident = nl + 1;
if (*p == '<')
- return report(options, oid, type, FSCK_MSG_MISSING_NAME_BEFORE_EMAIL, "invalid author/committer line - missing space before email");
+ return fsck_report_object(repo, options, oid, type,
+ FSCK_MSG_MISSING_NAME_BEFORE_EMAIL,
+ "invalid author/committer line - missing space before email");
for (;;) {
if (p >= ident_end || *p == '\n')
- return report(options, oid, type, FSCK_MSG_MISSING_EMAIL, "invalid author/committer line - missing email");
+ return fsck_report_object(repo, options, oid, type,
+ FSCK_MSG_MISSING_EMAIL,
+ "invalid author/committer line - missing email");
if (*p == '>')
- return report(options, oid, type, FSCK_MSG_BAD_NAME, "invalid author/committer line - bad name");
+ return fsck_report_object(repo, options, oid, type,
+ FSCK_MSG_BAD_NAME,
+ "invalid author/committer line - bad name");
if (*p == '<')
break; /* end of name, beginning of email */
@@ -913,11 +925,15 @@ static int fsck_ident(const char **ident, const char *ident_end,
p++;
}
if (p[-1] != ' ')
- return report(options, oid, type, FSCK_MSG_MISSING_SPACE_BEFORE_EMAIL, "invalid author/committer line - missing space before email");
+ return fsck_report_object(repo, options, oid, type,
+ FSCK_MSG_MISSING_SPACE_BEFORE_EMAIL,
+ "invalid author/committer line - missing space before email");
p++; /* skip past '<' we found */
for (;;) {
if (p >= ident_end || *p == '<' || *p == '\n')
- return report(options, oid, type, FSCK_MSG_BAD_EMAIL, "invalid author/committer line - bad email");
+ return fsck_report_object(repo, options, oid, type,
+ FSCK_MSG_BAD_EMAIL,
+ "invalid author/committer line - bad email");
if (*p == '>')
break; /* end of email */
@@ -926,7 +942,9 @@ static int fsck_ident(const char **ident, const char *ident_end,
}
p++; /* skip past '>' we found */
if (*p != ' ')
- return report(options, oid, type, FSCK_MSG_MISSING_SPACE_BEFORE_DATE, "invalid author/committer line - missing space before date");
+ return fsck_report_object(repo, options, oid, type,
+ FSCK_MSG_MISSING_SPACE_BEFORE_DATE,
+ "invalid author/committer line - missing space before date");
p++;
/*
* Our timestamp parser is based on the C strto*() functions, which
@@ -940,14 +958,21 @@ static int fsck_ident(const char **ident, const char *ident_end,
while (*p == ' ' || *p == '\t')
p++;
if (!isdigit(*p))
- return report(options, oid, type, FSCK_MSG_BAD_DATE,
- "invalid author/committer line - bad date");
+ return fsck_report_object(repo, options, oid, type,
+ FSCK_MSG_BAD_DATE,
+ "invalid author/committer line - bad date");
if (*p == '0' && p[1] != ' ')
- return report(options, oid, type, FSCK_MSG_ZERO_PADDED_DATE, "invalid author/committer line - zero-padded date");
+ return fsck_report_object(repo, options, oid, type,
+ FSCK_MSG_ZERO_PADDED_DATE,
+ "invalid author/committer line - zero-padded date");
if (date_overflows(parse_timestamp_from_buf(&p, ident_end)))
- return report(options, oid, type, FSCK_MSG_BAD_DATE_OVERFLOW, "invalid author/committer line - date causes integer overflow");
+ return fsck_report_object(repo, options, oid, type,
+ FSCK_MSG_BAD_DATE_OVERFLOW,
+ "invalid author/committer line - date causes integer overflow");
if (*p != ' ')
- return report(options, oid, type, FSCK_MSG_BAD_DATE, "invalid author/committer line - bad date");
+ return fsck_report_object(repo, options, oid, type,
+ FSCK_MSG_BAD_DATE,
+ "invalid author/committer line - bad date");
p++;
if ((*p != '+' && *p != '-') ||
!isdigit(p[1]) ||
@@ -955,7 +980,9 @@ static int fsck_ident(const char **ident, const char *ident_end,
!isdigit(p[3]) ||
!isdigit(p[4]) ||
(p[5] != '\n'))
- return report(options, oid, type, FSCK_MSG_BAD_TIMEZONE, "invalid author/committer line - bad time zone");
+ return fsck_report_object(repo, options, oid, type,
+ FSCK_MSG_BAD_TIMEZONE,
+ "invalid author/committer line - bad time zone");
p += 6;
return 0;
}
@@ -977,20 +1004,26 @@ static int fsck_commit(struct repository *repo,
* memory safety of the rest of the function depends on it. See the
* comment above the definition of verify_headers() for more details.
*/
- if (verify_headers(buffer, size, oid, OBJ_COMMIT, options))
+ if (verify_headers(repo, buffer, size, oid, OBJ_COMMIT, options))
return -1;
if (buffer >= buffer_end || !skip_prefix(buffer, "tree ", &buffer))
- return report(options, oid, OBJ_COMMIT, FSCK_MSG_MISSING_TREE, "invalid format - expected 'tree' line");
+ return fsck_report_object(repo, options, oid, OBJ_COMMIT,
+ FSCK_MSG_MISSING_TREE,
+ "invalid format - expected 'tree' line");
if (parse_oid_hex_algop(buffer, &tree_oid, &p, repo->hash_algo) || *p != '\n') {
- err = report(options, oid, OBJ_COMMIT, FSCK_MSG_BAD_TREE_SHA1, "invalid 'tree' line format - bad sha1");
+ err = fsck_report_object(repo, options, oid, OBJ_COMMIT,
+ FSCK_MSG_BAD_TREE_SHA1,
+ "invalid 'tree' line format - bad sha1");
if (err)
return err;
}
buffer = p + 1;
while (buffer < buffer_end && skip_prefix(buffer, "parent ", &buffer)) {
if (parse_oid_hex_algop(buffer, &parent_oid, &p, repo->hash_algo) || *p != '\n') {
- err = report(options, oid, OBJ_COMMIT, FSCK_MSG_BAD_PARENT_SHA1, "invalid 'parent' line format - bad sha1");
+ err = fsck_report_object(repo, options, oid, OBJ_COMMIT,
+ FSCK_MSG_BAD_PARENT_SHA1,
+ "invalid 'parent' line format - bad sha1");
if (err)
return err;
}
@@ -999,24 +1032,31 @@ static int fsck_commit(struct repository *repo,
author_count = 0;
while (buffer < buffer_end && skip_prefix(buffer, "author ", &buffer)) {
author_count++;
- err = fsck_ident(&buffer, buffer_end, oid, OBJ_COMMIT, options);
+ err = fsck_ident(repo, &buffer, buffer_end, oid, OBJ_COMMIT, options);
if (err)
return err;
}
if (author_count < 1)
- err = report(options, oid, OBJ_COMMIT, FSCK_MSG_MISSING_AUTHOR, "invalid format - expected 'author' line");
+ err = fsck_report_object(repo, options, oid, OBJ_COMMIT,
+ FSCK_MSG_MISSING_AUTHOR,
+ "invalid format - expected 'author' line");
else if (author_count > 1)
- err = report(options, oid, OBJ_COMMIT, FSCK_MSG_MULTIPLE_AUTHORS, "invalid format - multiple 'author' lines");
+ err = fsck_report_object(repo, options, oid, OBJ_COMMIT,
+ FSCK_MSG_MULTIPLE_AUTHORS,
+ "invalid format - multiple 'author' lines");
if (err)
return err;
if (buffer >= buffer_end || !skip_prefix(buffer, "committer ", &buffer))
- return report(options, oid, OBJ_COMMIT, FSCK_MSG_MISSING_COMMITTER, "invalid format - expected 'committer' line");
- err = fsck_ident(&buffer, buffer_end, oid, OBJ_COMMIT, options);
+ return fsck_report_object(repo, options, oid, OBJ_COMMIT,
+ FSCK_MSG_MISSING_COMMITTER,
+ "invalid format - expected 'committer' line");
+ err = fsck_ident(repo, &buffer, buffer_end, oid, OBJ_COMMIT, options);
if (err)
return err;
if (memchr(buffer_begin, '\0', size)) {
- err = report(options, oid, OBJ_COMMIT, FSCK_MSG_NUL_IN_COMMIT,
- "NUL byte in the commit object body");
+ err = fsck_report_object(repo, options, oid, OBJ_COMMIT,
+ FSCK_MSG_NUL_IN_COMMIT,
+ "NUL byte in the commit object body");
if (err)
return err;
}
@@ -1050,52 +1090,66 @@ int fsck_tag_standalone(struct repository *repo,
* memory safety of the rest of the function depends on it. See the
* comment above the definition of verify_headers() for more details.
*/
- ret = verify_headers(buffer, size, oid, OBJ_TAG, options);
+ ret = verify_headers(repo, buffer, size, oid, OBJ_TAG, options);
if (ret)
goto done;
if (buffer >= buffer_end || !skip_prefix(buffer, "object ", &buffer)) {
- ret = report(options, oid, OBJ_TAG, FSCK_MSG_MISSING_OBJECT, "invalid format - expected 'object' line");
+ ret = fsck_report_object(repo, options, oid, OBJ_TAG,
+ FSCK_MSG_MISSING_OBJECT,
+ "invalid format - expected 'object' line");
goto done;
}
if (parse_oid_hex_algop(buffer, tagged_oid, &p, repo->hash_algo) || *p != '\n') {
- ret = report(options, oid, OBJ_TAG, FSCK_MSG_BAD_OBJECT_SHA1, "invalid 'object' line format - bad sha1");
+ ret = fsck_report_object(repo, options, oid, OBJ_TAG,
+ FSCK_MSG_BAD_OBJECT_SHA1,
+ "invalid 'object' line format - bad sha1");
if (ret)
goto done;
}
buffer = p + 1;
if (buffer >= buffer_end || !skip_prefix(buffer, "type ", &buffer)) {
- ret = report(options, oid, OBJ_TAG, FSCK_MSG_MISSING_TYPE_ENTRY, "invalid format - expected 'type' line");
+ ret = fsck_report_object(repo, options, oid, OBJ_TAG,
+ FSCK_MSG_MISSING_TYPE_ENTRY,
+ "invalid format - expected 'type' line");
goto done;
}
eol = memchr(buffer, '\n', buffer_end - buffer);
if (!eol) {
- ret = report(options, oid, OBJ_TAG, FSCK_MSG_MISSING_TYPE, "invalid format - unexpected end after 'type' line");
+ ret = fsck_report_object(repo, options, oid, OBJ_TAG,
+ FSCK_MSG_MISSING_TYPE,
+ "invalid format - unexpected end after 'type' line");
goto done;
}
*tagged_type = type_from_string_gently(buffer, eol - buffer, 1);
if (*tagged_type < 0)
- ret = report(options, oid, OBJ_TAG, FSCK_MSG_BAD_TYPE, "invalid 'type' value");
+ ret = fsck_report_object(repo, options, oid, OBJ_TAG,
+ FSCK_MSG_BAD_TYPE,
+ "invalid 'type' value");
if (ret)
goto done;
buffer = eol + 1;
if (buffer >= buffer_end || !skip_prefix(buffer, "tag ", &buffer)) {
- ret = report(options, oid, OBJ_TAG, FSCK_MSG_MISSING_TAG_ENTRY, "invalid format - expected 'tag' line");
+ ret = fsck_report_object(repo, options, oid, OBJ_TAG,
+ FSCK_MSG_MISSING_TAG_ENTRY,
+ "invalid format - expected 'tag' line");
goto done;
}
eol = memchr(buffer, '\n', buffer_end - buffer);
if (!eol) {
- ret = report(options, oid, OBJ_TAG, FSCK_MSG_MISSING_TAG, "invalid format - unexpected end after 'type' line");
+ ret = fsck_report_object(repo, options, oid, OBJ_TAG,
+ FSCK_MSG_MISSING_TAG,
+ "invalid format - unexpected end after 'type' line");
goto done;
}
strbuf_addf(&sb, "refs/tags/%.*s", (int)(eol - buffer), buffer);
if (check_refname_format(sb.buf, 0)) {
- ret = report(options, oid, OBJ_TAG,
- FSCK_MSG_BAD_TAG_NAME,
- "invalid 'tag' name: %.*s",
- (int)(eol - buffer), buffer);
+ ret = fsck_report_object(repo, options, oid, OBJ_TAG,
+ FSCK_MSG_BAD_TAG_NAME,
+ "invalid 'tag' name: %.*s",
+ (int)(eol - buffer), buffer);
if (ret)
goto done;
}
@@ -1103,17 +1157,21 @@ int fsck_tag_standalone(struct repository *repo,
if (buffer >= buffer_end || !skip_prefix(buffer, "tagger ", &buffer)) {
/* early tags do not contain 'tagger' lines; warn only */
- ret = report(options, oid, OBJ_TAG, FSCK_MSG_MISSING_TAGGER_ENTRY, "invalid format - expected 'tagger' line");
+ ret = fsck_report_object(repo, options, oid, OBJ_TAG,
+ FSCK_MSG_MISSING_TAGGER_ENTRY,
+ "invalid format - expected 'tagger' line");
if (ret)
goto done;
}
else
- ret = fsck_ident(&buffer, buffer_end, oid, OBJ_TAG, options);
+ ret = fsck_ident(repo, &buffer, buffer_end, oid, OBJ_TAG, options);
if (buffer < buffer_end && (skip_prefix(buffer, "gpgsig ", &buffer) || skip_prefix(buffer, "gpgsig-sha256 ", &buffer))) {
eol = memchr(buffer, '\n', buffer_end - buffer);
if (!eol) {
- ret = report(options, oid, OBJ_TAG, FSCK_MSG_BAD_GPGSIG, "invalid format - unexpected end after 'gpgsig' or 'gpgsig-sha256' line");
+ ret = fsck_report_object(repo, options, oid, OBJ_TAG,
+ FSCK_MSG_BAD_GPGSIG,
+ "invalid format - unexpected end after 'gpgsig' or 'gpgsig-sha256' line");
goto done;
}
buffer = eol + 1;
@@ -1121,7 +1179,9 @@ int fsck_tag_standalone(struct repository *repo,
while (buffer < buffer_end && starts_with(buffer, " ")) {
eol = memchr(buffer, '\n', buffer_end - buffer);
if (!eol) {
- ret = report(options, oid, OBJ_TAG, FSCK_MSG_BAD_HEADER_CONTINUATION, "invalid format - unexpected end in 'gpgsig' or 'gpgsig-sha256' continuation line");
+ ret = fsck_report_object(repo, options, oid, OBJ_TAG,
+ FSCK_MSG_BAD_HEADER_CONTINUATION,
+ "invalid format - unexpected end in 'gpgsig' or 'gpgsig-sha256' continuation line");
goto done;
}
buffer = eol + 1;
@@ -1136,7 +1196,9 @@ int fsck_tag_standalone(struct repository *repo,
* garbage" could be a custom header. E.g. "mktag"
* doesn't want any unknown headers.
*/
- ret = report(options, oid, OBJ_TAG, FSCK_MSG_EXTRA_HEADER_ENTRY, "invalid format - extra header(s) after 'tagger'");
+ ret = fsck_report_object(repo, options, oid, OBJ_TAG,
+ FSCK_MSG_EXTRA_HEADER_ENTRY,
+ "invalid format - extra header(s) after 'tagger'");
if (ret)
goto done;
}
@@ -1147,6 +1209,7 @@ int fsck_tag_standalone(struct repository *repo,
}
struct fsck_gitmodules_data {
+ struct repository *repo;
const struct object_id *oid;
struct fsck_options *options;
int ret;
@@ -1157,6 +1220,7 @@ static int fsck_gitmodules_fn(const char *var, const char *value,
void *vdata)
{
struct fsck_gitmodules_data *data = vdata;
+ struct repository *repo = data->repo;
const char *subsection, *key;
size_t subsection_len;
char *name;
@@ -1167,37 +1231,31 @@ static int fsck_gitmodules_fn(const char *var, const char *value,
name = xmemdupz(subsection, subsection_len);
if (check_submodule_name(name) < 0)
- data->ret |= report(data->options,
- data->oid, OBJ_BLOB,
- FSCK_MSG_GITMODULES_NAME,
- "disallowed submodule name: %s",
- name);
+ data->ret |= fsck_report_object(repo, data->options, data->oid, OBJ_BLOB,
+ FSCK_MSG_GITMODULES_NAME,
+ "disallowed submodule name: %s", name);
if (!strcmp(key, "url") && value &&
check_submodule_url(value) < 0)
- data->ret |= report(data->options,
- data->oid, OBJ_BLOB,
- FSCK_MSG_GITMODULES_URL,
- "disallowed submodule url: %s",
- value);
+ data->ret |= fsck_report_object(repo, data->options, data->oid, OBJ_BLOB,
+ FSCK_MSG_GITMODULES_URL,
+ "disallowed submodule url: %s", value);
if (!strcmp(key, "path") && value &&
looks_like_command_line_option(value))
- data->ret |= report(data->options,
- data->oid, OBJ_BLOB,
- FSCK_MSG_GITMODULES_PATH,
- "disallowed submodule path: %s",
- value);
+ data->ret |= fsck_report_object(repo, data->options, data->oid, OBJ_BLOB,
+ FSCK_MSG_GITMODULES_PATH,
+ "disallowed submodule path: %s", value);
if (!strcmp(key, "update") && value &&
parse_submodule_update_type(value) == SM_UPDATE_COMMAND)
- data->ret |= report(data->options, data->oid, OBJ_BLOB,
- FSCK_MSG_GITMODULES_UPDATE,
- "disallowed submodule update setting: %s",
- value);
+ data->ret |= fsck_report_object(repo, data->options, data->oid, OBJ_BLOB,
+ FSCK_MSG_GITMODULES_UPDATE,
+ "disallowed submodule update setting: %s", value);
free(name);
return 0;
}
-static int fsck_blob(const struct object_id *oid, const char *buf,
+static int fsck_blob(struct repository *repo,
+ const struct object_id *oid, const char *buf,
unsigned long size, struct fsck_options *options)
{
int ret = 0;
@@ -1217,11 +1275,12 @@ static int fsck_blob(const struct object_id *oid, const char *buf,
* blob too gigantic to load into memory. Let's just consider
* that an error.
*/
- return report(options, oid, OBJ_BLOB,
- FSCK_MSG_GITMODULES_LARGE,
- ".gitmodules too large to parse");
+ return fsck_report_object(repo, options, oid, OBJ_BLOB,
+ FSCK_MSG_GITMODULES_LARGE,
+ ".gitmodules too large to parse");
}
+ data.repo = repo;
data.oid = oid;
data.options = options;
data.ret = 0;
@@ -1229,9 +1288,9 @@ static int fsck_blob(const struct object_id *oid, const char *buf,
if (git_config_from_mem(fsck_gitmodules_fn, CONFIG_ORIGIN_BLOB,
".gitmodules", buf, size, &data,
CONFIG_SCOPE_UNKNOWN, &config_opts))
- data.ret |= report(options, oid, OBJ_BLOB,
- FSCK_MSG_GITMODULES_PARSE,
- "could not parse gitmodules blob");
+ data.ret |= fsck_report_object(repo, options, oid, OBJ_BLOB,
+ FSCK_MSG_GITMODULES_PARSE,
+ "could not parse gitmodules blob");
ret |= data.ret;
}
@@ -1246,17 +1305,17 @@ static int fsck_blob(const struct object_id *oid, const char *buf,
* blob too gigantic to load into memory. Let's just consider
* that an error.
*/
- return report(options, oid, OBJ_BLOB,
- FSCK_MSG_GITATTRIBUTES_LARGE,
- ".gitattributes too large to parse");
+ return fsck_report_object(repo, options, oid, OBJ_BLOB,
+ FSCK_MSG_GITATTRIBUTES_LARGE,
+ ".gitattributes too large to parse");
}
for (ptr = buf; *ptr; ) {
const char *eol = strchrnul(ptr, '\n');
if (eol - ptr >= ATTR_MAX_LINE_LENGTH) {
- ret |= report(options, oid, OBJ_BLOB,
- FSCK_MSG_GITATTRIBUTES_LINE_LENGTH,
- ".gitattributes has too long lines to parse");
+ ret |= fsck_report_object(repo, options, oid, OBJ_BLOB,
+ FSCK_MSG_GITATTRIBUTES_LINE_LENGTH,
+ ".gitattributes has too long lines to parse");
break;
}
@@ -1272,7 +1331,9 @@ int fsck_object(struct repository *repo,
struct fsck_options *options)
{
if (!obj)
- return report(options, NULL, OBJ_NONE, FSCK_MSG_BAD_OBJECT_SHA1, "no valid object to fsck");
+ return fsck_report_object(repo, options, NULL, OBJ_NONE,
+ FSCK_MSG_BAD_OBJECT_SHA1,
+ "no valid object to fsck");
return fsck_buffer(repo, &obj->oid, obj->type, data, size, options);
}
@@ -1283,18 +1344,18 @@ int fsck_buffer(struct repository *repo,
struct fsck_options *options)
{
if (type == OBJ_BLOB)
- return fsck_blob(oid, data, size, options);
+ return fsck_blob(repo, oid, data, size, options);
if (type == OBJ_TREE)
- return fsck_tree(oid, data, size, options);
+ return fsck_tree(repo, oid, data, size, options);
if (type == OBJ_COMMIT)
return fsck_commit(repo, oid, data, size, options);
if (type == OBJ_TAG)
return fsck_tag(repo, oid, data, size, options);
- return report(options, oid, type,
- FSCK_MSG_UNKNOWN_TYPE,
- "unknown type '%d' (internal fsck error)",
- type);
+ return fsck_report_object(repo, options, oid, type,
+ FSCK_MSG_UNKNOWN_TYPE,
+ "unknown type '%d' (internal fsck error)",
+ type);
}
int fsck_objects_error_function(struct fsck_options *o,
@@ -1357,17 +1418,17 @@ static int fsck_blobs(struct repository *repo,
if (!buf) {
if (is_promisor_object(repo, oid))
continue;
- ret |= report(options,
- oid, OBJ_BLOB, msg_missing,
- "unable to read %s blob", blob_type);
+ ret |= fsck_report_object(repo, options,
+ oid, OBJ_BLOB, msg_missing,
+ "unable to read %s blob", blob_type);
continue;
}
if (type == OBJ_BLOB)
- ret |= fsck_blob(oid, buf, size, options);
+ ret |= fsck_blob(repo, oid, buf, size, options);
else
- ret |= report(options, oid, type, msg_type,
- "non-blob found at %s", blob_type);
+ ret |= fsck_report_object(repo, options, oid, type, msg_type,
+ "non-blob found at %s", blob_type);
free(buf);
}
diff --git a/fsck.h b/fsck.h
index 62b7c3c93a..5d05996dd0 100644
--- a/fsck.h
+++ b/fsck.h
@@ -159,6 +159,7 @@ int fsck_refs_error_function(struct fsck_options *options,
const char *message);
struct fsck_object_report {
+ struct repository *repo;
const struct object_id *oid;
enum object_type object_type;
};
--
2.53.0.1055.ga2ffed1127.dirty
^ permalink raw reply related [flat|nested] 33+ messages in thread* Re: [PATCH 13/14] fsck: provide repository in `struct fsck_report_object`
2026-03-20 11:47 ` [PATCH 13/14] fsck: provide repository in `struct fsck_report_object` Patrick Steinhardt
@ 2026-03-20 23:13 ` Junio C Hamano
0 siblings, 0 replies; 33+ messages in thread
From: Junio C Hamano @ 2026-03-20 23:13 UTC (permalink / raw)
To: Patrick Steinhardt; +Cc: git
Patrick Steinhardt <ps@pks.im> writes:
> The `report()` function invokes a callback function with a `struct
> fsck_report_object` for every object that failed at least one of our
> checks. This report doesn't give the caller enough context though, and
> thus they have to rely on global state for `the_repository`.
>
> Refactor the code and inject the repository into the report.
>
> As this requires us to touch up all callsites, rename the `report()`
> function to `fsck_report_object()` to align it with `fsck_report_ref()`.
> We have already discussed this rename in the past, but we decided to not
> do it because it required us to adapt too many callsites.
>
> Signed-off-by: Patrick Steinhardt <ps@pks.im>
> ---
> fsck.c | 365 ++++++++++++++++++++++++++++++++++++++---------------------------
> fsck.h | 1 +
> 2 files changed, 214 insertions(+), 152 deletions(-)
>
> diff --git a/fsck.c b/fsck.c
> index edf7a0618f..59b9163598 100644
> --- a/fsck.c
> +++ b/fsck.c
> @@ -258,13 +258,15 @@ static int fsck_vreport(struct fsck_options *options,
> return result;
> }
>
> -__attribute__((format (printf, 5, 6)))
> -static int report(struct fsck_options *options,
> - const struct object_id *oid, enum object_type object_type,
> - enum fsck_msg_id msg_id, const char *fmt, ...)
> +__attribute__((format (printf, 6, 7)))
> +static int fsck_report_object(struct repository *repo,
> + struct fsck_options *options,
> + const struct object_id *oid, enum object_type object_type,
> + enum fsck_msg_id msg_id, const char *fmt, ...)
Earlier I wondered if struct repository *repo should be added to
fsck_options; I didn't comment on individual patches, but almost all
patches I saw since that remark made me suspect that fsck_options
would be a good place to pass repository throughout the callchain
even more.
^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 14/14] builtin/fsck: stop using `the_repository` in error reporting
2026-03-20 11:47 [PATCH 00/14] fsck: drop use of `the_repository` Patrick Steinhardt
` (12 preceding siblings ...)
2026-03-20 11:47 ` [PATCH 13/14] fsck: provide repository in `struct fsck_report_object` Patrick Steinhardt
@ 2026-03-20 11:47 ` Patrick Steinhardt
2026-03-23 15:02 ` [PATCH v2 00/12] fsck: drop use of `the_repository` Patrick Steinhardt
14 siblings, 0 replies; 33+ messages in thread
From: Patrick Steinhardt @ 2026-03-20 11:47 UTC (permalink / raw)
To: git
In the preceding commit we have introduced the repository into `struct
fsck_object_report`. This allows us to drop remaining uses of the global
`the_repository` variable.
Drop them and remove `USE_THE_REPOSITORY_VARIABLE`.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
builtin/fsck.c | 36 ++++++++++++++++++------------------
1 file changed, 18 insertions(+), 18 deletions(-)
diff --git a/builtin/fsck.c b/builtin/fsck.c
index b15708d155..24d8ec6d42 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -1,4 +1,3 @@
-#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "gettext.h"
#include "hex.h"
@@ -66,13 +65,14 @@ static const char *describe_object(const struct object_id *oid)
return fsck_describe_object(&fsck_walk_options, oid);
}
-static const char *printable_type(const struct object_id *oid,
+static const char *printable_type(struct repository *repo,
+ const struct object_id *oid,
enum object_type type)
{
const char *ret;
if (type == OBJ_NONE)
- type = odb_read_object_info(the_repository->objects,
+ type = odb_read_object_info(repo->objects,
oid, NULL);
ret = type_name(type);
@@ -82,12 +82,12 @@ static const char *printable_type(const struct object_id *oid,
return ret;
}
-static int objerror(struct object *obj, const char *err)
+static int objerror(struct repository *repo, struct object *obj, const char *err)
{
errors_found |= ERROR_OBJECT;
/* TRANSLATORS: e.g. error in tree 01bfda: <more explanation> */
fprintf_ln(stderr, _("error in %s %s: %s"),
- printable_type(&obj->oid, obj->type),
+ printable_type(repo, &obj->oid, obj->type),
describe_object(&obj->oid), err);
return -1;
}
@@ -106,13 +106,13 @@ static int fsck_objects_error_func(struct fsck_options *o UNUSED,
case FSCK_WARN:
/* TRANSLATORS: e.g. warning in tree 01bfda: <more explanation> */
fprintf_ln(stderr, _("warning in %s %s: %s"),
- printable_type(oid, object_type),
+ printable_type(report->repo, oid, object_type),
describe_object(oid), message);
return 0;
case FSCK_ERROR:
/* TRANSLATORS: e.g. error in tree 01bfda: <more explanation> */
fprintf_ln(stderr, _("error in %s %s: %s"),
- printable_type(oid, object_type),
+ printable_type(report->repo, oid, object_type),
describe_object(oid), message);
return 1;
default:
@@ -142,7 +142,7 @@ static int mark_object(struct object *obj, enum object_type type,
if (!obj) {
/* ... these references to parent->fld are safe here */
printf_ln(_("broken link from %7s %s"),
- printable_type(&parent->oid, parent->type),
+ printable_type(data->repo, &parent->oid, parent->type),
describe_object(&parent->oid));
printf_ln(_("broken link from %7s %s"),
(type == OBJ_ANY ? _("unknown") : type_name(type)),
@@ -153,7 +153,7 @@ static int mark_object(struct object *obj, enum object_type type,
if (type != OBJ_ANY && obj->type != type)
/* ... and the reference to parent is safe here */
- objerror(parent, _("wrong object type in link"));
+ objerror(data->repo, parent, _("wrong object type in link"));
if (obj->flags & REACHABLE)
return 0;
@@ -172,9 +172,9 @@ static int mark_object(struct object *obj, enum object_type type,
HAS_OBJECT_RECHECK_PACKED)) {
printf_ln(_("broken link from %7s %s\n"
" to %7s %s"),
- printable_type(&parent->oid, parent->type),
+ printable_type(data->repo, &parent->oid, parent->type),
describe_object(&parent->oid),
- printable_type(&obj->oid, obj->type),
+ printable_type(data->repo, &obj->oid, obj->type),
describe_object(&obj->oid));
errors_found |= ERROR_REACHABLE;
}
@@ -281,7 +281,7 @@ static void check_reachable_object(struct repository *repo, struct object *obj)
if (has_object_pack(repo, &obj->oid))
return; /* it is in pack - forget about it */
printf_ln(_("missing %s %s"),
- printable_type(&obj->oid, obj->type),
+ printable_type(repo, &obj->oid, obj->type),
describe_object(&obj->oid));
errors_found |= ERROR_REACHABLE;
return;
@@ -308,7 +308,7 @@ static void check_unreachable_object(struct repository *repo, struct object *obj
*/
if (show_unreachable) {
printf_ln(_("unreachable %s %s"),
- printable_type(&obj->oid, obj->type),
+ printable_type(repo, &obj->oid, obj->type),
describe_object(&obj->oid));
return;
}
@@ -328,7 +328,7 @@ static void check_unreachable_object(struct repository *repo, struct object *obj
if (!(obj->flags & USED)) {
if (show_dangling)
printf_ln(_("dangling %s %s"),
- printable_type(&obj->oid, obj->type),
+ printable_type(repo, &obj->oid, obj->type),
describe_object(&obj->oid));
if (write_lost_and_found) {
char *filename = repo_git_path(repo, "lost-found/%s/%s",
@@ -426,11 +426,11 @@ static int fsck_obj(struct repository *repo,
if (verbose)
fprintf_ln(stderr, _("Checking %s %s"),
- printable_type(&obj->oid, obj->type),
+ printable_type(repo, &obj->oid, obj->type),
describe_object(&obj->oid));
if (fsck_walk(repo, obj, NULL, &fsck_obj_options))
- objerror(obj, _("broken links"));
+ objerror(repo, obj, _("broken links"));
err = fsck_object(repo, obj, buffer, size, &fsck_obj_options);
if (err)
goto out;
@@ -448,7 +448,7 @@ static int fsck_obj(struct repository *repo,
if (show_tags && tag->tagged) {
printf_ln(_("tagged %s %s (%s) in %s"),
- printable_type(&tag->tagged->oid, tag->tagged->type),
+ printable_type(repo, &tag->tagged->oid, tag->tagged->type),
describe_object(&tag->tagged->oid),
tag->tag,
describe_object(&tag->object.oid));
@@ -845,7 +845,7 @@ static int fsck_cache_tree(struct repository *repo, struct cache_tree *it,
fsck_put_object_name(&fsck_walk_options, &it->oid, ":");
mark_object_reachable(repo, obj);
if (obj->type != OBJ_TREE)
- err |= objerror(obj, _("non-tree in cache-tree"));
+ err |= objerror(repo, obj, _("non-tree in cache-tree"));
}
for (i = 0; i < it->subtree_nr; i++)
err |= fsck_cache_tree(repo, it->down[i]->cache_tree, index_path);
--
2.53.0.1055.ga2ffed1127.dirty
^ permalink raw reply related [flat|nested] 33+ messages in thread* [PATCH v2 00/12] fsck: drop use of `the_repository`
2026-03-20 11:47 [PATCH 00/14] fsck: drop use of `the_repository` Patrick Steinhardt
` (13 preceding siblings ...)
2026-03-20 11:47 ` [PATCH 14/14] builtin/fsck: stop using `the_repository` in error reporting Patrick Steinhardt
@ 2026-03-23 15:02 ` Patrick Steinhardt
2026-03-23 15:02 ` [PATCH v2 01/12] fetch-pack: move fsck options into function scope Patrick Steinhardt
` (11 more replies)
14 siblings, 12 replies; 33+ messages in thread
From: Patrick Steinhardt @ 2026-03-23 15:02 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
Hi,
this patch series refactors "{builtin/,}fsck.c" to not depend on
`the_repository` anymore. These refactorings are mostly done to prepare
for upcoming changes where we'll make backend-specific fsck checks
pluggable.
Changes in v2:
- Propagate the repository via `struct fsck_options`.
- Link to v1: https://lore.kernel.org/r/20260320-b4-pks-fsck-without-the-repository-v1-0-6594f997926b@pks.im
Thanks!
Patrick
---
Patrick Steinhardt (12):
fetch-pack: move fsck options into function scope
fsck: initialize fsck options via a function
fsck: store repository in fsck options
fsck: drop USE_THE_REPOSITORY
builtin/fsck: fix trivial dependence on `the_repository`
builtin/fsck: stop using `the_repository` when snapshotting refs
builtin/fsck: stop using `the_repository` when checking refs
builtin/fsck: stop using `the_repository` when checking reflogs
builtin/fsck: stop using `the_repository` with loose objects
builtin/fsck: stop using `the_repository` when checking packed objects
builtin/fsck: stop using `the_repository` when marking objects
builtin/fsck: stop using `the_repository` in error reporting
builtin/fsck.c | 273 ++++++++++++++++++++++++++---------------------
builtin/index-pack.c | 4 +-
builtin/mktag.c | 5 +-
builtin/refs.c | 6 +-
builtin/unpack-objects.c | 6 +-
fetch-pack.c | 9 +-
fsck.c | 76 ++++++++++---
fsck.h | 42 +++-----
object-file.c | 3 +-
pack-check.c | 7 +-
pack.h | 9 +-
11 files changed, 259 insertions(+), 181 deletions(-)
Range-diff versus v1:
1: fd589e1813 < -: ---------- fsck: drop `the_repository` in `fsck_walk()`
2: 6d0d46b70d < -: ---------- fsck: drop `the_repository` in `fsck_finish()`
3: 79c3cd644b < -: ---------- fsck: refactor interface to parse fsck options
4: f5fd9d1489 < -: ---------- fsck: drop `the_repository` in `fsck_set_msg_types()`
5: 58c145905e < -: ---------- fsck: stop relying on global state via `parse_oid_hex()`
-: ---------- > 1: 1b5958d8db fetch-pack: move fsck options into function scope
-: ---------- > 2: 19b502cd82 fsck: initialize fsck options via a function
-: ---------- > 3: 34b921be8b fsck: store repository in fsck options
-: ---------- > 4: f8a74307d8 fsck: drop USE_THE_REPOSITORY
6: 4d255cd44d ! 5: 6e3f51757f builtin/fsck: fix trivial dependence on `the_repository`
@@ Commit message
Signed-off-by: Patrick Steinhardt <ps@pks.im>
## builtin/fsck.c ##
-@@ builtin/fsck.c: static void mark_object_reachable(struct object *obj)
- mark_object(obj, OBJ_ANY, NULL, NULL);
- }
-
--static int traverse_one_object(struct object *obj)
-+static int traverse_one_object(struct repository *repo, struct object *obj)
- {
-- int result = fsck_walk(the_repository, obj, obj, &fsck_walk_options);
-+ int result = fsck_walk(repo, obj, obj, &fsck_walk_options);
-
- if (obj->type == OBJ_TREE) {
- struct tree *tree = (struct tree *)obj;
@@ builtin/fsck.c: static int traverse_one_object(struct object *obj)
return result;
}
@@ builtin/fsck.c: static int traverse_one_object(struct object *obj)
+ progress = start_delayed_progress(repo,
_("Checking connectivity"), 0);
while (pending.nr) {
-- result |= traverse_one_object(object_array_pop(&pending));
-+ result |= traverse_one_object(repo, object_array_pop(&pending));
- display_progress(progress, ++nr);
- }
- stop_progress(&progress);
+ result |= traverse_one_object(object_array_pop(&pending));
@@ builtin/fsck.c: static int mark_unreachable_referents(const struct object_id *oid,
/*
* Check a single reachable object
@@ builtin/fsck.c: static void check_connectivity(void)
}
}
-@@ builtin/fsck.c: static int fsck_handle_ref(const struct reference *ref, void *cb_data UNUSED)
+@@ builtin/fsck.c: static int fsck_subdir(unsigned int nr, const char *path UNUSED, void *data)
return 0;
}
--static void snapshot_refs(struct snapshot *snap, int argc, const char **argv)
-+static void snapshot_refs(struct repository *repo, struct snapshot *snap,
-+ int argc, const char **argv)
+-static void fsck_source(struct odb_source *source)
++static void fsck_source(struct repository *repo, struct odb_source *source)
{
- struct refs_for_each_ref_options opts = {
- .flags = REFS_FOR_EACH_INCLUDE_BROKEN,
-@@ builtin/fsck.c: static void snapshot_refs(struct snapshot *snap, int argc, const char **argv)
- for (int i = 0; i < argc; i++) {
- const char *arg = argv[i];
- struct object_id oid;
-- if (!repo_get_oid(the_repository, arg, &oid)) {
-+ if (!repo_get_oid(repo, arg, &oid)) {
- struct reference ref = {
- .name = arg,
- .oid = &oid,
-@@ builtin/fsck.c: static void snapshot_refs(struct snapshot *snap, int argc, const char **argv)
- return;
- }
-
-- refs_for_each_ref_ext(get_main_ref_store(the_repository),
-+ refs_for_each_ref_ext(get_main_ref_store(repo),
- snapshot_ref, snap, &opts);
-
- worktrees = get_worktrees();
-@@ builtin/fsck.c: static void snapshot_refs(struct snapshot *snap, int argc, const char **argv)
-
- strbuf_worktree_ref(wt, &refname, "HEAD");
-
-- head_points_at = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
-+ head_points_at = refs_resolve_ref_unsafe(get_main_ref_store(repo),
- refname.buf, 0, &head_oid, NULL);
-
- if (head_points_at && !is_null_oid(&head_oid)) {
+ struct progress *progress = NULL;
+ struct for_each_loose_cb cb_data = {
@@ builtin/fsck.c: static void fsck_source(struct odb_source *source)
fprintf_ln(stderr, _("Checking object directory"));
if (show_progress)
- progress = start_progress(the_repository,
-+ progress = start_progress(source->odb->repo,
++ progress = start_progress(repo,
_("Checking object directories"), 256);
for_each_loose_file_in_source(source, fsck_loose,
@@ builtin/fsck.c: static void fsck_source(struct odb_source *source)
}
-static int fsck_cache_tree(struct cache_tree *it, const char *index_path)
-+static int fsck_cache_tree(struct repository *repo, struct cache_tree *it,
-+ const char *index_path)
++static int fsck_cache_tree(struct repository *repo, struct cache_tree *it, const char *index_path)
{
int i;
int err = 0;
@@ builtin/fsck.c: static int check_pack_rev_indexes(struct repository *r, int show
"Verifying reverse pack-indexes", pack_count);
pack_count = 0;
}
-@@ builtin/fsck.c: static struct option fsck_opts[] = {
- int cmd_fsck(int argc,
- const char **argv,
- const char *prefix,
-- struct repository *repo UNUSED)
-+ struct repository *repo)
- {
- struct odb_source *source;
- struct snapshot snap = {
@@ builtin/fsck.c: int cmd_fsck(int argc,
if (name_objects)
fsck_enable_object_names(&fsck_walk_options);
-- fsck_options_parse_config(&fsck_obj_options, the_repository);
+- repo_config(the_repository, git_fsck_config, &fsck_obj_options);
- prepare_repo_settings(the_repository);
-+ fsck_options_parse_config(&fsck_obj_options, repo);
++ repo_config(repo, git_fsck_config, &fsck_obj_options);
+ prepare_repo_settings(repo);
if (check_references)
@@ builtin/fsck.c: int cmd_fsck(int argc,
/*
* Take a snapshot of the refs before walking objects to avoid looking
@@ builtin/fsck.c: int cmd_fsck(int argc,
- * objects. We can still walk over new objects that are added during the
- * execution of fsck but won't miss any objects that were reachable.
- */
-- snapshot_refs(&snap, argc, argv);
-+ snapshot_refs(repo, &snap, argc, argv);
+ snapshot_refs(&snap, argc, argv);
/* Ensure we get a "fresh" view of the odb */
- odb_reprepare(the_repository->objects);
@@ builtin/fsck.c: int cmd_fsck(int argc,
} else {
- odb_prepare_alternates(the_repository->objects);
- for (source = the_repository->objects->sources; source; source = source->next)
+- fsck_source(source);
+ odb_prepare_alternates(repo->objects);
+ for (source = repo->objects->sources; source; source = source->next)
- fsck_source(source);
++ fsck_source(repo, source);
if (check_full) {
+ struct packed_git *p;
@@ builtin/fsck.c: int cmd_fsck(int argc,
struct progress *progress = NULL;
@@ builtin/fsck.c: int cmd_fsck(int argc,
p, fsck_obj_buffer,
progress, count))
errors_found |= ERROR_PACK;
-@@ builtin/fsck.c: int cmd_fsck(int argc,
- stop_progress(&progress);
- }
-
-- if (fsck_finish(the_repository, &fsck_obj_options))
-+ if (fsck_finish(repo, &fsck_obj_options))
- errors_found |= ERROR_OBJECT;
- }
-
@@ builtin/fsck.c: int cmd_fsck(int argc,
for (p = worktrees; *p; p++) {
struct worktree *wt = *p;
7: 65f1c0078b ! 6: 6c0507a4c8 builtin/fsck: stop using `the_repository` when snapshotting refs
@@ builtin/fsck.c: struct snapshot {
/*
* Increment default_refs anyway, because this is a
* valid ref.
-@@ builtin/fsck.c: static void snapshot_refs(struct repository *repo, struct snapshot *snap,
+@@ builtin/fsck.c: static int fsck_handle_ref(const struct reference *ref, void *cb_data UNUSED)
+ return 0;
+ }
+
+-static void snapshot_refs(struct snapshot *snap, int argc, const char **argv)
++static void snapshot_refs(struct repository *repo,
++ struct snapshot *snap, int argc, const char **argv)
+ {
struct refs_for_each_ref_options opts = {
.flags = REFS_FOR_EACH_INCLUDE_BROKEN,
};
@@ builtin/fsck.c: static void snapshot_refs(struct repository *repo, struct snapsh
struct worktree **worktrees, **p;
const char *head_points_at;
struct object_id head_oid;
-@@ builtin/fsck.c: static void snapshot_refs(struct repository *repo, struct snapshot *snap,
+@@ builtin/fsck.c: static void snapshot_refs(struct snapshot *snap, int argc, const char **argv)
+ for (int i = 0; i < argc; i++) {
+ const char *arg = argv[i];
+ struct object_id oid;
+- if (!repo_get_oid(the_repository, arg, &oid)) {
++ if (!repo_get_oid(repo, arg, &oid)) {
+ struct reference ref = {
+ .name = arg,
.oid = &oid,
};
@@ builtin/fsck.c: static void snapshot_refs(struct repository *repo, struct snapsh
continue;
}
error(_("invalid parameter: expected sha1, got '%s'"), arg);
-@@ builtin/fsck.c: static void snapshot_refs(struct repository *repo, struct snapshot *snap,
+@@ builtin/fsck.c: static void snapshot_refs(struct snapshot *snap, int argc, const char **argv)
+ return;
}
- refs_for_each_ref_ext(get_main_ref_store(repo),
+- refs_for_each_ref_ext(get_main_ref_store(the_repository),
- snapshot_ref, snap, &opts);
++ refs_for_each_ref_ext(get_main_ref_store(repo),
+ snapshot_ref, &data, &opts);
worktrees = get_worktrees();
for (p = worktrees; *p; p++) {
-@@ builtin/fsck.c: static void snapshot_refs(struct repository *repo, struct snapshot *snap,
+@@ builtin/fsck.c: static void snapshot_refs(struct snapshot *snap, int argc, const char **argv)
+
+ strbuf_worktree_ref(wt, &refname, "HEAD");
+
+- head_points_at = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
++ head_points_at = refs_resolve_ref_unsafe(get_main_ref_store(repo),
+ refname.buf, 0, &head_oid, NULL);
+
+ if (head_points_at && !is_null_oid(&head_oid)) {
+@@ builtin/fsck.c: static void snapshot_refs(struct snapshot *snap, int argc, const char **argv)
.oid = &head_oid,
};
@@ builtin/fsck.c: static void snapshot_refs(struct repository *repo, struct snapsh
}
strbuf_release(&refname);
+@@ builtin/fsck.c: int cmd_fsck(int argc,
+ * objects. We can still walk over new objects that are added during the
+ * execution of fsck but won't miss any objects that were reachable.
+ */
+- snapshot_refs(&snap, argc, argv);
++ snapshot_refs(repo, &snap, argc, argv);
+
+ /* Ensure we get a "fresh" view of the odb */
+ odb_reprepare(repo->objects);
8: 42b9d4ad29 = 7: 844a192db2 builtin/fsck: stop using `the_repository` when checking refs
9: 3c3af4cbcd = 8: 6557fc60ee builtin/fsck: stop using `the_repository` when checking reflogs
10: 387ba6f851 ! 9: 31709b33c8 builtin/fsck: stop using `the_repository` with loose objects
@@ Commit message
Signed-off-by: Patrick Steinhardt <ps@pks.im>
## builtin/fsck.c ##
-@@ builtin/fsck.c: static void check_connectivity(struct repository *repo)
- }
- }
-
--static int fsck_obj(struct object *obj, void *buffer, unsigned long size)
-+static int fsck_obj(struct repository *repo,
-+ struct object *obj,
-+ void *buffer, unsigned long size)
- {
- int err;
-
-@@ builtin/fsck.c: static int fsck_obj(struct object *obj, void *buffer, unsigned long size)
- printable_type(&obj->oid, obj->type),
- describe_object(&obj->oid));
-
-- if (fsck_walk(the_repository, obj, NULL, &fsck_obj_options))
-+ if (fsck_walk(repo, obj, NULL, &fsck_obj_options))
- objerror(obj, _("broken links"));
-- err = fsck_object(the_repository, obj, buffer, size, &fsck_obj_options);
-+ err = fsck_object(repo, obj, buffer, size, &fsck_obj_options);
- if (err)
- goto out;
-
-@@ builtin/fsck.c: static int fsck_obj_buffer(const struct object_id *oid, enum object_type type,
- }
- obj->flags &= ~(REACHABLE | SEEN);
- obj->flags |= HAS_OBJ;
-- return fsck_obj(obj, buffer, size);
-+ return fsck_obj(the_repository, obj, buffer, size);
- }
-
- static int default_refs;
@@ builtin/fsck.c: static void process_refs(struct repository *repo, struct snapshot *snap)
}
}
@@ builtin/fsck.c: static int fsck_loose(const struct object_id *oid, const char *p
contents, &eaten);
if (!obj) {
-@@ builtin/fsck.c: static int fsck_loose(const struct object_id *oid, const char *path,
-
- obj->flags &= ~(REACHABLE | SEEN);
- obj->flags |= HAS_OBJ;
-- if (fsck_obj(obj, contents, size))
-+ if (fsck_obj(data->repo, obj, contents, size))
- errors_found |= ERROR_OBJECT;
-
- if (!eaten)
-@@ builtin/fsck.c: static void fsck_source(struct odb_source *source)
+@@ builtin/fsck.c: static void fsck_source(struct repository *repo, struct odb_source *source)
{
struct progress *progress = NULL;
struct for_each_loose_cb cb_data = {
11: 031a245247 ! 10: ecbd9abef9 builtin/fsck: stop using `the_repository` when checking packed objects
@@ Commit message
Signed-off-by: Patrick Steinhardt <ps@pks.im>
## builtin/fsck.c ##
-@@ builtin/fsck.c: static int fsck_obj(struct repository *repo,
+@@ builtin/fsck.c: static int fsck_obj(struct object *obj, void *buffer, unsigned long size)
}
static int fsck_obj_buffer(const struct object_id *oid, enum object_type type,
@@ builtin/fsck.c: static int fsck_obj(struct repository *repo,
if (!obj) {
errors_found |= ERROR_OBJECT;
return error(_("%s: object corrupt or missing"),
-@@ builtin/fsck.c: static int fsck_obj_buffer(const struct object_id *oid, enum object_type type,
- }
- obj->flags &= ~(REACHABLE | SEEN);
- obj->flags |= HAS_OBJ;
-- return fsck_obj(the_repository, obj, buffer, size);
-+ return fsck_obj(repo, obj, buffer, size);
- }
-
- static int default_refs;
@@ builtin/fsck.c: int cmd_fsck(int argc,
repo_for_each_pack(repo, p) {
/* verify gives error messages itself */
12: 5d61f5a545 ! 11: 9e246797c5 builtin/fsck: stop using `the_repository` when marking objects
@@ Commit message
## builtin/fsck.c ##
@@ builtin/fsck.c: static int fsck_objects_error_func(struct fsck_options *o UNUSED,
-
static struct object_array pending;
-+struct mark_object_data {
-+ struct repository *repo;
-+ struct object *parent;
-+};
-+
static int mark_object(struct object *obj, enum object_type type,
- void *data, struct fsck_options *options UNUSED)
-+ void *cb_data, struct fsck_options *options UNUSED)
++ void *data, struct fsck_options *options)
{
-- struct object *parent = data;
-+ struct mark_object_data *data = cb_data;
-+ struct object *parent = data->parent;
+ struct object *parent = data;
- /*
- * The only case data is NULL or type is OBJ_ANY is when
@@ builtin/fsck.c: static int mark_object(struct object *obj, enum object_type type,
return 0;
obj->flags |= REACHABLE;
- if (is_promisor_object(the_repository, &obj->oid))
-+ if (is_promisor_object(data->repo, &obj->oid))
++ if (is_promisor_object(options->repo, &obj->oid))
/*
* Further recursion does not need to be performed on this
* object since it is a promisor object (so it does not need to
@@ builtin/fsck.c: static int mark_object(struct object *obj, enum object_type type
if (!(obj->flags & HAS_OBJ)) {
- if (parent && !odb_has_object(the_repository->objects, &obj->oid,
-+ if (parent && !odb_has_object(data->repo->objects, &obj->oid,
++ if (parent && !odb_has_object(options->repo->objects, &obj->oid,
HAS_OBJECT_RECHECK_PACKED)) {
printf_ln(_("broken link from %7s %s\n"
" to %7s %s"),
@@ builtin/fsck.c: static int mark_object(struct object *obj, enum object_type type,
- return 0;
- }
--static void mark_object_reachable(struct object *obj)
-+static void mark_object_reachable(struct repository *repo, struct object *obj)
+ static void mark_object_reachable(struct object *obj)
{
- mark_object(obj, OBJ_ANY, NULL, NULL);
-+ struct mark_object_data data = {
-+ .repo = repo,
-+ };
-+ mark_object(obj, OBJ_ANY, &data, NULL);
++ mark_object(obj, OBJ_ANY, NULL, &fsck_walk_options);
}
- static int traverse_one_object(struct repository *repo, struct object *obj)
- {
-- int result = fsck_walk(repo, obj, obj, &fsck_walk_options);
-+ struct mark_object_data data = {
-+ .repo = repo,
-+ .parent = obj,
-+ };
-+ int result = fsck_walk(repo, obj, &data, &fsck_walk_options);
-
- if (obj->type == OBJ_TREE) {
- struct tree *tree = (struct tree *)obj;
+ static int traverse_one_object(struct object *obj)
@@ builtin/fsck.c: static int mark_used(struct object *obj, enum object_type type UNUSED,
static int mark_unreachable_referents(const struct object_id *oid,
@@ builtin/fsck.c: static int mark_used(struct object *obj, enum object_type type U
+ void *data)
{
+ struct repository *repo = data;
- struct fsck_options options = FSCK_OPTIONS_DEFAULT;
+ struct fsck_options options;
- struct object *obj = lookup_object(the_repository, oid);
-+ struct object *obj = lookup_object(repo, oid);
++ struct object *obj = lookup_object(data, oid);
if (!obj || !(obj->flags & HAS_OBJ))
return 0; /* not part of our original set */
@@ builtin/fsck.c: static int mark_unreachable_referents(const struct object_id *oi
object_as_type(obj, type, 0);
}
+- fsck_options_init(&options, the_repository, FSCK_OPTIONS_DEFAULT);
++ fsck_options_init(&options, repo, FSCK_OPTIONS_DEFAULT);
options.walk = mark_used;
-- fsck_walk(the_repository, obj, NULL, &options);
-+ fsck_walk(repo, obj, NULL, &options);
+ fsck_walk(obj, NULL, &options);
if (obj->type == OBJ_TREE)
- free_tree_buffer((struct tree *)obj);
-
@@ builtin/fsck.c: static void check_connectivity(struct repository *repo)
* traversal.
*/
@@ builtin/fsck.c: static void check_connectivity(struct repository *repo)
}
/* Look up all the requirements, warn about missing objects.. */
-@@ builtin/fsck.c: static void fsck_handle_reflog_oid(struct repository *repo,
- "%s@{%"PRItime"}",
- refname, timestamp);
- obj->flags |= USED;
-- mark_object_reachable(obj);
-+ mark_object_reachable(repo, obj);
- } else if (!is_promisor_object(repo, oid)) {
- error(_("%s: invalid reflog entry %s"),
- refname, oid_to_hex(oid));
-@@ builtin/fsck.c: static int fsck_handle_ref(const struct reference *ref, void *cb_data)
- obj->flags |= USED;
- fsck_put_object_name(&fsck_walk_options,
- ref->oid, "%s", ref->name);
-- mark_object_reachable(obj);
-+ mark_object_reachable(repo, obj);
-
- return 0;
- }
-@@ builtin/fsck.c: static int fsck_cache_tree(struct repository *repo, struct cache_tree *it,
- }
- obj->flags |= USED;
- fsck_put_object_name(&fsck_walk_options, &it->oid, ":");
-- mark_object_reachable(obj);
-+ mark_object_reachable(repo, obj);
- if (obj->type != OBJ_TREE)
- err |= objerror(obj, _("non-tree in cache-tree"));
- }
-@@ builtin/fsck.c: static int fsck_resolve_undo(struct index_state *istate,
- obj->flags |= USED;
- fsck_put_object_name(&fsck_walk_options, &ru->oid[i],
- ":(%d):%s", i, path);
-- mark_object_reachable(obj);
-+ mark_object_reachable(istate->repo, obj);
- }
- }
- return 0;
-@@ builtin/fsck.c: static void fsck_index(struct index_state *istate, const char *index_path,
- "%s:%s",
- is_current_worktree ? "" : index_path,
- istate->cache[i]->name);
-- mark_object_reachable(obj);
-+ mark_object_reachable(istate->repo, obj);
- }
- if (istate->cache_tree)
- fsck_cache_tree(istate->repo, istate->cache_tree, index_path);
@@ builtin/fsck.c: static void fsck_index(struct index_state *istate, const char *index_path,
static int mark_object_for_connectivity(const struct object_id *oid,
13: 6842133df2 < -: ---------- fsck: provide repository in `struct fsck_report_object`
14: 06a88b16cd ! 12: 066e60a2ca builtin/fsck: stop using `the_repository` in error reporting
@@ builtin/fsck.c: static const char *describe_object(const struct object_id *oid)
if (type == OBJ_NONE)
- type = odb_read_object_info(the_repository->objects,
-+ type = odb_read_object_info(repo->objects,
- oid, NULL);
+- oid, NULL);
++ type = odb_read_object_info(repo->objects, oid, NULL);
ret = type_name(type);
+ if (!ret)
@@ builtin/fsck.c: static const char *printable_type(const struct object_id *oid,
return ret;
}
@@ builtin/fsck.c: static const char *printable_type(const struct object_id *oid,
describe_object(&obj->oid), err);
return -1;
}
+
+-static int fsck_objects_error_func(struct fsck_options *o UNUSED,
++static int fsck_objects_error_func(struct fsck_options *o,
+ void *fsck_report,
+ enum fsck_msg_type msg_type,
+ enum fsck_msg_id msg_id UNUSED,
@@ builtin/fsck.c: static int fsck_objects_error_func(struct fsck_options *o UNUSED,
case FSCK_WARN:
/* TRANSLATORS: e.g. warning in tree 01bfda: <more explanation> */
fprintf_ln(stderr, _("warning in %s %s: %s"),
- printable_type(oid, object_type),
-+ printable_type(report->repo, oid, object_type),
++ printable_type(o->repo, oid, object_type),
describe_object(oid), message);
return 0;
case FSCK_ERROR:
/* TRANSLATORS: e.g. error in tree 01bfda: <more explanation> */
fprintf_ln(stderr, _("error in %s %s: %s"),
- printable_type(oid, object_type),
-+ printable_type(report->repo, oid, object_type),
++ printable_type(o->repo, oid, object_type),
describe_object(oid), message);
return 1;
default:
@@ builtin/fsck.c: static int mark_object(struct object *obj, enum object_type type
/* ... these references to parent->fld are safe here */
printf_ln(_("broken link from %7s %s"),
- printable_type(&parent->oid, parent->type),
-+ printable_type(data->repo, &parent->oid, parent->type),
++ printable_type(options->repo, &parent->oid, parent->type),
describe_object(&parent->oid));
printf_ln(_("broken link from %7s %s"),
(type == OBJ_ANY ? _("unknown") : type_name(type)),
@@ builtin/fsck.c: static int mark_object(struct object *obj, enum object_type type
if (type != OBJ_ANY && obj->type != type)
/* ... and the reference to parent is safe here */
- objerror(parent, _("wrong object type in link"));
-+ objerror(data->repo, parent, _("wrong object type in link"));
++ objerror(options->repo, parent, _("wrong object type in link"));
if (obj->flags & REACHABLE)
return 0;
@@ builtin/fsck.c: static int mark_object(struct object *obj, enum object_type type
printf_ln(_("broken link from %7s %s\n"
" to %7s %s"),
- printable_type(&parent->oid, parent->type),
-+ printable_type(data->repo, &parent->oid, parent->type),
++ printable_type(options->repo, &parent->oid, parent->type),
describe_object(&parent->oid),
- printable_type(&obj->oid, obj->type),
-+ printable_type(data->repo, &obj->oid, obj->type),
++ printable_type(options->repo, &obj->oid, obj->type),
describe_object(&obj->oid));
errors_found |= ERROR_REACHABLE;
}
@@ builtin/fsck.c: static void check_unreachable_object(struct repository *repo, st
describe_object(&obj->oid));
if (write_lost_and_found) {
char *filename = repo_git_path(repo, "lost-found/%s/%s",
-@@ builtin/fsck.c: static int fsck_obj(struct repository *repo,
+@@ builtin/fsck.c: static void check_connectivity(struct repository *repo)
+ }
+ }
+
+-static int fsck_obj(struct object *obj, void *buffer, unsigned long size)
++static int fsck_obj(struct repository *repo,
++ struct object *obj, void *buffer, unsigned long size)
+ {
+ int err;
+
+@@ builtin/fsck.c: static int fsck_obj(struct object *obj, void *buffer, unsigned long size)
if (verbose)
fprintf_ln(stderr, _("Checking %s %s"),
@@ builtin/fsck.c: static int fsck_obj(struct repository *repo,
+ printable_type(repo, &obj->oid, obj->type),
describe_object(&obj->oid));
- if (fsck_walk(repo, obj, NULL, &fsck_obj_options))
+ if (fsck_walk(obj, NULL, &fsck_obj_options))
- objerror(obj, _("broken links"));
+ objerror(repo, obj, _("broken links"));
- err = fsck_object(repo, obj, buffer, size, &fsck_obj_options);
+ err = fsck_object(obj, buffer, size, &fsck_obj_options);
if (err)
goto out;
-@@ builtin/fsck.c: static int fsck_obj(struct repository *repo,
+@@ builtin/fsck.c: static int fsck_obj(struct object *obj, void *buffer, unsigned long size)
if (show_tags && tag->tagged) {
printf_ln(_("tagged %s %s (%s) in %s"),
@@ builtin/fsck.c: static int fsck_obj(struct repository *repo,
describe_object(&tag->tagged->oid),
tag->tag,
describe_object(&tag->object.oid));
-@@ builtin/fsck.c: static int fsck_cache_tree(struct repository *repo, struct cache_tree *it,
+@@ builtin/fsck.c: static int fsck_obj_buffer(const struct object_id *oid, enum object_type type,
+ }
+ obj->flags &= ~(REACHABLE | SEEN);
+ obj->flags |= HAS_OBJ;
+- return fsck_obj(obj, buffer, size);
++ return fsck_obj(repo, obj, buffer, size);
+ }
+
+ static int default_refs;
+@@ builtin/fsck.c: static int fsck_loose(const struct object_id *oid, const char *path,
+
+ obj->flags &= ~(REACHABLE | SEEN);
+ obj->flags |= HAS_OBJ;
+- if (fsck_obj(obj, contents, size))
++ if (fsck_obj(data->repo, obj, contents, size))
+ errors_found |= ERROR_OBJECT;
+
+ if (!eaten)
+@@ builtin/fsck.c: static int fsck_cache_tree(struct repository *repo, struct cache_tree *it, const
fsck_put_object_name(&fsck_walk_options, &it->oid, ":");
- mark_object_reachable(repo, obj);
+ mark_object_reachable(obj);
if (obj->type != OBJ_TREE)
- err |= objerror(obj, _("non-tree in cache-tree"));
+ err |= objerror(repo, obj, _("non-tree in cache-tree"));
---
base-commit: 7ff1e8dc1e1680510c96e69965b3fa81372c5037
change-id: 20260320-b4-pks-fsck-without-the-repository-4ddc4c8ed61e
^ permalink raw reply [flat|nested] 33+ messages in thread* [PATCH v2 01/12] fetch-pack: move fsck options into function scope
2026-03-23 15:02 ` [PATCH v2 00/12] fsck: drop use of `the_repository` Patrick Steinhardt
@ 2026-03-23 15:02 ` Patrick Steinhardt
2026-03-23 15:43 ` Junio C Hamano
2026-03-23 15:02 ` [PATCH v2 02/12] fsck: initialize fsck options via a function Patrick Steinhardt
` (10 subsequent siblings)
11 siblings, 1 reply; 33+ messages in thread
From: Patrick Steinhardt @ 2026-03-23 15:02 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
When fetching a packfile, we optionally verify received objects via the
fsck subsystem. The options for those consistency checks are declared in
global scope without a good reason, and they are never cleaned up. So in
case the options are reused, they may accumulate more state over time.
Furthermore, in subsequent changes we'll introduce a repository pointer
into the structure. Obviously though, we don't have a repository
available at static time, except for `the_repository`, which we don't
want to use here.
Refactor the code to move the options into the respective functions and
properly manage their lifecycle.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
fetch-pack.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/fetch-pack.c b/fetch-pack.c
index 6ecd468ef7..ec5abb92b5 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -51,7 +51,6 @@ static int server_supports_filtering;
static int advertise_sid;
static struct shallow_lock shallow_lock;
static const char *alternate_shallow_file;
-static struct fsck_options fsck_options = FSCK_OPTIONS_MISSING_GITMODULES;
static struct strbuf fsck_msg_types = STRBUF_INIT;
static struct string_list uri_protocols = STRING_LIST_INIT_DUP;
@@ -1100,6 +1099,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
struct shallow_info *si,
struct string_list *pack_lockfiles)
{
+ struct fsck_options fsck_options = FSCK_OPTIONS_MISSING_GITMODULES;
struct repository *r = the_repository;
struct ref *ref = copy_ref_list(orig_ref);
struct object_id oid;
@@ -1235,6 +1235,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
die("fsck failed");
all_done:
+ fsck_options_clear(&fsck_options);
if (negotiator)
negotiator->release(negotiator);
return ref;
@@ -1654,6 +1655,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
struct string_list *pack_lockfiles)
{
struct repository *r = the_repository;
+ struct fsck_options fsck_options = FSCK_OPTIONS_MISSING_GITMODULES;
struct ref *ref = copy_ref_list(orig_ref);
enum fetch_state state = FETCH_CHECK_LOCAL;
struct oidset common = OIDSET_INIT;
@@ -1882,6 +1884,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
if (negotiator)
negotiator->release(negotiator);
+ fsck_options_clear(&fsck_options);
oidset_clear(&common);
return ref;
}
--
2.53.0.1118.gaef5881109.dirty
^ permalink raw reply related [flat|nested] 33+ messages in thread* Re: [PATCH v2 01/12] fetch-pack: move fsck options into function scope
2026-03-23 15:02 ` [PATCH v2 01/12] fetch-pack: move fsck options into function scope Patrick Steinhardt
@ 2026-03-23 15:43 ` Junio C Hamano
0 siblings, 0 replies; 33+ messages in thread
From: Junio C Hamano @ 2026-03-23 15:43 UTC (permalink / raw)
To: Patrick Steinhardt; +Cc: git
Patrick Steinhardt <ps@pks.im> writes:
> When fetching a packfile, we optionally verify received objects via the
> fsck subsystem. The options for those consistency checks are declared in
> global scope without a good reason, and they are never cleaned up. So in
> case the options are reused, they may accumulate more state over time.
Great realization.
So we have two code paths (the original and v2), both of which used
to use the one in the global scope without cleaning up, but now we
have a way to proerly clean them up. Very nice.
> Furthermore, in subsequent changes we'll introduce a repository pointer
> into the structure. Obviously though, we don't have a repository
> available at static time, except for `the_repository`, which we don't
> want to use here.
>
> Refactor the code to move the options into the respective functions and
> properly manage their lifecycle.
>
> Signed-off-by: Patrick Steinhardt <ps@pks.im>
> ---
> fetch-pack.c | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/fetch-pack.c b/fetch-pack.c
> index 6ecd468ef7..ec5abb92b5 100644
> --- a/fetch-pack.c
> +++ b/fetch-pack.c
> @@ -51,7 +51,6 @@ static int server_supports_filtering;
> static int advertise_sid;
> static struct shallow_lock shallow_lock;
> static const char *alternate_shallow_file;
> -static struct fsck_options fsck_options = FSCK_OPTIONS_MISSING_GITMODULES;
> static struct strbuf fsck_msg_types = STRBUF_INIT;
> static struct string_list uri_protocols = STRING_LIST_INIT_DUP;
>
> @@ -1100,6 +1099,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
> struct shallow_info *si,
> struct string_list *pack_lockfiles)
> {
> + struct fsck_options fsck_options = FSCK_OPTIONS_MISSING_GITMODULES;
> struct repository *r = the_repository;
> struct ref *ref = copy_ref_list(orig_ref);
> struct object_id oid;
> @@ -1235,6 +1235,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
> die("fsck failed");
>
> all_done:
> + fsck_options_clear(&fsck_options);
> if (negotiator)
> negotiator->release(negotiator);
> return ref;
> @@ -1654,6 +1655,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
> struct string_list *pack_lockfiles)
> {
> struct repository *r = the_repository;
> + struct fsck_options fsck_options = FSCK_OPTIONS_MISSING_GITMODULES;
> struct ref *ref = copy_ref_list(orig_ref);
> enum fetch_state state = FETCH_CHECK_LOCAL;
> struct oidset common = OIDSET_INIT;
> @@ -1882,6 +1884,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
> if (negotiator)
> negotiator->release(negotiator);
>
> + fsck_options_clear(&fsck_options);
> oidset_clear(&common);
> return ref;
> }
^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH v2 02/12] fsck: initialize fsck options via a function
2026-03-23 15:02 ` [PATCH v2 00/12] fsck: drop use of `the_repository` Patrick Steinhardt
2026-03-23 15:02 ` [PATCH v2 01/12] fetch-pack: move fsck options into function scope Patrick Steinhardt
@ 2026-03-23 15:02 ` Patrick Steinhardt
2026-03-23 15:48 ` Junio C Hamano
2026-03-23 15:02 ` [PATCH v2 03/12] fsck: store repository in fsck options Patrick Steinhardt
` (9 subsequent siblings)
11 siblings, 1 reply; 33+ messages in thread
From: Patrick Steinhardt @ 2026-03-23 15:02 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
We initialize the `struct fsck_options` via a set of macros, often in
global scope. In the next commit though we're about to introduce a new
repository field to the options that must be initialized, and naturally
we don't have a repo other than `the_repository` available in this
scope.
Refactor the code to instead intrdouce a new `fsck_options_init()`
function that initializes the options for us and move initialization
into function scope.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
builtin/fsck.c | 10 +++++++---
builtin/index-pack.c | 4 +++-
builtin/mktag.c | 3 ++-
builtin/refs.c | 4 +++-
builtin/unpack-objects.c | 4 +++-
fetch-pack.c | 8 ++++++--
fsck.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
fsck.h | 38 ++++++++++----------------------------
object-file.c | 3 ++-
9 files changed, 81 insertions(+), 38 deletions(-)
diff --git a/builtin/fsck.c b/builtin/fsck.c
index 9bab32effe..59e3b0f7ac 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -42,8 +42,8 @@ static int check_full = 1;
static int connectivity_only;
static int check_strict;
static int keep_cache_objects;
-static struct fsck_options fsck_walk_options = FSCK_OPTIONS_DEFAULT;
-static struct fsck_options fsck_obj_options = FSCK_OPTIONS_DEFAULT;
+static struct fsck_options fsck_walk_options;
+static struct fsck_options fsck_obj_options;
static int errors_found;
static int write_lost_and_found;
static int verbose;
@@ -224,7 +224,7 @@ static int mark_unreachable_referents(const struct object_id *oid,
struct object_info *oi UNUSED,
void *data UNUSED)
{
- struct fsck_options options = FSCK_OPTIONS_DEFAULT;
+ struct fsck_options options;
struct object *obj = lookup_object(the_repository, oid);
if (!obj || !(obj->flags & HAS_OBJ))
@@ -243,6 +243,7 @@ static int mark_unreachable_referents(const struct object_id *oid,
object_as_type(obj, type, 0);
}
+ fsck_options_init(&options, FSCK_OPTIONS_DEFAULT);
options.walk = mark_used;
fsck_walk(obj, NULL, &options);
if (obj->type == OBJ_TREE)
@@ -1004,7 +1005,10 @@ int cmd_fsck(int argc,
argc = parse_options(argc, argv, prefix, fsck_opts, fsck_usage, 0);
+ fsck_options_init(&fsck_walk_options, FSCK_OPTIONS_DEFAULT);
fsck_walk_options.walk = mark_object;
+
+ fsck_options_init(&fsck_obj_options, FSCK_OPTIONS_DEFAULT);
fsck_obj_options.walk = mark_used;
fsck_obj_options.error_func = fsck_objects_error_func;
if (check_strict)
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index d1e47279a8..c8d28bcf8e 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -136,7 +136,7 @@ static int nr_threads;
static int from_stdin;
static int strict;
static int do_fsck_object;
-static struct fsck_options fsck_options = FSCK_OPTIONS_MISSING_GITMODULES;
+static struct fsck_options fsck_options;
static int verbose;
static const char *progress_title;
static int show_resolving_progress;
@@ -1908,6 +1908,8 @@ int cmd_index_pack(int argc,
show_usage_if_asked(argc, argv, index_pack_usage);
disable_replace_refs();
+
+ fsck_options_init(&fsck_options, FSCK_OPTIONS_MISSING_GITMODULES);
fsck_options.walk = mark_link;
reset_pack_idx_option(&opts);
diff --git a/builtin/mktag.c b/builtin/mktag.c
index 7cf6e1230a..9f37f9dede 100644
--- a/builtin/mktag.c
+++ b/builtin/mktag.c
@@ -16,7 +16,7 @@ static char const * const builtin_mktag_usage[] = {
};
static int option_strict = 1;
-static struct fsck_options fsck_options = FSCK_OPTIONS_STRICT;
+static struct fsck_options fsck_options;
static int mktag_fsck_error_func(struct fsck_options *o UNUSED,
void *fsck_report UNUSED,
@@ -94,6 +94,7 @@ int cmd_mktag(int argc,
if (strbuf_read(&buf, 0, 0) < 0)
die_errno(_("could not read from stdin"));
+ fsck_options_init(&fsck_options, FSCK_OPTIONS_STRICT);
fsck_options.error_func = mktag_fsck_error_func;
fsck_set_msg_type_from_ids(&fsck_options, FSCK_MSG_EXTRA_HEADER_ENTRY,
FSCK_WARN);
diff --git a/builtin/refs.c b/builtin/refs.c
index 3064f888b2..1719ada549 100644
--- a/builtin/refs.c
+++ b/builtin/refs.c
@@ -80,7 +80,7 @@ static int cmd_refs_migrate(int argc, const char **argv, const char *prefix,
static int cmd_refs_verify(int argc, const char **argv, const char *prefix,
struct repository *repo UNUSED)
{
- struct fsck_options fsck_refs_options = FSCK_REFS_OPTIONS_DEFAULT;
+ struct fsck_options fsck_refs_options;
struct worktree **worktrees;
const char * const verify_usage[] = {
REFS_VERIFY_USAGE,
@@ -93,6 +93,8 @@ static int cmd_refs_verify(int argc, const char **argv, const char *prefix,
};
int ret = 0;
+ fsck_options_init(&fsck_refs_options, FSCK_OPTIONS_REFS);
+
argc = parse_options(argc, argv, prefix, options, verify_usage, 0);
if (argc)
usage(_("'git refs verify' takes no arguments"));
diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c
index 6fc64e9e4b..9e4bb9d25c 100644
--- a/builtin/unpack-objects.c
+++ b/builtin/unpack-objects.c
@@ -29,7 +29,7 @@ static unsigned int offset, len;
static off_t consumed_bytes;
static off_t max_input_size;
static struct git_hash_ctx ctx;
-static struct fsck_options fsck_options = FSCK_OPTIONS_STRICT;
+static struct fsck_options fsck_options;
static struct progress *progress;
/*
@@ -627,6 +627,8 @@ int cmd_unpack_objects(int argc,
show_usage_if_asked(argc, argv, unpack_usage);
+ fsck_options_init(&fsck_options, FSCK_OPTIONS_STRICT);
+
for (i = 1 ; i < argc; i++) {
const char *arg = argv[i];
diff --git a/fetch-pack.c b/fetch-pack.c
index ec5abb92b5..7339162368 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -1099,7 +1099,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
struct shallow_info *si,
struct string_list *pack_lockfiles)
{
- struct fsck_options fsck_options = FSCK_OPTIONS_MISSING_GITMODULES;
+ struct fsck_options fsck_options = { 0 };
struct repository *r = the_repository;
struct ref *ref = copy_ref_list(orig_ref);
struct object_id oid;
@@ -1228,6 +1228,8 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
alternate_shallow_file = setup_temporary_shallow(si->shallow);
} else
alternate_shallow_file = NULL;
+
+ fsck_options_init(&fsck_options, FSCK_OPTIONS_MISSING_GITMODULES);
if (get_pack(args, fd, pack_lockfiles, NULL, sought, nr_sought,
&fsck_options.gitmodules_found))
die(_("git fetch-pack: fetch failed."));
@@ -1655,7 +1657,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
struct string_list *pack_lockfiles)
{
struct repository *r = the_repository;
- struct fsck_options fsck_options = FSCK_OPTIONS_MISSING_GITMODULES;
+ struct fsck_options fsck_options;
struct ref *ref = copy_ref_list(orig_ref);
enum fetch_state state = FETCH_CHECK_LOCAL;
struct oidset common = OIDSET_INIT;
@@ -1673,6 +1675,8 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
struct strvec index_pack_args = STRVEC_INIT;
const char *promisor_remote_config;
+ fsck_options_init(&fsck_options, FSCK_OPTIONS_MISSING_GITMODULES);
+
if (server_feature_v2("promisor-remote", &promisor_remote_config))
promisor_remote_reply(promisor_remote_config, NULL);
diff --git a/fsck.c b/fsck.c
index 0f02cf8f77..1ff8208502 100644
--- a/fsck.c
+++ b/fsck.c
@@ -1380,6 +1380,51 @@ bool fsck_has_queued_checks(struct fsck_options *options)
!oidset_equal(&options->gitattributes_found, &options->gitattributes_done);
}
+void fsck_options_init(struct fsck_options *options,
+ enum fsck_options_type type)
+{
+ static const struct fsck_options defaults[] = {
+ [FSCK_OPTIONS_DEFAULT] = {
+ .skip_oids = OIDSET_INIT,
+ .gitmodules_found = OIDSET_INIT,
+ .gitmodules_done = OIDSET_INIT,
+ .gitattributes_found = OIDSET_INIT,
+ .gitattributes_done = OIDSET_INIT,
+ .error_func = fsck_objects_error_function
+ },
+ [FSCK_OPTIONS_STRICT] = {
+ .strict = 1,
+ .gitmodules_found = OIDSET_INIT,
+ .gitmodules_done = OIDSET_INIT,
+ .gitattributes_found = OIDSET_INIT,
+ .gitattributes_done = OIDSET_INIT,
+ .error_func = fsck_objects_error_function,
+ },
+ [FSCK_OPTIONS_MISSING_GITMODULES] = {
+ .strict = 1,
+ .gitmodules_found = OIDSET_INIT,
+ .gitmodules_done = OIDSET_INIT,
+ .gitattributes_found = OIDSET_INIT,
+ .gitattributes_done = OIDSET_INIT,
+ .error_func = fsck_objects_error_cb_print_missing_gitmodules,
+ },
+ [FSCK_OPTIONS_REFS] = {
+ .error_func = fsck_refs_error_function,
+ },
+ };
+
+ switch (type) {
+ case FSCK_OPTIONS_DEFAULT:
+ case FSCK_OPTIONS_STRICT:
+ case FSCK_OPTIONS_MISSING_GITMODULES:
+ case FSCK_OPTIONS_REFS:
+ memcpy(options, &defaults[type], sizeof(*options));
+ break;
+ default:
+ BUG("unknown fsck options type %d", type);
+ }
+}
+
void fsck_options_clear(struct fsck_options *options)
{
free(options->msg_type);
diff --git a/fsck.h b/fsck.h
index 65ecbb7fe1..9c973b53b2 100644
--- a/fsck.h
+++ b/fsck.h
@@ -180,34 +180,6 @@ struct fsck_options {
kh_oid_map_t *object_names;
};
-#define FSCK_OPTIONS_DEFAULT { \
- .skip_oids = OIDSET_INIT, \
- .gitmodules_found = OIDSET_INIT, \
- .gitmodules_done = OIDSET_INIT, \
- .gitattributes_found = OIDSET_INIT, \
- .gitattributes_done = OIDSET_INIT, \
- .error_func = fsck_objects_error_function \
-}
-#define FSCK_OPTIONS_STRICT { \
- .strict = 1, \
- .gitmodules_found = OIDSET_INIT, \
- .gitmodules_done = OIDSET_INIT, \
- .gitattributes_found = OIDSET_INIT, \
- .gitattributes_done = OIDSET_INIT, \
- .error_func = fsck_objects_error_function, \
-}
-#define FSCK_OPTIONS_MISSING_GITMODULES { \
- .strict = 1, \
- .gitmodules_found = OIDSET_INIT, \
- .gitmodules_done = OIDSET_INIT, \
- .gitattributes_found = OIDSET_INIT, \
- .gitattributes_done = OIDSET_INIT, \
- .error_func = fsck_objects_error_cb_print_missing_gitmodules, \
-}
-#define FSCK_REFS_OPTIONS_DEFAULT { \
- .error_func = fsck_refs_error_function, \
-}
-
/* descend in all linked child objects
* the return value is:
* -1 error in processing the object
@@ -255,6 +227,16 @@ int fsck_finish(struct fsck_options *options);
*/
bool fsck_has_queued_checks(struct fsck_options *options);
+enum fsck_options_type {
+ FSCK_OPTIONS_DEFAULT,
+ FSCK_OPTIONS_STRICT,
+ FSCK_OPTIONS_MISSING_GITMODULES,
+ FSCK_OPTIONS_REFS,
+};
+
+void fsck_options_init(struct fsck_options *options,
+ enum fsck_options_type type);
+
/*
* Clear the fsck_options struct, freeing any allocated memory.
*/
diff --git a/object-file.c b/object-file.c
index c62e5496e0..186b2ff764 100644
--- a/object-file.c
+++ b/object-file.c
@@ -1279,8 +1279,9 @@ static int index_mem(struct index_state *istate,
}
}
if (flags & INDEX_FORMAT_CHECK) {
- struct fsck_options opts = FSCK_OPTIONS_DEFAULT;
+ struct fsck_options opts;
+ fsck_options_init(&opts, FSCK_OPTIONS_DEFAULT);
opts.strict = 1;
opts.error_func = hash_format_check_report;
if (fsck_buffer(null_oid(istate->repo->hash_algo), type, buf, size, &opts))
--
2.53.0.1118.gaef5881109.dirty
^ permalink raw reply related [flat|nested] 33+ messages in thread* Re: [PATCH v2 02/12] fsck: initialize fsck options via a function
2026-03-23 15:02 ` [PATCH v2 02/12] fsck: initialize fsck options via a function Patrick Steinhardt
@ 2026-03-23 15:48 ` Junio C Hamano
0 siblings, 0 replies; 33+ messages in thread
From: Junio C Hamano @ 2026-03-23 15:48 UTC (permalink / raw)
To: Patrick Steinhardt; +Cc: git
Patrick Steinhardt <ps@pks.im> writes:
> +void fsck_options_init(struct fsck_options *options,
> + enum fsck_options_type type)
> +{
> + static const struct fsck_options defaults[] = {
> + [FSCK_OPTIONS_DEFAULT] = {
> + .skip_oids = OIDSET_INIT,
> + .gitmodules_found = OIDSET_INIT,
> + .gitmodules_done = OIDSET_INIT,
> + .gitattributes_found = OIDSET_INIT,
> + .gitattributes_done = OIDSET_INIT,
> + .error_func = fsck_objects_error_function
> + },
> + [FSCK_OPTIONS_STRICT] = {
> + .strict = 1,
> + .gitmodules_found = OIDSET_INIT,
> + .gitmodules_done = OIDSET_INIT,
> + .gitattributes_found = OIDSET_INIT,
> + .gitattributes_done = OIDSET_INIT,
> + .error_func = fsck_objects_error_function,
> + },
> + [FSCK_OPTIONS_MISSING_GITMODULES] = {
> + .strict = 1,
> + .gitmodules_found = OIDSET_INIT,
> + .gitmodules_done = OIDSET_INIT,
> + .gitattributes_found = OIDSET_INIT,
> + .gitattributes_done = OIDSET_INIT,
> + .error_func = fsck_objects_error_cb_print_missing_gitmodules,
> + },
> + [FSCK_OPTIONS_REFS] = {
> + .error_func = fsck_refs_error_function,
> + },
> + };
> +
> + switch (type) {
> + case FSCK_OPTIONS_DEFAULT:
> + case FSCK_OPTIONS_STRICT:
> + case FSCK_OPTIONS_MISSING_GITMODULES:
> + case FSCK_OPTIONS_REFS:
> + memcpy(options, &defaults[type], sizeof(*options));
> + break;
> + default:
> + BUG("unknown fsck options type %d", type);
> + }
> +}
Wow, nice reorganization that migrates the earlier definitions from
the header file.
By reusing these FSCK_OPTIONS_* names as an enum elements, we will
let the compiler catch if any other branch adds new uses of these
names with their original meaning, which is a nice touch, too.
> void fsck_options_clear(struct fsck_options *options)
> {
> free(options->msg_type);
> diff --git a/fsck.h b/fsck.h
> index 65ecbb7fe1..9c973b53b2 100644
> --- a/fsck.h
> +++ b/fsck.h
> @@ -180,34 +180,6 @@ struct fsck_options {
> kh_oid_map_t *object_names;
> };
>
> -#define FSCK_OPTIONS_DEFAULT { \
> - .skip_oids = OIDSET_INIT, \
> - .gitmodules_found = OIDSET_INIT, \
> - .gitmodules_done = OIDSET_INIT, \
> - .gitattributes_found = OIDSET_INIT, \
> - .gitattributes_done = OIDSET_INIT, \
> - .error_func = fsck_objects_error_function \
> -}
> -#define FSCK_OPTIONS_STRICT { \
> - .strict = 1, \
> - .gitmodules_found = OIDSET_INIT, \
> - .gitmodules_done = OIDSET_INIT, \
> - .gitattributes_found = OIDSET_INIT, \
> - .gitattributes_done = OIDSET_INIT, \
> - .error_func = fsck_objects_error_function, \
> -}
> -#define FSCK_OPTIONS_MISSING_GITMODULES { \
> - .strict = 1, \
> - .gitmodules_found = OIDSET_INIT, \
> - .gitmodules_done = OIDSET_INIT, \
> - .gitattributes_found = OIDSET_INIT, \
> - .gitattributes_done = OIDSET_INIT, \
> - .error_func = fsck_objects_error_cb_print_missing_gitmodules, \
> -}
> -#define FSCK_REFS_OPTIONS_DEFAULT { \
> - .error_func = fsck_refs_error_function, \
> -}
> -
> /* descend in all linked child objects
> * the return value is:
> * -1 error in processing the object
> @@ -255,6 +227,16 @@ int fsck_finish(struct fsck_options *options);
> */
> bool fsck_has_queued_checks(struct fsck_options *options);
>
> +enum fsck_options_type {
> + FSCK_OPTIONS_DEFAULT,
> + FSCK_OPTIONS_STRICT,
> + FSCK_OPTIONS_MISSING_GITMODULES,
> + FSCK_OPTIONS_REFS,
> +};
> +
> +void fsck_options_init(struct fsck_options *options,
> + enum fsck_options_type type);
> +
> /*
> * Clear the fsck_options struct, freeing any allocated memory.
> */
> diff --git a/object-file.c b/object-file.c
> index c62e5496e0..186b2ff764 100644
> --- a/object-file.c
> +++ b/object-file.c
> @@ -1279,8 +1279,9 @@ static int index_mem(struct index_state *istate,
> }
> }
> if (flags & INDEX_FORMAT_CHECK) {
> - struct fsck_options opts = FSCK_OPTIONS_DEFAULT;
> + struct fsck_options opts;
>
> + fsck_options_init(&opts, FSCK_OPTIONS_DEFAULT);
> opts.strict = 1;
> opts.error_func = hash_format_check_report;
> if (fsck_buffer(null_oid(istate->repo->hash_algo), type, buf, size, &opts))
^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH v2 03/12] fsck: store repository in fsck options
2026-03-23 15:02 ` [PATCH v2 00/12] fsck: drop use of `the_repository` Patrick Steinhardt
2026-03-23 15:02 ` [PATCH v2 01/12] fetch-pack: move fsck options into function scope Patrick Steinhardt
2026-03-23 15:02 ` [PATCH v2 02/12] fsck: initialize fsck options via a function Patrick Steinhardt
@ 2026-03-23 15:02 ` Patrick Steinhardt
2026-03-23 15:02 ` [PATCH v2 04/12] fsck: drop USE_THE_REPOSITORY Patrick Steinhardt
` (8 subsequent siblings)
11 siblings, 0 replies; 33+ messages in thread
From: Patrick Steinhardt @ 2026-03-23 15:02 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
The fsck subsystem relies on `the_repository` quite a bit. While we
could of course explicitly pass a repository down the callchain, we
already have a `struct fsck_options` that we pass to almost all
functions.
Extend the options to also store the repository to make it readily
available.
Suggested-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
builtin/fsck.c | 8 ++++----
builtin/index-pack.c | 2 +-
builtin/mktag.c | 4 ++--
builtin/refs.c | 4 ++--
builtin/unpack-objects.c | 4 ++--
fetch-pack.c | 4 ++--
fsck.c | 3 +++
fsck.h | 4 ++++
object-file.c | 2 +-
9 files changed, 21 insertions(+), 14 deletions(-)
diff --git a/builtin/fsck.c b/builtin/fsck.c
index 59e3b0f7ac..990d836918 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -243,7 +243,7 @@ static int mark_unreachable_referents(const struct object_id *oid,
object_as_type(obj, type, 0);
}
- fsck_options_init(&options, FSCK_OPTIONS_DEFAULT);
+ fsck_options_init(&options, the_repository, FSCK_OPTIONS_DEFAULT);
options.walk = mark_used;
fsck_walk(obj, NULL, &options);
if (obj->type == OBJ_TREE)
@@ -987,7 +987,7 @@ static struct option fsck_opts[] = {
int cmd_fsck(int argc,
const char **argv,
const char *prefix,
- struct repository *repo UNUSED)
+ struct repository *repo)
{
struct odb_source *source;
struct snapshot snap = {
@@ -1005,10 +1005,10 @@ int cmd_fsck(int argc,
argc = parse_options(argc, argv, prefix, fsck_opts, fsck_usage, 0);
- fsck_options_init(&fsck_walk_options, FSCK_OPTIONS_DEFAULT);
+ fsck_options_init(&fsck_walk_options, repo, FSCK_OPTIONS_DEFAULT);
fsck_walk_options.walk = mark_object;
- fsck_options_init(&fsck_obj_options, FSCK_OPTIONS_DEFAULT);
+ fsck_options_init(&fsck_obj_options, repo, FSCK_OPTIONS_DEFAULT);
fsck_obj_options.walk = mark_used;
fsck_obj_options.error_func = fsck_objects_error_func;
if (check_strict)
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index c8d28bcf8e..e4129bd605 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -1909,7 +1909,7 @@ int cmd_index_pack(int argc,
disable_replace_refs();
- fsck_options_init(&fsck_options, FSCK_OPTIONS_MISSING_GITMODULES);
+ fsck_options_init(&fsck_options, the_repository, FSCK_OPTIONS_MISSING_GITMODULES);
fsck_options.walk = mark_link;
reset_pack_idx_option(&opts);
diff --git a/builtin/mktag.c b/builtin/mktag.c
index 9f37f9dede..f40264a878 100644
--- a/builtin/mktag.c
+++ b/builtin/mktag.c
@@ -75,7 +75,7 @@ static int verify_object_in_tag(struct object_id *tagged_oid, int *tagged_type)
int cmd_mktag(int argc,
const char **argv,
const char *prefix,
- struct repository *repo UNUSED)
+ struct repository *repo)
{
static struct option builtin_mktag_options[] = {
OPT_BOOL(0, "strict", &option_strict,
@@ -94,7 +94,7 @@ int cmd_mktag(int argc,
if (strbuf_read(&buf, 0, 0) < 0)
die_errno(_("could not read from stdin"));
- fsck_options_init(&fsck_options, FSCK_OPTIONS_STRICT);
+ fsck_options_init(&fsck_options, repo, FSCK_OPTIONS_STRICT);
fsck_options.error_func = mktag_fsck_error_func;
fsck_set_msg_type_from_ids(&fsck_options, FSCK_MSG_EXTRA_HEADER_ENTRY,
FSCK_WARN);
diff --git a/builtin/refs.c b/builtin/refs.c
index 1719ada549..e3125bc61b 100644
--- a/builtin/refs.c
+++ b/builtin/refs.c
@@ -78,7 +78,7 @@ static int cmd_refs_migrate(int argc, const char **argv, const char *prefix,
}
static int cmd_refs_verify(int argc, const char **argv, const char *prefix,
- struct repository *repo UNUSED)
+ struct repository *repo)
{
struct fsck_options fsck_refs_options;
struct worktree **worktrees;
@@ -93,7 +93,7 @@ static int cmd_refs_verify(int argc, const char **argv, const char *prefix,
};
int ret = 0;
- fsck_options_init(&fsck_refs_options, FSCK_OPTIONS_REFS);
+ fsck_options_init(&fsck_refs_options, repo, FSCK_OPTIONS_REFS);
argc = parse_options(argc, argv, prefix, options, verify_usage, 0);
if (argc)
diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c
index 9e4bb9d25c..d863912b24 100644
--- a/builtin/unpack-objects.c
+++ b/builtin/unpack-objects.c
@@ -613,7 +613,7 @@ static void unpack_all(void)
int cmd_unpack_objects(int argc,
const char **argv,
const char *prefix UNUSED,
- struct repository *repo UNUSED)
+ struct repository *repo)
{
int i;
struct object_id oid;
@@ -627,7 +627,7 @@ int cmd_unpack_objects(int argc,
show_usage_if_asked(argc, argv, unpack_usage);
- fsck_options_init(&fsck_options, FSCK_OPTIONS_STRICT);
+ fsck_options_init(&fsck_options, repo, FSCK_OPTIONS_STRICT);
for (i = 1 ; i < argc; i++) {
const char *arg = argv[i];
diff --git a/fetch-pack.c b/fetch-pack.c
index 7339162368..84a21c5107 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -1229,7 +1229,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
} else
alternate_shallow_file = NULL;
- fsck_options_init(&fsck_options, FSCK_OPTIONS_MISSING_GITMODULES);
+ fsck_options_init(&fsck_options, the_repository, FSCK_OPTIONS_MISSING_GITMODULES);
if (get_pack(args, fd, pack_lockfiles, NULL, sought, nr_sought,
&fsck_options.gitmodules_found))
die(_("git fetch-pack: fetch failed."));
@@ -1675,7 +1675,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
struct strvec index_pack_args = STRVEC_INIT;
const char *promisor_remote_config;
- fsck_options_init(&fsck_options, FSCK_OPTIONS_MISSING_GITMODULES);
+ fsck_options_init(&fsck_options, the_repository, FSCK_OPTIONS_MISSING_GITMODULES);
if (server_feature_v2("promisor-remote", &promisor_remote_config))
promisor_remote_reply(promisor_remote_config, NULL);
diff --git a/fsck.c b/fsck.c
index 1ff8208502..a05997703a 100644
--- a/fsck.c
+++ b/fsck.c
@@ -1381,6 +1381,7 @@ bool fsck_has_queued_checks(struct fsck_options *options)
}
void fsck_options_init(struct fsck_options *options,
+ struct repository *repo,
enum fsck_options_type type)
{
static const struct fsck_options defaults[] = {
@@ -1423,6 +1424,8 @@ void fsck_options_init(struct fsck_options *options,
default:
BUG("unknown fsck options type %d", type);
}
+
+ options->repo = repo;
}
void fsck_options_clear(struct fsck_options *options)
diff --git a/fsck.h b/fsck.h
index 9c973b53b2..e77935c8a9 100644
--- a/fsck.h
+++ b/fsck.h
@@ -166,7 +166,10 @@ struct fsck_ref_report {
const char *path;
};
+struct repository;
+
struct fsck_options {
+ struct repository *repo;
fsck_walk_func walk;
fsck_error error_func;
unsigned strict;
@@ -235,6 +238,7 @@ enum fsck_options_type {
};
void fsck_options_init(struct fsck_options *options,
+ struct repository *repo,
enum fsck_options_type type);
/*
diff --git a/object-file.c b/object-file.c
index 186b2ff764..24ed5d5577 100644
--- a/object-file.c
+++ b/object-file.c
@@ -1281,7 +1281,7 @@ static int index_mem(struct index_state *istate,
if (flags & INDEX_FORMAT_CHECK) {
struct fsck_options opts;
- fsck_options_init(&opts, FSCK_OPTIONS_DEFAULT);
+ fsck_options_init(&opts, the_repository, FSCK_OPTIONS_DEFAULT);
opts.strict = 1;
opts.error_func = hash_format_check_report;
if (fsck_buffer(null_oid(istate->repo->hash_algo), type, buf, size, &opts))
--
2.53.0.1118.gaef5881109.dirty
^ permalink raw reply related [flat|nested] 33+ messages in thread* [PATCH v2 04/12] fsck: drop USE_THE_REPOSITORY
2026-03-23 15:02 ` [PATCH v2 00/12] fsck: drop use of `the_repository` Patrick Steinhardt
` (2 preceding siblings ...)
2026-03-23 15:02 ` [PATCH v2 03/12] fsck: store repository in fsck options Patrick Steinhardt
@ 2026-03-23 15:02 ` Patrick Steinhardt
2026-03-23 15:02 ` [PATCH v2 05/12] builtin/fsck: fix trivial dependence on `the_repository` Patrick Steinhardt
` (7 subsequent siblings)
11 siblings, 0 replies; 33+ messages in thread
From: Patrick Steinhardt @ 2026-03-23 15:02 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
Stop using `the_repository` in "fsck.c" in favor of the repository that
we've already got available via `struct fsck_options`.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
fsck.c | 28 +++++++++++++---------------
1 file changed, 13 insertions(+), 15 deletions(-)
diff --git a/fsck.c b/fsck.c
index a05997703a..b72200c352 100644
--- a/fsck.c
+++ b/fsck.c
@@ -1,5 +1,3 @@
-#define USE_THE_REPOSITORY_VARIABLE
-
#include "git-compat-util.h"
#include "date.h"
#include "dir.h"
@@ -207,7 +205,7 @@ void fsck_set_msg_types(struct fsck_options *options, const char *values)
if (equal == len)
die("skiplist requires a path");
oidset_parse_file(&options->skip_oids, buf + equal + 1,
- the_repository->hash_algo);
+ options->repo->hash_algo);
buf += len + 1;
continue;
}
@@ -360,7 +358,7 @@ static int fsck_walk_tree(struct tree *tree, void *data, struct fsck_options *op
int res = 0;
const char *name;
- if (repo_parse_tree(the_repository, tree))
+ if (repo_parse_tree(options->repo, tree))
return -1;
name = fsck_get_object_name(options, &tree->object.oid);
@@ -375,14 +373,14 @@ static int fsck_walk_tree(struct tree *tree, void *data, struct fsck_options *op
continue;
if (S_ISDIR(entry.mode)) {
- obj = (struct object *)lookup_tree(the_repository, &entry.oid);
+ obj = (struct object *)lookup_tree(options->repo, &entry.oid);
if (name && obj)
fsck_put_object_name(options, &entry.oid, "%s%s/",
name, entry.path);
result = options->walk(obj, OBJ_TREE, data, options);
}
else if (S_ISREG(entry.mode) || S_ISLNK(entry.mode)) {
- obj = (struct object *)lookup_blob(the_repository, &entry.oid);
+ obj = (struct object *)lookup_blob(options->repo, &entry.oid);
if (name && obj)
fsck_put_object_name(options, &entry.oid, "%s%s",
name, entry.path);
@@ -409,7 +407,7 @@ static int fsck_walk_commit(struct commit *commit, void *data, struct fsck_optio
int result;
const char *name;
- if (repo_parse_commit(the_repository, commit))
+ if (repo_parse_commit(options->repo, commit))
return -1;
name = fsck_get_object_name(options, &commit->object.oid);
@@ -417,7 +415,7 @@ static int fsck_walk_commit(struct commit *commit, void *data, struct fsck_optio
fsck_put_object_name(options, get_commit_tree_oid(commit),
"%s:", name);
- result = options->walk((struct object *) repo_get_commit_tree(the_repository, commit),
+ result = options->walk((struct object *) repo_get_commit_tree(options->repo, commit),
OBJ_TREE, data, options);
if (result < 0)
return result;
@@ -474,7 +472,7 @@ static int fsck_walk_tag(struct tag *tag, void *data, struct fsck_options *optio
{
const char *name = fsck_get_object_name(options, &tag->object.oid);
- if (parse_tag(the_repository, tag))
+ if (parse_tag(options->repo, tag))
return -1;
if (name)
fsck_put_object_name(options, &tag->tagged->oid, "%s", name);
@@ -487,7 +485,7 @@ int fsck_walk(struct object *obj, void *data, struct fsck_options *options)
return -1;
if (obj->type == OBJ_NONE)
- parse_object(the_repository, &obj->oid);
+ parse_object(options->repo, &obj->oid);
switch (obj->type) {
case OBJ_BLOB:
@@ -970,14 +968,14 @@ static int fsck_commit(const struct object_id *oid,
if (buffer >= buffer_end || !skip_prefix(buffer, "tree ", &buffer))
return report(options, oid, OBJ_COMMIT, FSCK_MSG_MISSING_TREE, "invalid format - expected 'tree' line");
- if (parse_oid_hex(buffer, &tree_oid, &p) || *p != '\n') {
+ if (parse_oid_hex_algop(buffer, &tree_oid, &p, options->repo->hash_algo) || *p != '\n') {
err = report(options, oid, OBJ_COMMIT, FSCK_MSG_BAD_TREE_SHA1, "invalid 'tree' line format - bad sha1");
if (err)
return err;
}
buffer = p + 1;
while (buffer < buffer_end && skip_prefix(buffer, "parent ", &buffer)) {
- if (parse_oid_hex(buffer, &parent_oid, &p) || *p != '\n') {
+ if (parse_oid_hex_algop(buffer, &parent_oid, &p, options->repo->hash_algo) || *p != '\n') {
err = report(options, oid, OBJ_COMMIT, FSCK_MSG_BAD_PARENT_SHA1, "invalid 'parent' line format - bad sha1");
if (err)
return err;
@@ -1044,7 +1042,7 @@ int fsck_tag_standalone(const struct object_id *oid, const char *buffer,
ret = report(options, oid, OBJ_TAG, FSCK_MSG_MISSING_OBJECT, "invalid format - expected 'object' line");
goto done;
}
- if (parse_oid_hex(buffer, tagged_oid, &p) || *p != '\n') {
+ if (parse_oid_hex_algop(buffer, tagged_oid, &p, options->repo->hash_algo) || *p != '\n') {
ret = report(options, oid, OBJ_TAG, FSCK_MSG_BAD_OBJECT_SHA1, "invalid 'object' line format - bad sha1");
if (ret)
goto done;
@@ -1336,9 +1334,9 @@ static int fsck_blobs(struct oidset *blobs_found, struct oidset *blobs_done,
if (oidset_contains(blobs_done, oid))
continue;
- buf = odb_read_object(the_repository->objects, oid, &type, &size);
+ buf = odb_read_object(options->repo->objects, oid, &type, &size);
if (!buf) {
- if (is_promisor_object(the_repository, oid))
+ if (is_promisor_object(options->repo, oid))
continue;
ret |= report(options,
oid, OBJ_BLOB, msg_missing,
--
2.53.0.1118.gaef5881109.dirty
^ permalink raw reply related [flat|nested] 33+ messages in thread* [PATCH v2 05/12] builtin/fsck: fix trivial dependence on `the_repository`
2026-03-23 15:02 ` [PATCH v2 00/12] fsck: drop use of `the_repository` Patrick Steinhardt
` (3 preceding siblings ...)
2026-03-23 15:02 ` [PATCH v2 04/12] fsck: drop USE_THE_REPOSITORY Patrick Steinhardt
@ 2026-03-23 15:02 ` Patrick Steinhardt
2026-03-23 15:02 ` [PATCH v2 06/12] builtin/fsck: stop using `the_repository` when snapshotting refs Patrick Steinhardt
` (6 subsequent siblings)
11 siblings, 0 replies; 33+ messages in thread
From: Patrick Steinhardt @ 2026-03-23 15:02 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
We have a bunch of sites in "builtin/fsck.c" that depend on
`the_repository` even though we already have a repository available, or
in cases where we can trivially make it available.
Refactor such sites to use the context-provided repository instead.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
builtin/fsck.c | 98 +++++++++++++++++++++++++++++-----------------------------
1 file changed, 49 insertions(+), 49 deletions(-)
diff --git a/builtin/fsck.c b/builtin/fsck.c
index 990d836918..59680e6daf 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -195,13 +195,13 @@ static int traverse_one_object(struct object *obj)
return result;
}
-static int traverse_reachable(void)
+static int traverse_reachable(struct repository *repo)
{
struct progress *progress = NULL;
unsigned int nr = 0;
int result = 0;
if (show_progress)
- progress = start_delayed_progress(the_repository,
+ progress = start_delayed_progress(repo,
_("Checking connectivity"), 0);
while (pending.nr) {
result |= traverse_one_object(object_array_pop(&pending));
@@ -255,7 +255,7 @@ static int mark_unreachable_referents(const struct object_id *oid,
/*
* Check a single reachable object
*/
-static void check_reachable_object(struct object *obj)
+static void check_reachable_object(struct repository *repo, struct object *obj)
{
/*
* We obviously want the object to be parsed,
@@ -263,9 +263,9 @@ static void check_reachable_object(struct object *obj)
* do a full fsck
*/
if (!(obj->flags & HAS_OBJ)) {
- if (is_promisor_object(the_repository, &obj->oid))
+ if (is_promisor_object(repo, &obj->oid))
return;
- if (has_object_pack(the_repository, &obj->oid))
+ if (has_object_pack(repo, &obj->oid))
return; /* it is in pack - forget about it */
printf_ln(_("missing %s %s"),
printable_type(&obj->oid, obj->type),
@@ -278,7 +278,7 @@ static void check_reachable_object(struct object *obj)
/*
* Check a single unreachable object
*/
-static void check_unreachable_object(struct object *obj)
+static void check_unreachable_object(struct repository *repo, struct object *obj)
{
/*
* Missing unreachable object? Ignore it. It's not like
@@ -318,19 +318,19 @@ static void check_unreachable_object(struct object *obj)
printable_type(&obj->oid, obj->type),
describe_object(&obj->oid));
if (write_lost_and_found) {
- char *filename = repo_git_path(the_repository, "lost-found/%s/%s",
+ char *filename = repo_git_path(repo, "lost-found/%s/%s",
obj->type == OBJ_COMMIT ? "commit" : "other",
describe_object(&obj->oid));
FILE *f;
- if (safe_create_leading_directories_const(the_repository, filename)) {
+ if (safe_create_leading_directories_const(repo, filename)) {
error(_("could not create lost-found"));
free(filename);
return;
}
f = xfopen(filename, "w");
if (obj->type == OBJ_BLOB) {
- if (odb_stream_blob_to_fd(the_repository->objects, fileno(f),
+ if (odb_stream_blob_to_fd(repo->objects, fileno(f),
&obj->oid, NULL, 1))
die_errno(_("could not write '%s'"), filename);
} else
@@ -350,23 +350,23 @@ static void check_unreachable_object(struct object *obj)
*/
}
-static void check_object(struct object *obj)
+static void check_object(struct repository *repo, struct object *obj)
{
if (verbose)
fprintf_ln(stderr, _("Checking %s"), describe_object(&obj->oid));
if (obj->flags & REACHABLE)
- check_reachable_object(obj);
+ check_reachable_object(repo, obj);
else
- check_unreachable_object(obj);
+ check_unreachable_object(repo, obj);
}
-static void check_connectivity(void)
+static void check_connectivity(struct repository *repo)
{
int i, max;
/* Traverse the pending reachable objects */
- traverse_reachable();
+ traverse_reachable(repo);
/*
* With --connectivity-only, we won't have actually opened and marked
@@ -384,20 +384,20 @@ static void check_connectivity(void)
* and ignore any that weren't present in our earlier
* traversal.
*/
- odb_for_each_object(the_repository->objects, NULL,
+ odb_for_each_object(repo->objects, NULL,
mark_unreachable_referents, NULL, 0);
}
/* Look up all the requirements, warn about missing objects.. */
- max = get_max_object_index(the_repository);
+ max = get_max_object_index(repo);
if (verbose)
fprintf_ln(stderr, _("Checking connectivity (%d objects)"), max);
for (i = 0; i < max; i++) {
- struct object *obj = get_indexed_object(the_repository, i);
+ struct object *obj = get_indexed_object(repo, i);
if (obj)
- check_object(obj);
+ check_object(repo, obj);
}
}
@@ -770,7 +770,7 @@ static int fsck_subdir(unsigned int nr, const char *path UNUSED, void *data)
return 0;
}
-static void fsck_source(struct odb_source *source)
+static void fsck_source(struct repository *repo, struct odb_source *source)
{
struct progress *progress = NULL;
struct for_each_loose_cb cb_data = {
@@ -781,7 +781,7 @@ static void fsck_source(struct odb_source *source)
fprintf_ln(stderr, _("Checking object directory"));
if (show_progress)
- progress = start_progress(the_repository,
+ progress = start_progress(repo,
_("Checking object directories"), 256);
for_each_loose_file_in_source(source, fsck_loose,
@@ -790,7 +790,7 @@ static void fsck_source(struct odb_source *source)
stop_progress(&progress);
}
-static int fsck_cache_tree(struct cache_tree *it, const char *index_path)
+static int fsck_cache_tree(struct repository *repo, struct cache_tree *it, const char *index_path)
{
int i;
int err = 0;
@@ -799,7 +799,7 @@ static int fsck_cache_tree(struct cache_tree *it, const char *index_path)
fprintf_ln(stderr, _("Checking cache tree of %s"), index_path);
if (0 <= it->entry_count) {
- struct object *obj = parse_object(the_repository, &it->oid);
+ struct object *obj = parse_object(repo, &it->oid);
if (!obj) {
error(_("%s: invalid sha1 pointer in cache-tree of %s"),
oid_to_hex(&it->oid), index_path);
@@ -813,7 +813,7 @@ static int fsck_cache_tree(struct cache_tree *it, const char *index_path)
err |= objerror(obj, _("non-tree in cache-tree"));
}
for (i = 0; i < it->subtree_nr; i++)
- err |= fsck_cache_tree(it->down[i]->cache_tree, index_path);
+ err |= fsck_cache_tree(repo, it->down[i]->cache_tree, index_path);
return err;
}
@@ -839,7 +839,7 @@ static int fsck_resolve_undo(struct index_state *istate,
if (!ru->mode[i] || !S_ISREG(ru->mode[i]))
continue;
- obj = parse_object(the_repository, &ru->oid[i]);
+ obj = parse_object(istate->repo, &ru->oid[i]);
if (!obj) {
error(_("%s: invalid sha1 pointer in resolve-undo of %s"),
oid_to_hex(&ru->oid[i]),
@@ -871,7 +871,7 @@ static void fsck_index(struct index_state *istate, const char *index_path,
mode = istate->cache[i]->ce_mode;
if (S_ISGITLINK(mode))
continue;
- blob = lookup_blob(the_repository,
+ blob = lookup_blob(istate->repo,
&istate->cache[i]->oid);
if (!blob)
continue;
@@ -884,7 +884,7 @@ static void fsck_index(struct index_state *istate, const char *index_path,
mark_object_reachable(obj);
}
if (istate->cache_tree)
- fsck_cache_tree(istate->cache_tree, index_path);
+ fsck_cache_tree(istate->repo, istate->cache_tree, index_path);
fsck_resolve_undo(istate, index_path);
}
@@ -907,7 +907,7 @@ static int check_pack_rev_indexes(struct repository *r, int show_progress)
if (show_progress) {
repo_for_each_pack(r, p)
pack_count++;
- progress = start_delayed_progress(the_repository,
+ progress = start_delayed_progress(r,
"Verifying reverse pack-indexes", pack_count);
pack_count = 0;
}
@@ -1027,11 +1027,11 @@ int cmd_fsck(int argc,
if (name_objects)
fsck_enable_object_names(&fsck_walk_options);
- repo_config(the_repository, git_fsck_config, &fsck_obj_options);
- prepare_repo_settings(the_repository);
+ repo_config(repo, git_fsck_config, &fsck_obj_options);
+ prepare_repo_settings(repo);
if (check_references)
- fsck_refs(the_repository);
+ fsck_refs(repo);
/*
* Take a snapshot of the refs before walking objects to avoid looking
@@ -1042,15 +1042,15 @@ int cmd_fsck(int argc,
snapshot_refs(&snap, argc, argv);
/* Ensure we get a "fresh" view of the odb */
- odb_reprepare(the_repository->objects);
+ odb_reprepare(repo->objects);
if (connectivity_only) {
- odb_for_each_object(the_repository->objects, NULL,
+ odb_for_each_object(repo->objects, NULL,
mark_object_for_connectivity, NULL, 0);
} else {
- odb_prepare_alternates(the_repository->objects);
- for (source = the_repository->objects->sources; source; source = source->next)
- fsck_source(source);
+ odb_prepare_alternates(repo->objects);
+ for (source = repo->objects->sources; source; source = source->next)
+ fsck_source(repo, source);
if (check_full) {
struct packed_git *p;
@@ -1058,19 +1058,19 @@ int cmd_fsck(int argc,
struct progress *progress = NULL;
if (show_progress) {
- repo_for_each_pack(the_repository, p) {
+ repo_for_each_pack(repo, p) {
if (open_pack_index(p))
continue;
total += p->num_objects;
}
- progress = start_progress(the_repository,
+ progress = start_progress(repo,
_("Checking objects"), total);
}
- repo_for_each_pack(the_repository, p) {
+ repo_for_each_pack(repo, p) {
/* verify gives error messages itself */
- if (verify_pack(the_repository,
+ if (verify_pack(repo,
p, fsck_obj_buffer,
progress, count))
errors_found |= ERROR_PACK;
@@ -1104,7 +1104,7 @@ int cmd_fsck(int argc,
for (p = worktrees; *p; p++) {
struct worktree *wt = *p;
struct index_state istate =
- INDEX_STATE_INIT(the_repository);
+ INDEX_STATE_INIT(repo);
char *path, *wt_gitdir;
/*
@@ -1125,17 +1125,17 @@ int cmd_fsck(int argc,
free_worktrees(worktrees);
}
- errors_found |= check_pack_rev_indexes(the_repository, show_progress);
- if (verify_bitmap_files(the_repository))
+ errors_found |= check_pack_rev_indexes(repo, show_progress);
+ if (verify_bitmap_files(repo))
errors_found |= ERROR_BITMAP;
- check_connectivity();
+ check_connectivity(repo);
- if (the_repository->settings.core_commit_graph) {
+ if (repo->settings.core_commit_graph) {
struct child_process commit_graph_verify = CHILD_PROCESS_INIT;
- odb_prepare_alternates(the_repository->objects);
- for (source = the_repository->objects->sources; source; source = source->next) {
+ odb_prepare_alternates(repo->objects);
+ for (source = repo->objects->sources; source; source = source->next) {
child_process_init(&commit_graph_verify);
commit_graph_verify.git_cmd = 1;
strvec_pushl(&commit_graph_verify.args, "commit-graph",
@@ -1149,11 +1149,11 @@ int cmd_fsck(int argc,
}
}
- if (the_repository->settings.core_multi_pack_index) {
+ if (repo->settings.core_multi_pack_index) {
struct child_process midx_verify = CHILD_PROCESS_INIT;
- odb_prepare_alternates(the_repository->objects);
- for (source = the_repository->objects->sources; source; source = source->next) {
+ odb_prepare_alternates(repo->objects);
+ for (source = repo->objects->sources; source; source = source->next) {
child_process_init(&midx_verify);
midx_verify.git_cmd = 1;
strvec_pushl(&midx_verify.args, "multi-pack-index",
--
2.53.0.1118.gaef5881109.dirty
^ permalink raw reply related [flat|nested] 33+ messages in thread* [PATCH v2 06/12] builtin/fsck: stop using `the_repository` when snapshotting refs
2026-03-23 15:02 ` [PATCH v2 00/12] fsck: drop use of `the_repository` Patrick Steinhardt
` (4 preceding siblings ...)
2026-03-23 15:02 ` [PATCH v2 05/12] builtin/fsck: fix trivial dependence on `the_repository` Patrick Steinhardt
@ 2026-03-23 15:02 ` Patrick Steinhardt
2026-03-23 15:02 ` [PATCH v2 07/12] builtin/fsck: stop using `the_repository` when checking refs Patrick Steinhardt
` (5 subsequent siblings)
11 siblings, 0 replies; 33+ messages in thread
From: Patrick Steinhardt @ 2026-03-23 15:02 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
We depedn on `the_repository` when snapshotting refs. Refactor this to
use a context-provided repository instead that is injected via the
`struct snapshot_ref_data`.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
builtin/fsck.c | 33 ++++++++++++++++++++++-----------
1 file changed, 22 insertions(+), 11 deletions(-)
diff --git a/builtin/fsck.c b/builtin/fsck.c
index 59680e6daf..edbff16add 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -533,14 +533,20 @@ struct snapshot {
/* TODO: Consider also snapshotting the index of each worktree. */
};
+struct snapshot_ref_data {
+ struct repository *repo;
+ struct snapshot *snap;
+};
+
static int snapshot_ref(const struct reference *ref, void *cb_data)
{
- struct snapshot *snap = cb_data;
+ struct snapshot_ref_data *data = cb_data;
+ struct snapshot *snap = data->snap;
struct object *obj;
- obj = parse_object(the_repository, ref->oid);
+ obj = parse_object(data->repo, ref->oid);
if (!obj) {
- if (is_promisor_object(the_repository, ref->oid)) {
+ if (is_promisor_object(data->repo, ref->oid)) {
/*
* Increment default_refs anyway, because this is a
* valid ref.
@@ -581,11 +587,16 @@ static int fsck_handle_ref(const struct reference *ref, void *cb_data UNUSED)
return 0;
}
-static void snapshot_refs(struct snapshot *snap, int argc, const char **argv)
+static void snapshot_refs(struct repository *repo,
+ struct snapshot *snap, int argc, const char **argv)
{
struct refs_for_each_ref_options opts = {
.flags = REFS_FOR_EACH_INCLUDE_BROKEN,
};
+ struct snapshot_ref_data data = {
+ .repo = repo,
+ .snap = snap,
+ };
struct worktree **worktrees, **p;
const char *head_points_at;
struct object_id head_oid;
@@ -593,13 +604,13 @@ static void snapshot_refs(struct snapshot *snap, int argc, const char **argv)
for (int i = 0; i < argc; i++) {
const char *arg = argv[i];
struct object_id oid;
- if (!repo_get_oid(the_repository, arg, &oid)) {
+ if (!repo_get_oid(repo, arg, &oid)) {
struct reference ref = {
.name = arg,
.oid = &oid,
};
- snapshot_ref(&ref, snap);
+ snapshot_ref(&ref, &data);
continue;
}
error(_("invalid parameter: expected sha1, got '%s'"), arg);
@@ -611,8 +622,8 @@ static void snapshot_refs(struct snapshot *snap, int argc, const char **argv)
return;
}
- refs_for_each_ref_ext(get_main_ref_store(the_repository),
- snapshot_ref, snap, &opts);
+ refs_for_each_ref_ext(get_main_ref_store(repo),
+ snapshot_ref, &data, &opts);
worktrees = get_worktrees();
for (p = worktrees; *p; p++) {
@@ -621,7 +632,7 @@ static void snapshot_refs(struct snapshot *snap, int argc, const char **argv)
strbuf_worktree_ref(wt, &refname, "HEAD");
- head_points_at = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
+ head_points_at = refs_resolve_ref_unsafe(get_main_ref_store(repo),
refname.buf, 0, &head_oid, NULL);
if (head_points_at && !is_null_oid(&head_oid)) {
@@ -630,7 +641,7 @@ static void snapshot_refs(struct snapshot *snap, int argc, const char **argv)
.oid = &head_oid,
};
- snapshot_ref(&ref, snap);
+ snapshot_ref(&ref, &data);
}
strbuf_release(&refname);
@@ -1039,7 +1050,7 @@ int cmd_fsck(int argc,
* objects. We can still walk over new objects that are added during the
* execution of fsck but won't miss any objects that were reachable.
*/
- snapshot_refs(&snap, argc, argv);
+ snapshot_refs(repo, &snap, argc, argv);
/* Ensure we get a "fresh" view of the odb */
odb_reprepare(repo->objects);
--
2.53.0.1118.gaef5881109.dirty
^ permalink raw reply related [flat|nested] 33+ messages in thread* [PATCH v2 07/12] builtin/fsck: stop using `the_repository` when checking refs
2026-03-23 15:02 ` [PATCH v2 00/12] fsck: drop use of `the_repository` Patrick Steinhardt
` (5 preceding siblings ...)
2026-03-23 15:02 ` [PATCH v2 06/12] builtin/fsck: stop using `the_repository` when snapshotting refs Patrick Steinhardt
@ 2026-03-23 15:02 ` Patrick Steinhardt
2026-03-23 15:02 ` [PATCH v2 08/12] builtin/fsck: stop using `the_repository` when checking reflogs Patrick Steinhardt
` (4 subsequent siblings)
11 siblings, 0 replies; 33+ messages in thread
From: Patrick Steinhardt @ 2026-03-23 15:02 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
We implicitly rely on `the_repository` when checking refs. Refactor this
to instead inject the repository via the callback payload.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
builtin/fsck.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/builtin/fsck.c b/builtin/fsck.c
index edbff16add..efc60862ae 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -574,11 +574,12 @@ static int snapshot_ref(const struct reference *ref, void *cb_data)
return 0;
}
-static int fsck_handle_ref(const struct reference *ref, void *cb_data UNUSED)
+static int fsck_handle_ref(const struct reference *ref, void *cb_data)
{
+ struct repository *repo = cb_data;
struct object *obj;
- obj = parse_object(the_repository, ref->oid);
+ obj = parse_object(repo, ref->oid);
obj->flags |= USED;
fsck_put_object_name(&fsck_walk_options,
ref->oid, "%s", ref->name);
@@ -665,7 +666,7 @@ static void free_snapshot_refs(struct snapshot *snap)
free(snap->ref);
}
-static void process_refs(struct snapshot *snap)
+static void process_refs(struct repository *repo, struct snapshot *snap)
{
struct worktree **worktrees, **p;
@@ -674,7 +675,7 @@ static void process_refs(struct snapshot *snap)
.name = snap->ref[i].refname,
.oid = &snap->ref[i].oid,
};
- fsck_handle_ref(&ref, NULL);
+ fsck_handle_ref(&ref, repo);
}
if (include_reflogs) {
@@ -1095,7 +1096,7 @@ int cmd_fsck(int argc,
}
/* Process the snapshotted refs and the reflogs. */
- process_refs(&snap);
+ process_refs(repo, &snap);
/* If not given any explicit objects, process index files too. */
if (!argc)
--
2.53.0.1118.gaef5881109.dirty
^ permalink raw reply related [flat|nested] 33+ messages in thread* [PATCH v2 08/12] builtin/fsck: stop using `the_repository` when checking reflogs
2026-03-23 15:02 ` [PATCH v2 00/12] fsck: drop use of `the_repository` Patrick Steinhardt
` (6 preceding siblings ...)
2026-03-23 15:02 ` [PATCH v2 07/12] builtin/fsck: stop using `the_repository` when checking refs Patrick Steinhardt
@ 2026-03-23 15:02 ` Patrick Steinhardt
2026-03-23 15:03 ` [PATCH v2 09/12] builtin/fsck: stop using `the_repository` with loose objects Patrick Steinhardt
` (3 subsequent siblings)
11 siblings, 0 replies; 33+ messages in thread
From: Patrick Steinhardt @ 2026-03-23 15:02 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
We implicitly rely on `the_repository` when checking reflogs. Refactor
this to instead inject the repository via the callback payload.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
builtin/fsck.c | 24 ++++++++++++++----------
1 file changed, 14 insertions(+), 10 deletions(-)
diff --git a/builtin/fsck.c b/builtin/fsck.c
index efc60862ae..be9dbba2da 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -468,13 +468,14 @@ static int fsck_obj_buffer(const struct object_id *oid, enum object_type type,
static int default_refs;
-static void fsck_handle_reflog_oid(const char *refname, struct object_id *oid,
- timestamp_t timestamp)
+static void fsck_handle_reflog_oid(struct repository *repo,
+ const char *refname, struct object_id *oid,
+ timestamp_t timestamp)
{
struct object *obj;
if (!is_null_oid(oid)) {
- obj = lookup_object(the_repository, oid);
+ obj = lookup_object(repo, oid);
if (obj && (obj->flags & HAS_OBJ)) {
if (timestamp)
fsck_put_object_name(&fsck_walk_options, oid,
@@ -482,7 +483,7 @@ static void fsck_handle_reflog_oid(const char *refname, struct object_id *oid,
refname, timestamp);
obj->flags |= USED;
mark_object_reachable(obj);
- } else if (!is_promisor_object(the_repository, oid)) {
+ } else if (!is_promisor_object(repo, oid)) {
error(_("%s: invalid reflog entry %s"),
refname, oid_to_hex(oid));
errors_found |= ERROR_REACHABLE;
@@ -494,8 +495,10 @@ static int fsck_handle_reflog_ent(const char *refname,
struct object_id *ooid, struct object_id *noid,
const char *email UNUSED,
timestamp_t timestamp, int tz UNUSED,
- const char *message UNUSED, void *cb_data UNUSED)
+ const char *message UNUSED, void *cb_data)
{
+ struct repository *repo = cb_data;
+
if (now && timestamp > now)
return 0;
@@ -503,19 +506,20 @@ static int fsck_handle_reflog_ent(const char *refname,
fprintf_ln(stderr, _("Checking reflog %s->%s"),
oid_to_hex(ooid), oid_to_hex(noid));
- fsck_handle_reflog_oid(refname, ooid, 0);
- fsck_handle_reflog_oid(refname, noid, timestamp);
+ fsck_handle_reflog_oid(repo, refname, ooid, 0);
+ fsck_handle_reflog_oid(repo, refname, noid, timestamp);
return 0;
}
static int fsck_handle_reflog(const char *logname, void *cb_data)
{
struct strbuf refname = STRBUF_INIT;
+ struct worktree *wt = cb_data;
- strbuf_worktree_ref(cb_data, &refname, logname);
- refs_for_each_reflog_ent(get_main_ref_store(the_repository),
+ strbuf_worktree_ref(wt, &refname, logname);
+ refs_for_each_reflog_ent(get_main_ref_store(wt->repo),
refname.buf, fsck_handle_reflog_ent,
- NULL);
+ wt->repo);
strbuf_release(&refname);
return 0;
}
--
2.53.0.1118.gaef5881109.dirty
^ permalink raw reply related [flat|nested] 33+ messages in thread* [PATCH v2 09/12] builtin/fsck: stop using `the_repository` with loose objects
2026-03-23 15:02 ` [PATCH v2 00/12] fsck: drop use of `the_repository` Patrick Steinhardt
` (7 preceding siblings ...)
2026-03-23 15:02 ` [PATCH v2 08/12] builtin/fsck: stop using `the_repository` when checking reflogs Patrick Steinhardt
@ 2026-03-23 15:03 ` Patrick Steinhardt
2026-03-23 15:03 ` [PATCH v2 10/12] builtin/fsck: stop using `the_repository` when checking packed objects Patrick Steinhardt
` (2 subsequent siblings)
11 siblings, 0 replies; 33+ messages in thread
From: Patrick Steinhardt @ 2026-03-23 15:03 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
We depend on `the_repository` when performing consistency checks for
loose objects. Refactor this to use a context-provided repository
instead that is injected via the `struct for_each_loose_cb`.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
builtin/fsck.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/builtin/fsck.c b/builtin/fsck.c
index be9dbba2da..e8bdec7cd0 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -711,27 +711,28 @@ static void process_refs(struct repository *repo, struct snapshot *snap)
}
}
-struct for_each_loose_cb
-{
+struct for_each_loose_cb {
+ struct repository *repo;
struct progress *progress;
};
static int fsck_loose(const struct object_id *oid, const char *path,
- void *data UNUSED)
+ void *cb_data)
{
+ struct for_each_loose_cb *data = cb_data;
struct object *obj;
enum object_type type = OBJ_NONE;
unsigned long size;
void *contents = NULL;
int eaten;
struct object_info oi = OBJECT_INFO_INIT;
- struct object_id real_oid = *null_oid(the_hash_algo);
+ struct object_id real_oid = *null_oid(data->repo->hash_algo);
int err = 0;
oi.sizep = &size;
oi.typep = &type;
- if (read_loose_object(the_repository, path, oid, &real_oid, &contents, &oi) < 0) {
+ if (read_loose_object(data->repo, path, oid, &real_oid, &contents, &oi) < 0) {
if (contents && !oideq(&real_oid, oid))
err = error(_("%s: hash-path mismatch, found at: %s"),
oid_to_hex(&real_oid), path);
@@ -748,7 +749,7 @@ static int fsck_loose(const struct object_id *oid, const char *path,
if (!contents && type != OBJ_BLOB)
BUG("read_loose_object streamed a non-blob");
- obj = parse_object_buffer(the_repository, oid, type, size,
+ obj = parse_object_buffer(data->repo, oid, type, size,
contents, &eaten);
if (!obj) {
@@ -790,6 +791,7 @@ static void fsck_source(struct repository *repo, struct odb_source *source)
{
struct progress *progress = NULL;
struct for_each_loose_cb cb_data = {
+ .repo = source->odb->repo,
.progress = progress,
};
--
2.53.0.1118.gaef5881109.dirty
^ permalink raw reply related [flat|nested] 33+ messages in thread* [PATCH v2 10/12] builtin/fsck: stop using `the_repository` when checking packed objects
2026-03-23 15:02 ` [PATCH v2 00/12] fsck: drop use of `the_repository` Patrick Steinhardt
` (8 preceding siblings ...)
2026-03-23 15:03 ` [PATCH v2 09/12] builtin/fsck: stop using `the_repository` with loose objects Patrick Steinhardt
@ 2026-03-23 15:03 ` Patrick Steinhardt
2026-03-23 15:03 ` [PATCH v2 11/12] builtin/fsck: stop using `the_repository` when marking objects Patrick Steinhardt
2026-03-23 15:03 ` [PATCH v2 12/12] builtin/fsck: stop using `the_repository` in error reporting Patrick Steinhardt
11 siblings, 0 replies; 33+ messages in thread
From: Patrick Steinhardt @ 2026-03-23 15:03 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
We implicitly rely on `the_repository` when checking objects part of a
packfile. These objects are iterated over via `verify_pack()`, which is
provided by the packfile subsystem, and a callback function is then
invoked for each of the objects in that specific pack.
Unfortunately, it is not possible to provide a payload to the callback
function. Refactor `verify_pack()` to accept a payload that is passed
through to the callback so that we can inject the repository and get rid
of the use of `the_repository`.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
builtin/fsck.c | 11 ++++++-----
pack-check.c | 7 ++++---
pack.h | 9 +++++++--
3 files changed, 17 insertions(+), 10 deletions(-)
diff --git a/builtin/fsck.c b/builtin/fsck.c
index e8bdec7cd0..22ca1200a2 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -447,15 +447,16 @@ static int fsck_obj(struct object *obj, void *buffer, unsigned long size)
}
static int fsck_obj_buffer(const struct object_id *oid, enum object_type type,
- unsigned long size, void *buffer, int *eaten)
+ unsigned long size, void *buffer, int *eaten, void *cb_data)
{
+ struct repository *repo = cb_data;
+ struct object *obj;
+
/*
* Note, buffer may be NULL if type is OBJ_BLOB. See
* verify_packfile(), data_valid variable for details.
*/
- struct object *obj;
- obj = parse_object_buffer(the_repository, oid, type, size, buffer,
- eaten);
+ obj = parse_object_buffer(repo, oid, type, size, buffer, eaten);
if (!obj) {
errors_found |= ERROR_OBJECT;
return error(_("%s: object corrupt or missing"),
@@ -1089,7 +1090,7 @@ int cmd_fsck(int argc,
repo_for_each_pack(repo, p) {
/* verify gives error messages itself */
if (verify_pack(repo,
- p, fsck_obj_buffer,
+ p, fsck_obj_buffer, repo,
progress, count))
errors_found |= ERROR_PACK;
count += p->num_objects;
diff --git a/pack-check.c b/pack-check.c
index 7378c80730..79992bb509 100644
--- a/pack-check.c
+++ b/pack-check.c
@@ -53,6 +53,7 @@ static int verify_packfile(struct repository *r,
struct packed_git *p,
struct pack_window **w_curs,
verify_fn fn,
+ void *fn_data,
struct progress *progress, uint32_t base_count)
{
@@ -161,7 +162,7 @@ static int verify_packfile(struct repository *r,
oid_to_hex(&oid), p->pack_name);
else if (fn) {
int eaten = 0;
- err |= fn(&oid, type, size, data, &eaten);
+ err |= fn(&oid, type, size, data, &eaten, fn_data);
if (eaten)
data = NULL;
}
@@ -192,7 +193,7 @@ int verify_pack_index(struct packed_git *p)
return err;
}
-int verify_pack(struct repository *r, struct packed_git *p, verify_fn fn,
+int verify_pack(struct repository *r, struct packed_git *p, verify_fn fn, void *fn_data,
struct progress *progress, uint32_t base_count)
{
int err = 0;
@@ -202,7 +203,7 @@ int verify_pack(struct repository *r, struct packed_git *p, verify_fn fn,
if (!p->index_data)
return -1;
- err |= verify_packfile(r, p, &w_curs, fn, progress, base_count);
+ err |= verify_packfile(r, p, &w_curs, fn, fn_data, progress, base_count);
unuse_pack(&w_curs);
return err;
diff --git a/pack.h b/pack.h
index ec76472e49..1cde92082b 100644
--- a/pack.h
+++ b/pack.h
@@ -85,7 +85,11 @@ struct pack_idx_entry {
struct progress;
/* Note, the data argument could be NULL if object type is blob */
-typedef int (*verify_fn)(const struct object_id *, enum object_type, unsigned long, void*, int*);
+typedef int (*verify_fn)(const struct object_id *oid,
+ enum object_type type,
+ unsigned long size,
+ void *buffer, int *eaten,
+ void *fn_data);
const char *write_idx_file(struct repository *repo,
const char *index_name,
@@ -95,7 +99,8 @@ const char *write_idx_file(struct repository *repo,
const unsigned char *sha1);
int check_pack_crc(struct packed_git *p, struct pack_window **w_curs, off_t offset, off_t len, unsigned int nr);
int verify_pack_index(struct packed_git *);
-int verify_pack(struct repository *, struct packed_git *, verify_fn fn, struct progress *, uint32_t);
+int verify_pack(struct repository *, struct packed_git *, verify_fn fn, void *fn_data,
+ struct progress *, uint32_t);
off_t write_pack_header(struct hashfile *f, uint32_t);
void fixup_pack_header_footer(const struct git_hash_algo *, int,
unsigned char *, const char *, uint32_t,
--
2.53.0.1118.gaef5881109.dirty
^ permalink raw reply related [flat|nested] 33+ messages in thread* [PATCH v2 11/12] builtin/fsck: stop using `the_repository` when marking objects
2026-03-23 15:02 ` [PATCH v2 00/12] fsck: drop use of `the_repository` Patrick Steinhardt
` (9 preceding siblings ...)
2026-03-23 15:03 ` [PATCH v2 10/12] builtin/fsck: stop using `the_repository` when checking packed objects Patrick Steinhardt
@ 2026-03-23 15:03 ` Patrick Steinhardt
2026-03-23 15:03 ` [PATCH v2 12/12] builtin/fsck: stop using `the_repository` in error reporting Patrick Steinhardt
11 siblings, 0 replies; 33+ messages in thread
From: Patrick Steinhardt @ 2026-03-23 15:03 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
We implicitly rely on `the_repository` when marking objects for
connectivity. Refactor this to instead inject the repository via the
callback payload.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
builtin/fsck.c | 26 ++++++++++++++------------
1 file changed, 14 insertions(+), 12 deletions(-)
diff --git a/builtin/fsck.c b/builtin/fsck.c
index 22ca1200a2..e37f708480 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -124,7 +124,7 @@ static int fsck_objects_error_func(struct fsck_options *o UNUSED,
static struct object_array pending;
static int mark_object(struct object *obj, enum object_type type,
- void *data, struct fsck_options *options UNUSED)
+ void *data, struct fsck_options *options)
{
struct object *parent = data;
@@ -153,7 +153,7 @@ static int mark_object(struct object *obj, enum object_type type,
return 0;
obj->flags |= REACHABLE;
- if (is_promisor_object(the_repository, &obj->oid))
+ if (is_promisor_object(options->repo, &obj->oid))
/*
* Further recursion does not need to be performed on this
* object since it is a promisor object (so it does not need to
@@ -162,7 +162,7 @@ static int mark_object(struct object *obj, enum object_type type,
return 0;
if (!(obj->flags & HAS_OBJ)) {
- if (parent && !odb_has_object(the_repository->objects, &obj->oid,
+ if (parent && !odb_has_object(options->repo->objects, &obj->oid,
HAS_OBJECT_RECHECK_PACKED)) {
printf_ln(_("broken link from %7s %s\n"
" to %7s %s"),
@@ -181,7 +181,7 @@ static int mark_object(struct object *obj, enum object_type type,
static void mark_object_reachable(struct object *obj)
{
- mark_object(obj, OBJ_ANY, NULL, NULL);
+ mark_object(obj, OBJ_ANY, NULL, &fsck_walk_options);
}
static int traverse_one_object(struct object *obj)
@@ -222,10 +222,11 @@ static int mark_used(struct object *obj, enum object_type type UNUSED,
static int mark_unreachable_referents(const struct object_id *oid,
struct object_info *oi UNUSED,
- void *data UNUSED)
+ void *data)
{
+ struct repository *repo = data;
struct fsck_options options;
- struct object *obj = lookup_object(the_repository, oid);
+ struct object *obj = lookup_object(data, oid);
if (!obj || !(obj->flags & HAS_OBJ))
return 0; /* not part of our original set */
@@ -237,13 +238,13 @@ static int mark_unreachable_referents(const struct object_id *oid,
* (and we want to avoid parsing blobs).
*/
if (obj->type == OBJ_NONE) {
- enum object_type type = odb_read_object_info(the_repository->objects,
+ enum object_type type = odb_read_object_info(repo->objects,
&obj->oid, NULL);
if (type > 0)
object_as_type(obj, type, 0);
}
- fsck_options_init(&options, the_repository, FSCK_OPTIONS_DEFAULT);
+ fsck_options_init(&options, repo, FSCK_OPTIONS_DEFAULT);
options.walk = mark_used;
fsck_walk(obj, NULL, &options);
if (obj->type == OBJ_TREE)
@@ -385,7 +386,7 @@ static void check_connectivity(struct repository *repo)
* traversal.
*/
odb_for_each_object(repo->objects, NULL,
- mark_unreachable_referents, NULL, 0);
+ mark_unreachable_referents, repo, 0);
}
/* Look up all the requirements, warn about missing objects.. */
@@ -909,9 +910,10 @@ static void fsck_index(struct index_state *istate, const char *index_path,
static int mark_object_for_connectivity(const struct object_id *oid,
struct object_info *oi UNUSED,
- void *cb_data UNUSED)
+ void *cb_data)
{
- struct object *obj = lookup_unknown_object(the_repository, oid);
+ struct repository *repo = cb_data;
+ struct object *obj = lookup_unknown_object(repo, oid);
obj->flags |= HAS_OBJ;
return 0;
}
@@ -1065,7 +1067,7 @@ int cmd_fsck(int argc,
if (connectivity_only) {
odb_for_each_object(repo->objects, NULL,
- mark_object_for_connectivity, NULL, 0);
+ mark_object_for_connectivity, repo, 0);
} else {
odb_prepare_alternates(repo->objects);
for (source = repo->objects->sources; source; source = source->next)
--
2.53.0.1118.gaef5881109.dirty
^ permalink raw reply related [flat|nested] 33+ messages in thread* [PATCH v2 12/12] builtin/fsck: stop using `the_repository` in error reporting
2026-03-23 15:02 ` [PATCH v2 00/12] fsck: drop use of `the_repository` Patrick Steinhardt
` (10 preceding siblings ...)
2026-03-23 15:03 ` [PATCH v2 11/12] builtin/fsck: stop using `the_repository` when marking objects Patrick Steinhardt
@ 2026-03-23 15:03 ` Patrick Steinhardt
11 siblings, 0 replies; 33+ messages in thread
From: Patrick Steinhardt @ 2026-03-23 15:03 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
In the preceding commit we have introduced the repository into `struct
fsck_object_report`. This allows us to drop remaining uses of the global
`the_repository` variable.
Drop them and remove `USE_THE_REPOSITORY_VARIABLE`.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
builtin/fsck.c | 46 +++++++++++++++++++++++-----------------------
1 file changed, 23 insertions(+), 23 deletions(-)
diff --git a/builtin/fsck.c b/builtin/fsck.c
index e37f708480..99696604b8 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -1,4 +1,3 @@
-#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "gettext.h"
#include "hex.h"
@@ -66,14 +65,14 @@ static const char *describe_object(const struct object_id *oid)
return fsck_describe_object(&fsck_walk_options, oid);
}
-static const char *printable_type(const struct object_id *oid,
+static const char *printable_type(struct repository *repo,
+ const struct object_id *oid,
enum object_type type)
{
const char *ret;
if (type == OBJ_NONE)
- type = odb_read_object_info(the_repository->objects,
- oid, NULL);
+ type = odb_read_object_info(repo->objects, oid, NULL);
ret = type_name(type);
if (!ret)
@@ -82,17 +81,17 @@ static const char *printable_type(const struct object_id *oid,
return ret;
}
-static int objerror(struct object *obj, const char *err)
+static int objerror(struct repository *repo, struct object *obj, const char *err)
{
errors_found |= ERROR_OBJECT;
/* TRANSLATORS: e.g. error in tree 01bfda: <more explanation> */
fprintf_ln(stderr, _("error in %s %s: %s"),
- printable_type(&obj->oid, obj->type),
+ printable_type(repo, &obj->oid, obj->type),
describe_object(&obj->oid), err);
return -1;
}
-static int fsck_objects_error_func(struct fsck_options *o UNUSED,
+static int fsck_objects_error_func(struct fsck_options *o,
void *fsck_report,
enum fsck_msg_type msg_type,
enum fsck_msg_id msg_id UNUSED,
@@ -106,13 +105,13 @@ static int fsck_objects_error_func(struct fsck_options *o UNUSED,
case FSCK_WARN:
/* TRANSLATORS: e.g. warning in tree 01bfda: <more explanation> */
fprintf_ln(stderr, _("warning in %s %s: %s"),
- printable_type(oid, object_type),
+ printable_type(o->repo, oid, object_type),
describe_object(oid), message);
return 0;
case FSCK_ERROR:
/* TRANSLATORS: e.g. error in tree 01bfda: <more explanation> */
fprintf_ln(stderr, _("error in %s %s: %s"),
- printable_type(oid, object_type),
+ printable_type(o->repo, oid, object_type),
describe_object(oid), message);
return 1;
default:
@@ -136,7 +135,7 @@ static int mark_object(struct object *obj, enum object_type type,
if (!obj) {
/* ... these references to parent->fld are safe here */
printf_ln(_("broken link from %7s %s"),
- printable_type(&parent->oid, parent->type),
+ printable_type(options->repo, &parent->oid, parent->type),
describe_object(&parent->oid));
printf_ln(_("broken link from %7s %s"),
(type == OBJ_ANY ? _("unknown") : type_name(type)),
@@ -147,7 +146,7 @@ static int mark_object(struct object *obj, enum object_type type,
if (type != OBJ_ANY && obj->type != type)
/* ... and the reference to parent is safe here */
- objerror(parent, _("wrong object type in link"));
+ objerror(options->repo, parent, _("wrong object type in link"));
if (obj->flags & REACHABLE)
return 0;
@@ -166,9 +165,9 @@ static int mark_object(struct object *obj, enum object_type type,
HAS_OBJECT_RECHECK_PACKED)) {
printf_ln(_("broken link from %7s %s\n"
" to %7s %s"),
- printable_type(&parent->oid, parent->type),
+ printable_type(options->repo, &parent->oid, parent->type),
describe_object(&parent->oid),
- printable_type(&obj->oid, obj->type),
+ printable_type(options->repo, &obj->oid, obj->type),
describe_object(&obj->oid));
errors_found |= ERROR_REACHABLE;
}
@@ -269,7 +268,7 @@ static void check_reachable_object(struct repository *repo, struct object *obj)
if (has_object_pack(repo, &obj->oid))
return; /* it is in pack - forget about it */
printf_ln(_("missing %s %s"),
- printable_type(&obj->oid, obj->type),
+ printable_type(repo, &obj->oid, obj->type),
describe_object(&obj->oid));
errors_found |= ERROR_REACHABLE;
return;
@@ -296,7 +295,7 @@ static void check_unreachable_object(struct repository *repo, struct object *obj
*/
if (show_unreachable) {
printf_ln(_("unreachable %s %s"),
- printable_type(&obj->oid, obj->type),
+ printable_type(repo, &obj->oid, obj->type),
describe_object(&obj->oid));
return;
}
@@ -316,7 +315,7 @@ static void check_unreachable_object(struct repository *repo, struct object *obj
if (!(obj->flags & USED)) {
if (show_dangling)
printf_ln(_("dangling %s %s"),
- printable_type(&obj->oid, obj->type),
+ printable_type(repo, &obj->oid, obj->type),
describe_object(&obj->oid));
if (write_lost_and_found) {
char *filename = repo_git_path(repo, "lost-found/%s/%s",
@@ -402,7 +401,8 @@ static void check_connectivity(struct repository *repo)
}
}
-static int fsck_obj(struct object *obj, void *buffer, unsigned long size)
+static int fsck_obj(struct repository *repo,
+ struct object *obj, void *buffer, unsigned long size)
{
int err;
@@ -412,11 +412,11 @@ static int fsck_obj(struct object *obj, void *buffer, unsigned long size)
if (verbose)
fprintf_ln(stderr, _("Checking %s %s"),
- printable_type(&obj->oid, obj->type),
+ printable_type(repo, &obj->oid, obj->type),
describe_object(&obj->oid));
if (fsck_walk(obj, NULL, &fsck_obj_options))
- objerror(obj, _("broken links"));
+ objerror(repo, obj, _("broken links"));
err = fsck_object(obj, buffer, size, &fsck_obj_options);
if (err)
goto out;
@@ -434,7 +434,7 @@ static int fsck_obj(struct object *obj, void *buffer, unsigned long size)
if (show_tags && tag->tagged) {
printf_ln(_("tagged %s %s (%s) in %s"),
- printable_type(&tag->tagged->oid, tag->tagged->type),
+ printable_type(repo, &tag->tagged->oid, tag->tagged->type),
describe_object(&tag->tagged->oid),
tag->tag,
describe_object(&tag->object.oid));
@@ -465,7 +465,7 @@ static int fsck_obj_buffer(const struct object_id *oid, enum object_type type,
}
obj->flags &= ~(REACHABLE | SEEN);
obj->flags |= HAS_OBJ;
- return fsck_obj(obj, buffer, size);
+ return fsck_obj(repo, obj, buffer, size);
}
static int default_refs;
@@ -765,7 +765,7 @@ static int fsck_loose(const struct object_id *oid, const char *path,
obj->flags &= ~(REACHABLE | SEEN);
obj->flags |= HAS_OBJ;
- if (fsck_obj(obj, contents, size))
+ if (fsck_obj(data->repo, obj, contents, size))
errors_found |= ERROR_OBJECT;
if (!eaten)
@@ -830,7 +830,7 @@ static int fsck_cache_tree(struct repository *repo, struct cache_tree *it, const
fsck_put_object_name(&fsck_walk_options, &it->oid, ":");
mark_object_reachable(obj);
if (obj->type != OBJ_TREE)
- err |= objerror(obj, _("non-tree in cache-tree"));
+ err |= objerror(repo, obj, _("non-tree in cache-tree"));
}
for (i = 0; i < it->subtree_nr; i++)
err |= fsck_cache_tree(repo, it->down[i]->cache_tree, index_path);
--
2.53.0.1118.gaef5881109.dirty
^ permalink raw reply related [flat|nested] 33+ messages in thread