diff mbox series

[2/3] fsck: check index files in all worktrees

Message ID Y/hw1YVgCYWX2yNK@coredump.intra.peff.net (mailing list archive)
State New, archived
Headers show
Series fsck index files from all worktrees | expand

Commit Message

Jeff King Feb. 24, 2023, 8:09 a.m. UTC
We check the index file for the main worktree, but completely ignore the
index files in other worktrees. These should be checked, too, as they
are part of the repository state (and in particular, errors in those
index files may cause repo-wide operations like "git gc" to complain).

Reported-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Jeff King <peff@peff.net>
---
I mostly cargo-culted the loop from add_index_objects_to_pending(),
which is how they get included in git-prune, git-repack, etc.

I'm not sure if we should be reporting something if we get a negative
return. Last time I dug into this, I think I found that the
index-reading code could not actually return an error (it dies instead).

If we get zero, there are no entries to check. But I'm not sure if we'd
still have extensions? So maybe this ought to be ignoring the return
value from read_index_from() entirely.

 builtin/fsck.c  | 17 +++++++++++++++--
 t/t1450-fsck.sh | 12 ++++++++++++
 2 files changed, 27 insertions(+), 2 deletions(-)

Comments

Jeff King Feb. 24, 2023, 8:45 a.m. UTC | #1
On Fri, Feb 24, 2023 at 03:09:58AM -0500, Jeff King wrote:

> +		for (p = get_worktrees(); *p; p++) {
> +			struct worktree *wt = *p;
> +			struct index_state istate =
> +				INDEX_STATE_INIT(the_repository);
> +
> +			if (read_index_from(&istate,
> +					    worktree_git_path(wt, "index"),
> +					    get_worktree_git_dir(wt)) > 0)
> +				fsck_index(&istate);
> +			discard_index(&istate);
> +		}

I didn't realize that get_worktrees() returns an allocated array, so
this is a small leak. I'll squash this in locally:

diff --git a/builtin/fsck.c b/builtin/fsck.c
index ddd13cb2b3..c11cb2a95f 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -984,12 +984,13 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
 	}
 
 	if (keep_cache_objects) {
-		struct worktree **p;
+		struct worktree **worktrees, **p;
 
 		verify_index_checksum = 1;
 		verify_ce_order = 1;
 
-		for (p = get_worktrees(); *p; p++) {
+		worktrees = get_worktrees();
+		for (p = worktrees; *p; p++) {
 			struct worktree *wt = *p;
 			struct index_state istate =
 				INDEX_STATE_INIT(the_repository);
@@ -1000,7 +1001,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
 				fsck_index(&istate);
 			discard_index(&istate);
 		}
-
+		free_worktrees(worktrees);
 	}
 
 	check_connectivity();

but I'll hold off for other comments before sending a re-roll.

-Peff
diff mbox series

Patch

diff --git a/builtin/fsck.c b/builtin/fsck.c
index fa101e0db2..ddd13cb2b3 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -984,10 +984,23 @@  int cmd_fsck(int argc, const char **argv, const char *prefix)
 	}
 
 	if (keep_cache_objects) {
+		struct worktree **p;
+
 		verify_index_checksum = 1;
 		verify_ce_order = 1;
-		repo_read_index(the_repository);
-		fsck_index(the_repository->index);
+
+		for (p = get_worktrees(); *p; p++) {
+			struct worktree *wt = *p;
+			struct index_state istate =
+				INDEX_STATE_INIT(the_repository);
+
+			if (read_index_from(&istate,
+					    worktree_git_path(wt, "index"),
+					    get_worktree_git_dir(wt)) > 0)
+				fsck_index(&istate);
+			discard_index(&istate);
+		}
+
 	}
 
 	check_connectivity();
diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh
index fdb886dfe4..3b70ad9e22 100755
--- a/t/t1450-fsck.sh
+++ b/t/t1450-fsck.sh
@@ -1023,4 +1023,16 @@  test_expect_success 'fsck error on gitattributes with excessive size' '
 	test_cmp expected actual
 '
 
+test_expect_success 'fsck detects problems in worktree index' '
+	test_when_finished "git worktree remove -f wt" &&
+	git worktree add wt &&
+
+	echo "this will be removed to break the worktree index" >wt/file &&
+	git -C wt add file &&
+	blob=$(git -C wt rev-parse :file) &&
+	remove_object $blob &&
+
+	test_must_fail git fsck
+'
+
 test_done