@@ -52,6 +52,14 @@
`emptyName`::
(WARN) A path contains an empty name.
+`escapeReferent`::
+ (INFO) The referent of a symref is outside the "ref" directory.
+ 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 git@vger.kernel.org
+ mailing list if you see this error, as we need to know what tools
+ created such a file.
+
`extraHeaderEntry`::
(IGNORE) Extra headers found after `tagger`.
@@ -80,6 +80,7 @@ enum fsck_msg_type {
FUNC(LARGE_PATHNAME, WARN) \
/* infos (reported as warnings, but ignored by default) */ \
FUNC(BAD_FILEMODE, INFO) \
+ FUNC(ESCAPE_REFERENT, INFO) \
FUNC(GITMODULES_PARSE, INFO) \
FUNC(GITIGNORE_SYMLINK, INFO) \
FUNC(GITATTRIBUTES_SYMLINK, INFO) \
@@ -3520,6 +3520,13 @@ static int files_fsck_symref_target(struct fsck_options *o,
orig_last_byte = referent->buf[orig_len - 1];
strbuf_rtrim(referent);
+ if (!starts_with(referent->buf, "refs/")) {
+ ret = fsck_report_ref(o, report,
+ FSCK_MSG_ESCAPE_REFERENT,
+ "referent '%s' is outside of refs/",
+ referent->buf);
+ }
+
if (check_refname_format(referent->buf, 0)) {
ret = fsck_report_ref(o, report,
FSCK_MSG_BAD_REFERENT,
@@ -370,4 +370,22 @@ test_expect_success 'textual symref content should be checked (aggregate)' '
test_cmp expect sorted_err
'
+test_expect_success 'textual symref should be checked whether it is escaped' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ branch_dir_prefix=.git/refs/heads &&
+ tag_dir_prefix=.git/refs/tags &&
+ cd repo &&
+ test_commit default &&
+ mkdir -p "$branch_dir_prefix/a/b" &&
+
+ printf "ref: refs-back/heads/main\n" >$branch_dir_prefix/branch-bad-1 &&
+ git refs verify 2>err &&
+ cat >expect <<-EOF &&
+ warning: refs/heads/branch-bad-1: escapeReferent: referent '\''refs-back/heads/main'\'' is outside of refs/
+ EOF
+ rm $branch_dir_prefix/branch-bad-1 &&
+ test_cmp expect err
+'
+
test_done
Ideally, we want to the users use "git symbolic-ref" to create symrefs instead of writing raw contents into the filesystem. However, "git symbolic-ref" is strict with the refname but not strict with the referent. For example, we can make the "referent" located at the "$(gitdir)/logs/aaa" and manually write the content into this where we can still successfully parse this symref by using "git rev-parse". $ git init repo && cd repo && git commit --allow-empty -mx $ git symbolic-ref refs/heads/test logs/aaa $ echo $(git rev-parse HEAD) > .git/logs/aaa $ git rev-parse test We may need to add some restrictions for "referent" parameter when using "git symbolic-ref" to create symrefs because ideally all the nonpeudo-refs should be located under the "refs" directory and we may tighten this in the future. In order to tell the user we may tighten the "escape" situation, create a new fsck message "escapeReferent" to notify the user that this may become an error in the future. Mentored-by: Patrick Steinhardt <ps@pks.im> Mentored-by: Karthik Nayak <karthik.188@gmail.com> Signed-off-by: shejialuo <shejialuo@gmail.com> --- Documentation/fsck-msgids.txt | 8 ++++++++ fsck.h | 1 + refs/files-backend.c | 7 +++++++ t/t0602-reffiles-fsck.sh | 18 ++++++++++++++++++ 4 files changed, 34 insertions(+)