]> git.ipfire.org Git - thirdparty/git.git/commitdiff
builtin/refs: get worktrees without reading head information
authorshejialuo <shejialuo@gmail.com>
Thu, 27 Feb 2025 16:06:06 +0000 (00:06 +0800)
committerJunio C Hamano <gitster@pobox.com>
Thu, 27 Feb 2025 22:03:07 +0000 (14:03 -0800)
In "packed-backend.c", there are some functions such as "create_snapshot"
and "next_record" which would check the correctness of the content of
the "packed-ref" file. When anything is bad, the program will die.

It may seem that we have nothing relevant to above feature, because we
are going to read and parse the raw "packed-ref" file without creating
the snapshot and using the ref iterator to check the consistency.

However, when using "get_worktrees" in "builtin/refs", we would parse
the "HEAD" information. If the referent of the "HEAD" is inside the
"packed-ref", we will call "create_snapshot" function to parse the
"packed-ref" to get the information. No matter whether the entry of
"HEAD" in "packed-ref" is correct, "create_snapshot" would call
"verify_buffer_safe" to check whether there is a newline in the last
line of the file. If not, the program will die.

Although this behavior has no harm for the program, it will
short-circuit the program. When the users execute "git refs verify" or
"git fsck", we should avoid reading the head information, which may
execute the read operation in packed backend with stricter checks to die
the program. Instead, we should continue to check other parts of the
"packed-refs" file completely.

Fortunately, in 465a22b338 (worktree: skip reading HEAD when repairing
worktrees, 2023-12-29), we have introduced a function
"get_worktrees_internal" which allows us to get worktrees without
reading head information.

Create a new exposed function "get_worktrees_without_reading_head", then
replace the "get_worktrees" in "builtin/refs" with the new created
function.

Mentored-by: Patrick Steinhardt <ps@pks.im>
Mentored-by: Karthik Nayak <karthik.188@gmail.com>
Signed-off-by: shejialuo <shejialuo@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/refs.c
worktree.c
worktree.h

index a29f19583474518ee0942ea53c39cbdf9661c5e2..55ff5dae11bba6ab553d9d3f087df5b840b8da03 100644 (file)
@@ -88,7 +88,7 @@ static int cmd_refs_verify(int argc, const char **argv, const char *prefix,
        git_config(git_fsck_config, &fsck_refs_options);
        prepare_repo_settings(the_repository);
 
-       worktrees = get_worktrees();
+       worktrees = get_worktrees_without_reading_head();
        for (size_t i = 0; worktrees[i]; i++)
                ret |= refs_fsck(get_worktree_ref_store(worktrees[i]),
                                 &fsck_refs_options, worktrees[i]);
index 248bbb39d43ae82ad843d4a00632cc2722454ea5..89b7d86cef1af13c23e21625d47385eaafb8d20a 100644 (file)
@@ -175,6 +175,11 @@ struct worktree **get_worktrees(void)
        return get_worktrees_internal(0);
 }
 
+struct worktree **get_worktrees_without_reading_head(void)
+{
+       return get_worktrees_internal(1);
+}
+
 const char *get_worktree_git_dir(const struct worktree *wt)
 {
        if (!wt)
index 38145df80f41079f301d3aeaaffcc35b7f6760b9..a305c7e2c7282a77bfdd16c451784e31ed3f5682 100644 (file)
@@ -30,6 +30,14 @@ struct worktree {
  */
 struct worktree **get_worktrees(void);
 
+/*
+ * Like `get_worktrees`, but does not read HEAD. Skip reading HEAD allows to
+ * get the worktree without worrying about failures pertaining to parsing
+ * the HEAD ref. This is useful in contexts where it is assumed that the
+ * refdb may not be in a consistent state.
+ */
+struct worktree **get_worktrees_without_reading_head(void);
+
 /*
  * Returns 1 if linked worktrees exist, 0 otherwise.
  */