@@ -184,6 +184,12 @@
`nullSha1`::
(WARN) Tree contains entries pointing to a null sha1.
+`symlinkRef`::
+ (INFO) A symbolic link is used as a symref. Report to the
+ git@vger.kernel.org mailing list if you see this error, as we
+ are assessing the feasibility of dropping the support to drop
+ creating symblinks as symrefs.
+
`treeNotSorted`::
(ERROR) A tree is not properly sorted.
@@ -87,6 +87,7 @@ enum fsck_msg_type {
FUNC(MAILMAP_SYMLINK, INFO) \
FUNC(BAD_TAG_NAME, INFO) \
FUNC(MISSING_TAGGER_ENTRY, INFO) \
+ FUNC(SYMLINK_REF, INFO) \
FUNC(UNOFFICIAL_FORMATTED_REF, INFO) \
/* ignored (elevated when requested) */ \
FUNC(EXTRA_HEADER_ENTRY, IGNORE)
@@ -1,6 +1,7 @@
#define USE_THE_REPOSITORY_VARIABLE
#include "../git-compat-util.h"
+#include "../abspath.h"
#include "../config.h"
#include "../copy.h"
#include "../environment.h"
@@ -3510,15 +3511,18 @@ typedef int (*files_fsck_refs_fn)(struct ref_store *ref_store,
static int files_fsck_symref_target(struct fsck_options *o,
struct fsck_ref_report *report,
- struct strbuf *referent)
+ struct strbuf *referent,
+ unsigned int symbolic_link)
{
char orig_last_byte;
size_t orig_len;
int ret = 0;
- orig_len = referent->len;
- orig_last_byte = referent->buf[orig_len - 1];
- strbuf_rtrim(referent);
+ if (!symbolic_link) {
+ orig_len = referent->len;
+ orig_last_byte = referent->buf[orig_len - 1];
+ strbuf_rtrim(referent);
+ }
if (!starts_with(referent->buf, "refs/") &&
!starts_with(referent->buf, "worktrees/")) {
@@ -3535,6 +3539,9 @@ static int files_fsck_symref_target(struct fsck_options *o,
goto out;
}
+ if (symbolic_link)
+ goto out;
+
if (referent->len == orig_len ||
(referent->len < orig_len && orig_last_byte != '\n')) {
@@ -3559,6 +3566,7 @@ static int files_fsck_refs_content(struct ref_store *ref_store,
struct dir_iterator *iter)
{
struct strbuf ref_content = STRBUF_INIT;
+ struct strbuf abs_gitdir = STRBUF_INIT;
struct strbuf referent = STRBUF_INIT;
struct strbuf refname = STRBUF_INIT;
struct fsck_ref_report report = { 0 };
@@ -3571,8 +3579,30 @@ static int files_fsck_refs_content(struct ref_store *ref_store,
strbuf_addf(&refname, "%s/%s", refs_check_dir, iter->relative_path);
report.path = refname.buf;
- if (S_ISLNK(iter->st.st_mode))
+ if (S_ISLNK(iter->st.st_mode)) {
+ const char* relative_referent_path = NULL;
+
+ ret = fsck_report_ref(o, &report,
+ FSCK_MSG_SYMLINK_REF,
+ "use deprecated symbolic link for symref");
+
+ strbuf_add_absolute_path(&abs_gitdir, ref_store->gitdir);
+ strbuf_normalize_path(&abs_gitdir);
+ if (!is_dir_sep(abs_gitdir.buf[abs_gitdir.len - 1]))
+ strbuf_addch(&abs_gitdir, '/');
+
+ strbuf_add_real_path(&ref_content, iter->path.buf);
+ skip_prefix(ref_content.buf, abs_gitdir.buf,
+ &relative_referent_path);
+
+ if (relative_referent_path)
+ strbuf_addstr(&referent, relative_referent_path);
+ else
+ strbuf_addbuf(&referent, &ref_content);
+
+ ret += files_fsck_symref_target(o, &report, &referent, 1);
goto cleanup;
+ }
if (strbuf_read_file(&ref_content, iter->path.buf, 0) < 0) {
ret = fsck_report_ref(o, &report,
@@ -3605,7 +3635,7 @@ static int files_fsck_refs_content(struct ref_store *ref_store,
goto cleanup;
}
} else {
- ret = files_fsck_symref_target(o, &report, &referent);
+ ret = files_fsck_symref_target(o, &report, &referent, 0);
goto cleanup;
}
@@ -3613,6 +3643,7 @@ static int files_fsck_refs_content(struct ref_store *ref_store,
strbuf_release(&refname);
strbuf_release(&ref_content);
strbuf_release(&referent);
+ strbuf_release(&abs_gitdir);
return ret;
}
@@ -486,4 +486,49 @@ test_expect_success 'all textual symref checks should work with worktrees' '
rm $worktree2_refdir_prefix/branch-garbage
'
+test_expect_success SYMLINKS 'symlink symref content should be checked (individual)' '
+ 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" &&
+
+ ln -sf ./main $branch_dir_prefix/branch-symbolic-good &&
+ git refs verify 2>err &&
+ cat >expect <<-EOF &&
+ warning: refs/heads/branch-symbolic-good: symlinkRef: use deprecated symbolic link for symref
+ EOF
+ rm $branch_dir_prefix/branch-symbolic-good &&
+ test_cmp expect err &&
+
+ ln -sf ../../logs/branch-escape $branch_dir_prefix/branch-symbolic &&
+ git refs verify 2>err &&
+ cat >expect <<-EOF &&
+ warning: refs/heads/branch-symbolic: symlinkRef: use deprecated symbolic link for symref
+ warning: refs/heads/branch-symbolic: escapeReferent: referent '\''logs/branch-escape'\'' is outside of refs/ or worktrees/
+ EOF
+ rm $branch_dir_prefix/branch-symbolic &&
+ test_cmp expect err &&
+
+ ln -sf ./"branch space" $branch_dir_prefix/branch-symbolic-bad &&
+ test_must_fail git refs verify 2>err &&
+ cat >expect <<-EOF &&
+ warning: refs/heads/branch-symbolic-bad: symlinkRef: use deprecated symbolic link for symref
+ error: refs/heads/branch-symbolic-bad: badReferent: points to invalid refname '\''refs/heads/branch space'\''
+ EOF
+ rm $branch_dir_prefix/branch-symbolic-bad &&
+ test_cmp expect err &&
+
+ ln -sf ./".tag" $tag_dir_prefix/tag-symbolic-1 &&
+ test_must_fail git refs verify 2>err &&
+ cat >expect <<-EOF &&
+ warning: refs/tags/tag-symbolic-1: symlinkRef: use deprecated symbolic link for symref
+ error: refs/tags/tag-symbolic-1: badReferent: points to invalid refname '\''refs/tags/.tag'\''
+ EOF
+ rm $tag_dir_prefix/tag-symbolic-1 &&
+ test_cmp expect err
+'
+
test_done
We have already introduced "files_fsck_symref_target". We should reuse this function to handle the symrefs which use legacy symbolic links. We should not check the trailing garbage for symbolic refs. Add a new parameter "symbolic_link" to disable some checks which should only be executed for textual symrefs. We firstly use the "strbuf_add_real_path" to resolve the symlink and get the absolute path as the "ref_content" which the symlink ref points to. Then we can use the absolute "abs_gitdir" of the "gitdir" and then combine "ref_content" and "abs_gitdir" to extract the relative path "referent". If "ref_content" is outside of "gitdir", we just use the "ref_content" as the "referent". Thus, we can reuse "files_fsck_symref_target" function to seamlessly check the symlink refs. Because we consider deprecating writing the symbolic links. We first need to asses whether symbolic links may still be used. So, add a new fsck message "symlinkRef(INFO)" to tell the user be aware of this information. 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 | 6 +++++ fsck.h | 1 + refs/files-backend.c | 43 ++++++++++++++++++++++++++++----- t/t0602-reffiles-fsck.sh | 45 +++++++++++++++++++++++++++++++++++ 4 files changed, 89 insertions(+), 6 deletions(-)