Skip to content

Commit 2d019f4

Browse files
committed
Merge branch 'jk/fsck-indices-in-worktrees'
"git fsck" learned to check the index files in other worktrees, just like "git gc" honors them as anchoring points. * jk/fsck-indices-in-worktrees: fsck: check even zero-entry index files fsck: mention file path for index errors fsck: check index files in all worktrees fsck: factor out index fsck
2 parents 73876f4 + 8d3e7ea commit 2d019f4

File tree

2 files changed

+92
-31
lines changed

2 files changed

+92
-31
lines changed

builtin/fsck.c

Lines changed: 62 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
#define USE_THE_INDEX_VARIABLE
21
#include "builtin.h"
32
#include "cache.h"
43
#include "repository.h"
@@ -732,19 +731,19 @@ static int fsck_head_link(const char *head_ref_name,
732731
return 0;
733732
}
734733

735-
static int fsck_cache_tree(struct cache_tree *it)
734+
static int fsck_cache_tree(struct cache_tree *it, const char *index_path)
736735
{
737736
int i;
738737
int err = 0;
739738

740739
if (verbose)
741-
fprintf_ln(stderr, _("Checking cache tree"));
740+
fprintf_ln(stderr, _("Checking cache tree of %s"), index_path);
742741

743742
if (0 <= it->entry_count) {
744743
struct object *obj = parse_object(the_repository, &it->oid);
745744
if (!obj) {
746-
error(_("%s: invalid sha1 pointer in cache-tree"),
747-
oid_to_hex(&it->oid));
745+
error(_("%s: invalid sha1 pointer in cache-tree of %s"),
746+
oid_to_hex(&it->oid), index_path);
748747
errors_found |= ERROR_REFS;
749748
return 1;
750749
}
@@ -755,11 +754,12 @@ static int fsck_cache_tree(struct cache_tree *it)
755754
err |= objerror(obj, _("non-tree in cache-tree"));
756755
}
757756
for (i = 0; i < it->subtree_nr; i++)
758-
err |= fsck_cache_tree(it->down[i]->cache_tree);
757+
err |= fsck_cache_tree(it->down[i]->cache_tree, index_path);
759758
return err;
760759
}
761760

762-
static int fsck_resolve_undo(struct index_state *istate)
761+
static int fsck_resolve_undo(struct index_state *istate,
762+
const char *index_path)
763763
{
764764
struct string_list_item *item;
765765
struct string_list *resolve_undo = istate->resolve_undo;
@@ -782,8 +782,9 @@ static int fsck_resolve_undo(struct index_state *istate)
782782

783783
obj = parse_object(the_repository, &ru->oid[i]);
784784
if (!obj) {
785-
error(_("%s: invalid sha1 pointer in resolve-undo"),
786-
oid_to_hex(&ru->oid[i]));
785+
error(_("%s: invalid sha1 pointer in resolve-undo of %s"),
786+
oid_to_hex(&ru->oid[i]),
787+
index_path);
787788
errors_found |= ERROR_REFS;
788789
continue;
789790
}
@@ -796,6 +797,38 @@ static int fsck_resolve_undo(struct index_state *istate)
796797
return 0;
797798
}
798799

800+
static void fsck_index(struct index_state *istate, const char *index_path,
801+
int is_main_index)
802+
{
803+
unsigned int i;
804+
805+
/* TODO: audit for interaction with sparse-index. */
806+
ensure_full_index(istate);
807+
for (i = 0; i < istate->cache_nr; i++) {
808+
unsigned int mode;
809+
struct blob *blob;
810+
struct object *obj;
811+
812+
mode = istate->cache[i]->ce_mode;
813+
if (S_ISGITLINK(mode))
814+
continue;
815+
blob = lookup_blob(the_repository,
816+
&istate->cache[i]->oid);
817+
if (!blob)
818+
continue;
819+
obj = &blob->object;
820+
obj->flags |= USED;
821+
fsck_put_object_name(&fsck_walk_options, &obj->oid,
822+
"%s:%s",
823+
is_main_index ? "" : index_path,
824+
istate->cache[i]->name);
825+
mark_object_reachable(obj);
826+
}
827+
if (istate->cache_tree)
828+
fsck_cache_tree(istate->cache_tree, index_path);
829+
fsck_resolve_undo(istate, index_path);
830+
}
831+
799832
static void mark_object_for_connectivity(const struct object_id *oid)
800833
{
801834
struct object *obj = lookup_unknown_object(the_repository, oid);
@@ -956,32 +989,30 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
956989
}
957990

