Skip to content

Commit c72b19b

Browse files
committed
Merge branch 'sj/ref-consistency-checks-more' into seen
"git fsck" becomes more careful when checking the refs. * sj/ref-consistency-checks-more: builtin/fsck: add `git refs verify` child process packed-backend: check whether the "packed-refs" is sorted packed-backend: add check for object consistency packed-backend: create "fsck_packed_ref_entry" to store parsing info packed-backend: add "packed-refs" entry consistency check packed-backend: check whether the refname contains NULL binaries packed-backend: add "packed-refs" header consistency check packed-backend: check whether the "packed-refs" is regular builtin/refs.h: get worktrees without reading head info files-backend: add object check for regular ref
2 parents 9ee62e3 + 35866d5 commit c72b19b

File tree

9 files changed

+724
-24
lines changed

9 files changed

+724
-24
lines changed

Documentation/fsck-msgids.adoc

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@
1616
`badObjectSha1`::
1717
(ERROR) An object has a bad sha1.
1818

19+
`badPackedRefEntry`::
20+
(ERROR) The "packed-refs" file contains an invalid entry.
21+
22+
`badPackedRefHeader`::
23+
(ERROR) The "packed-refs" file contains an invalid
24+
header.
25+
1926
`badParentSha1`::
2027
(ERROR) A commit object has a bad parent sha1.
2128

@@ -176,6 +183,16 @@
176183
`nullSha1`::
177184
(WARN) Tree contains entries pointing to a null sha1.
178185

186+
`packedRefEntryNotTerminated`::
187+
(ERROR) The "packed-refs" file contains an entry that is
188+
not terminated by a newline.
189+
190+
`packedRefMissingHeader`::
191+
(INFO) The "packed-refs" file does not contain the header.
192+
193+
`packedRefUnsorted`::
194+
(ERROR) The "packed-refs" file is not sorted.
195+
179196
`refMissingNewline`::
180197
(INFO) A loose ref that does not end with newline(LF). As
181198
valid implementations of Git never created such a loose ref
@@ -208,6 +225,11 @@
208225
`treeNotSorted`::
209226
(ERROR) A tree is not properly sorted.
210227

228+
`unknownPackedRefHeader`::
229+
(INFO) The "packed-refs" header starts with "# pack-refs with:"
230+
but the remaining content is not the same as what `git pack-refs`
231+
would write.
232+
211233
`unknownType`::
212234
(ERROR) Found an unknown object type.
213235

builtin/fsck.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -905,6 +905,33 @@ static int check_pack_rev_indexes(struct repository *r, int show_progress)
905905
return res;
906906
}
907907

