Skip to content

Commit

Permalink
Merge branch 'sj/ref-contents-check' into next
Browse files Browse the repository at this point in the history
"git fsck" learned to issue warnings on "curiously formatted" ref
contents that have always been taken valid but something Git
wouldn't have written itself (e.g., missing terminating end-of-line
after the full object name).

* sj/ref-contents-check:
  ref: add symlink ref content check for files backend
  ref: check whether the target of the symref is a ref
  ref: add basic symref content check for files backend
  ref: add more strict checks for regular refs
  ref: port git-fsck(1) regular refs check for files backend
  ref: support multiple worktrees check for refs
  ref: initialize ref name outside of check functions
  ref: check the full refname instead of basename
  ref: initialize "fsck_ref_report" with zero
  • Loading branch information
gitster committed Nov 25, 2024
2 parents ee2e588 + c9f03f3 commit 53e29ae
Show file tree
Hide file tree
Showing 11 changed files with 790 additions and 62 deletions.
35 changes: 35 additions & 0 deletions Documentation/fsck-msgids.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,18 @@
`badParentSha1`::
(ERROR) A commit object has a bad parent sha1.

`badRefContent`::
(ERROR) A ref has bad content.

`badRefFiletype`::
(ERROR) A ref has a bad file type.

`badRefName`::
(ERROR) A ref has an invalid format.

`badReferentName`::
(ERROR) The referent name of a symref is invalid.

`badTagName`::
(INFO) A tag has an invalid format.

Expand Down Expand Up @@ -170,6 +176,35 @@
`nullSha1`::
(WARN) Tree contains entries pointing to a null sha1.

`refMissingNewline`::
(INFO) A loose ref that does not end with newline(LF). As
valid implementations of Git never created such a loose ref
file, it may become an error in the future. Report to the
[email protected] mailing list if you see this error, as
we need to know what tools created such a file.

`symlinkRef`::
(INFO) A symbolic link is used as a symref. Report to the
[email protected] mailing list if you see this error, as we
are assessing the feasibility of dropping the support to drop
creating symbolic links as symrefs.

`symrefTargetIsNotARef`::
(INFO) The target of a symbolic reference points neither to
a root reference nor to a reference starting with "refs/".
Although we allow create a symref pointing to the referent which
is outside the "ref" by using `git symbolic-ref`, we may tighten
the rule in the future. Report to the [email protected]
mailing list if you see this error, as we need to know what tools
created such a file.

`trailingRefContent`::
(INFO) A loose ref has trailing content. As valid implementations
of Git never created such a loose ref file, it may become an
error in the future. Report to the [email protected] mailing
list if you see this error, as we need to know what tools
created such a file.

`treeNotSorted`::
(ERROR) A tree is not properly sorted.

Expand Down
10 changes: 8 additions & 2 deletions builtin/refs.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "parse-options.h"
#include "refs.h"
#include "strbuf.h"
#include "worktree.h"

#define REFS_MIGRATE_USAGE \
N_("git refs migrate --ref-format=<format> [--dry-run]")
Expand Down Expand Up @@ -66,6 +67,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 fsck_options fsck_refs_options = FSCK_REFS_OPTIONS_DEFAULT;
struct worktree **worktrees;
const char * const verify_usage[] = {
REFS_VERIFY_USAGE,
NULL,
Expand All @@ -75,7 +77,7 @@ static int cmd_refs_verify(int argc, const char **argv, const char *prefix)
OPT_BOOL(0, "strict", &fsck_refs_options.strict, N_("enable strict checking")),
OPT_END(),
};
int ret;
int ret = 0;

argc = parse_options(argc, argv, prefix, options, verify_usage, 0);
if (argc)
Expand All @@ -84,9 +86,13 @@ 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);

ret = refs_fsck(get_main_ref_store(the_repository), &fsck_refs_options);
worktrees = get_worktrees();
for (size_t i = 0; worktrees[i]; i++)
ret |= refs_fsck(get_worktree_ref_store(worktrees[i]),
&fsck_refs_options, worktrees[i]);

fsck_options_clear(&fsck_refs_options);
free_worktrees(worktrees);
return ret;
}

Expand Down
6 changes: 6 additions & 0 deletions fsck.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@ enum fsck_msg_type {
FUNC(BAD_NAME, ERROR) \
FUNC(BAD_OBJECT_SHA1, ERROR) \
FUNC(BAD_PARENT_SHA1, ERROR) \
FUNC(BAD_REF_CONTENT, ERROR) \
FUNC(BAD_REF_FILETYPE, ERROR) \
FUNC(BAD_REF_NAME, ERROR) \
FUNC(BAD_REFERENT_NAME, ERROR) \
FUNC(BAD_TIMEZONE, ERROR) \
FUNC(BAD_TREE, ERROR) \
FUNC(BAD_TREE_SHA1, ERROR) \
Expand Down Expand Up @@ -84,6 +86,10 @@ enum fsck_msg_type {
FUNC(MAILMAP_SYMLINK, INFO) \
FUNC(BAD_TAG_NAME, INFO) \
FUNC(MISSING_TAGGER_ENTRY, INFO) \
FUNC(SYMLINK_REF, INFO) \
FUNC(REF_MISSING_NEWLINE, INFO) \
FUNC(SYMREF_TARGET_IS_NOT_A_REF, INFO) \
FUNC(TRAILING_REF_CONTENT, INFO) \
/* ignored (elevated when requested) */ \
FUNC(EXTRA_HEADER_ENTRY, IGNORE)

Expand Down
7 changes: 4 additions & 3 deletions refs.c
Original file line number Diff line number Diff line change
Expand Up @@ -318,9 +318,10 @@ int check_refname_format(const char *refname, int flags)
return check_or_sanitize_refname(refname, flags, NULL);
}

int refs_fsck(struct ref_store *refs, struct fsck_options *o)
int refs_fsck(struct ref_store *refs, struct fsck_options *o,
struct worktree *wt)
{
return refs->be->fsck(refs, o);
return refs->be->fsck(refs, o, wt);
}

void sanitize_refname_component(const char *refname, struct strbuf *out)
Expand Down Expand Up @@ -1791,7 +1792,7 @@ static int refs_read_special_head(struct ref_store *ref_store,
}

result = parse_loose_ref_contents(ref_store->repo->hash_algo, content.buf,
oid, referent, type, failure_errno);
oid, referent, type, NULL, failure_errno);

done:
strbuf_release(&full_path);
Expand Down
3 changes: 2 additions & 1 deletion refs.h
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,8 @@ int check_refname_format(const char *refname, int flags);
* reflogs are consistent, and non-zero otherwise. The errors will be
* written to stderr.
*/
int refs_fsck(struct ref_store *refs, struct fsck_options *o);
int refs_fsck(struct ref_store *refs, struct fsck_options *o,
struct worktree *wt);

/*
* Apply the rules from check_refname_format, but mutate the result until it
Expand Down
5 changes: 3 additions & 2 deletions refs/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -408,10 +408,11 @@ static int debug_reflog_expire(struct ref_store *ref_store, const char *refname,
}

static int debug_fsck(struct ref_store *ref_store,
struct fsck_options *o)
struct fsck_options *o,
struct worktree *wt)
{
struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
int res = drefs->refs->be->fsck(drefs->refs, o);
int res = drefs->refs->be->fsck(drefs->refs, o, wt);
trace_printf_key(&trace_refs, "fsck: %d\n", res);
return res;
}
Expand Down
Loading

0 comments on commit 53e29ae

Please sign in to comment.