958991
if (keep_cache_objects) {
992+
struct worktree **worktrees, **p;
993+
959994
verify_index_checksum = 1;
960995
verify_ce_order = 1;
961-
repo_read_index(the_repository);
962-
/* TODO: audit for interaction with sparse-index. */
963-
ensure_full_index(&the_index);
964-
for (i = 0; i < the_index.cache_nr; i++) {
965-
unsigned int mode;
966-
struct blob *blob;
967-
struct object *obj;
968996

969-
mode = the_index.cache[i]->ce_mode;
970-
if (S_ISGITLINK(mode))
971-
continue;
972-
blob = lookup_blob(the_repository,
973-
&the_index.cache[i]->oid);
974-
if (!blob)
975-
continue;
976-
obj = &blob->object;
977-
obj->flags |= USED;
978-
fsck_put_object_name(&fsck_walk_options, &obj->oid,
979-
":%s", the_index.cache[i]->name);
980-
mark_object_reachable(obj);
997+
worktrees = get_worktrees();
998+
for (p = worktrees; *p; p++) {
999+
struct worktree *wt = *p;
1000+
struct index_state istate =
1001+
INDEX_STATE_INIT(the_repository);
1002+
char *path;
1003+
1004+
/*
1005+
* Make a copy since the buffer is reusable
1006+
* and may get overwritten by other calls
1007+
* while we're examining the index.
1008+
*/
1009+
path = xstrdup(worktree_git_path(wt, "index"));
1010+
read_index_from(&istate, path, get_worktree_git_dir(wt));
1011+
fsck_index(&istate, path, wt->is_current);
1012+
discard_index(&istate);
1013+
free(path);
9811014
}
982-
if (the_index.cache_tree)
983-
fsck_cache_tree(the_index.cache_tree);
984-
fsck_resolve_undo(&the_index);
1015+
free_worktrees(worktrees);
9851016
}
9861017

9871018
check_connectivity();

t/t1450-fsck.sh

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,4 +1023,34 @@ test_expect_success 'fsck error on gitattributes with excessive size' '
10231023
test_cmp expected actual
10241024
'
10251025

1026+
test_expect_success 'fsck detects problems in worktree index' '
1027+
test_when_finished "git worktree remove -f wt" &&
1028+
git worktree add wt &&
1029+
1030+
echo "this will be removed to break the worktree index" >wt/file &&
1031+
git -C wt add file &&
1032+
blob=$(git -C wt rev-parse :file) &&
1033+
remove_object $blob &&
1034+
1035+
test_must_fail git fsck --name-objects >actual 2>&1 &&
1036+
cat >expect <<-EOF &&
1037+
missing blob $blob (.git/worktrees/wt/index:file)
1038+
EOF
1039+
test_cmp expect actual
1040+
'
1041+
1042+
test_expect_success 'fsck reports problems in main index without filename' '
1043+
test_when_finished "rm -f .git/index && git read-tree HEAD" &&
1044+
echo "this object will be removed to break the main index" >file &&
1045+
git add file &&
1046+
blob=$(git rev-parse :file) &&
1047+
remove_object $blob &&
1048+
1049+
test_must_fail git fsck --name-objects >actual 2>&1 &&
1050+
cat >expect <<-EOF &&
1051+
missing blob $blob (:file)
1052+
EOF
1053+
test_cmp expect actual
1054+
'
1055+
10261056
test_done

0 commit comments

Comments
 (0)