908+
static void fsck_refs(void)
909+
{
910+
struct child_process refs_verify = CHILD_PROCESS_INIT;
911+
struct progress *progress = NULL;
912+
913+
if (show_progress)
914+
progress = start_progress(the_repository,
915+
_("Checking ref database"), 1);
916+
917+
if (verbose)
918+
fprintf_ln(stderr, _("Checking ref database"));
919+
920+
child_process_init(&refs_verify);
921+
refs_verify.git_cmd = 1;
922+
strvec_pushl(&refs_verify.args, "refs", "verify", NULL);
923+
if (verbose)
924+
strvec_push(&refs_verify.args, "--verbose");
925+
if (check_strict)
926+
strvec_push(&refs_verify.args, "--strict");
927+
928+
if (run_command(&refs_verify))
929+
errors_found |= ERROR_REFS;
930+
931+
display_progress(progress, 1);
932+
stop_progress(&progress);
933+
}
934+
908935
static char const * const fsck_usage[] = {
909936
N_("git fsck [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]\n"
910937
" [--[no-]full] [--strict] [--verbose] [--lost-found]\n"
@@ -970,6 +997,8 @@ int cmd_fsck(int argc,
970997
git_config(git_fsck_config, &fsck_obj_options);
971998
prepare_repo_settings(the_repository);
972999

1000+
fsck_refs();
1001+
9731002
if (connectivity_only) {
9741003
for_each_loose_object(mark_loose_for_connectivity, NULL, 0);
9751004
for_each_packed_object(the_repository,

builtin/refs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ static int cmd_refs_verify(int argc, const char **argv, const char *prefix,
8888
git_config(git_fsck_config, &fsck_refs_options);
8989
prepare_repo_settings(the_repository);
9090

91-
worktrees = get_worktrees();
91+
worktrees = get_worktrees_without_reading_head();
9292
for (size_t i = 0; worktrees[i]; i++)
9393
ret |= refs_fsck(get_worktree_ref_store(worktrees[i]),
9494
&fsck_refs_options, worktrees[i]);

fsck.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ enum fsck_msg_type {
3030
FUNC(BAD_EMAIL, ERROR) \
3131
FUNC(BAD_NAME, ERROR) \
3232
FUNC(BAD_OBJECT_SHA1, ERROR) \
33+
FUNC(BAD_PACKED_REF_ENTRY, ERROR) \
34+
FUNC(BAD_PACKED_REF_HEADER, ERROR) \
3335
FUNC(BAD_PARENT_SHA1, ERROR) \
3436
FUNC(BAD_REF_CONTENT, ERROR) \
3537
FUNC(BAD_REF_FILETYPE, ERROR) \
@@ -53,6 +55,8 @@ enum fsck_msg_type {
5355
FUNC(MISSING_TYPE, ERROR) \
5456
FUNC(MISSING_TYPE_ENTRY, ERROR) \
5557
FUNC(MULTIPLE_AUTHORS, ERROR) \
58+
FUNC(PACKED_REF_ENTRY_NOT_TERMINATED, ERROR) \
59+
FUNC(PACKED_REF_UNSORTED, ERROR) \
5660
FUNC(TREE_NOT_SORTED, ERROR) \
5761
FUNC(UNKNOWN_TYPE, ERROR) \
5862
FUNC(ZERO_PADDED_DATE, ERROR) \
@@ -90,6 +94,8 @@ enum fsck_msg_type {
9094
FUNC(REF_MISSING_NEWLINE, INFO) \
9195
FUNC(SYMREF_TARGET_IS_NOT_A_REF, INFO) \
9296
FUNC(TRAILING_REF_CONTENT, INFO) \
97+
FUNC(UNKNOWN_PACKED_REF_HEADER, INFO) \
98+
FUNC(PACKED_REF_MISSING_HEADER, INFO) \
9399
/* ignored (elevated when requested) */ \
94100
FUNC(EXTRA_HEADER_ENTRY, IGNORE)
95101

@@ -163,6 +169,7 @@ struct fsck_options {
163169
fsck_error error_func;
164170
unsigned strict;
165171
unsigned verbose;
172+
int safe_object_check;
166173
enum fsck_msg_type *msg_type;
167174
struct oidset skip_oids;
168175
struct oidset gitmodules_found;
@@ -198,6 +205,7 @@ struct fsck_options {
198205
}
199206
#define FSCK_REFS_OPTIONS_DEFAULT { \
200207
.error_func = fsck_refs_error_function, \
208+
.safe_object_check = 1, \
201209
}
202210

203211
/* descend in all linked child objects

refs/files-backend.c

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "../lockfile.h"
2222
#include "../object.h"
2323
#include "../object-file.h"
24+
#include "../packfile.h"
2425
#include "../path.h"
2526
#include "../dir.h"
2627
#include "../chdir-notify.h"
@@ -3635,6 +3636,34 @@ static int files_fsck_symref_target(struct fsck_options *o,
36353636
return ret;
36363637
}
36373638

3639+
static int files_fsck_refs_oid(struct fsck_options *o,
3640+
struct ref_store *ref_store,
3641+
struct fsck_ref_report report,
3642+
const char *target_name,
3643+
struct object_id *oid)
3644+
{
3645+
struct object *obj;
3646+
int ret = 0;
3647+
3648+
if (!o->safe_object_check || is_promisor_object(ref_store->repo, oid))
3649+
return 0;
3650+
3651+
obj = parse_object(ref_store->repo, oid);
3652+
if (!obj) {
3653+
ret |= fsck_report_ref(o, &report,
3654+
FSCK_MSG_BAD_REF_CONTENT,
3655+
"points to non-existing object %s",
3656+
oid_to_hex(oid));
3657+
} else if (obj->type != OBJ_COMMIT && is_branch(target_name)) {
3658+
ret |= fsck_report_ref(o, &report,
3659+
FSCK_MSG_BAD_REF_CONTENT,
3660+
"points to non-commit object %s",
3661+
oid_to_hex(oid));
3662+
}
3663+
3664+
return ret;
3665+
}
3666+
36383667
static int files_fsck_refs_content(struct ref_store *ref_store,
36393668
struct fsck_options *o,
36403669
const char *target_name,
@@ -3700,18 +3729,19 @@ static int files_fsck_refs_content(struct ref_store *ref_store,
37003729
}
37013730

37023731
if (!(type & REF_ISSYMREF)) {
3732+
ret |= files_fsck_refs_oid(o, ref_store, report, target_name, &oid);
3733+
37033734
if (!*trailing) {
3704-
ret = fsck_report_ref(o, &report,
3705-
FSCK_MSG_REF_MISSING_NEWLINE,
3706-
"misses LF at the end");
3707-
goto cleanup;
3708-
}
3709-
if (*trailing != '\n' || *(trailing + 1)) {
3710-
ret = fsck_report_ref(o, &report,
3711-
FSCK_MSG_TRAILING_REF_CONTENT,
3712-
"has trailing garbage: '%s'", trailing);
3713-
goto cleanup;
3735+
ret |= fsck_report_ref(o, &report,
3736+
FSCK_MSG_REF_MISSING_NEWLINE,
3737+
"misses LF at the end");
3738+
} else if (*trailing != '\n' || *(trailing + 1)) {
3739+
ret |= fsck_report_ref(o, &report,
3740+
FSCK_MSG_TRAILING_REF_CONTENT,
3741+
"has trailing garbage: '%s'", trailing);
37143742
}
3743+
3744+
goto cleanup;
37153745
} else {
37163746
ret = files_fsck_symref_target(o, &report, &referent, 0);
37173747
goto cleanup;
@@ -3835,8 +3865,8 @@ static int files_fsck(struct ref_store *ref_store,
38353865
struct files_ref_store *refs =
38363866
files_downcast(ref_store, REF_STORE_READ, "fsck");
38373867

3838-
return files_fsck_refs(ref_store, o, wt) |
3839-
refs->packed_ref_store->be->fsck(refs->packed_ref_store, o, wt);
3868+
return refs->packed_ref_store->be->fsck(refs->packed_ref_store, o, wt) |
3869+
files_fsck_refs(ref_store, o, wt);
38403870
}
38413871

38423872
struct ref_storage_be refs_be_files = {

0 commit comments

Comments
 (0)