Skip to content

Commit c9f03f3

Browse files
shejialuogitster
authored andcommitted
ref: add symlink ref content check for files backend
Besides the textual symref, we also allow symbolic links as the symref. So, we should also provide the consistency check as what we have done for textual symref. And also we consider deprecating writing the symbolic links. We first need to access whether symbolic links still be used. So, add a new fsck message "symlinkRef(INFO)" to tell the user be aware of this information. 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. And we need to also generate the "referent" parameter for reusing "files_fsck_symref_target" by the following steps: 1. Use "strbuf_add_real_path" to resolve the symlink and get the absolute path "ref_content" which the symlink ref points to. 2. Generate the absolute path "abs_gitdir" of "gitdir" and combine "ref_content" and "abs_gitdir" to extract the relative path "relative_referent_path". 3. If "ref_content" is outside of "gitdir", we just set "referent" with "ref_content". Instead, we set "referent" with "relative_referent_path". Mentored-by: Patrick Steinhardt <[email protected]> Mentored-by: Karthik Nayak <[email protected]> Signed-off-by: shejialuo <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent d996b44 commit c9f03f3

File tree

4 files changed

+182
-4
lines changed

4 files changed

+182
-4
lines changed

Documentation/fsck-msgids.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,12 @@
183183
[email protected] mailing list if you see this error, as
184184
we need to know what tools created such a file.
185185

186+
`symlinkRef`::
187+
(INFO) A symbolic link is used as a symref. Report to the
188+
[email protected] mailing list if you see this error, as we
189+
are assessing the feasibility of dropping the support to drop
190+
creating symbolic links as symrefs.
191+
186192
`symrefTargetIsNotARef`::
187193
(INFO) The target of a symbolic reference points neither to
188194
a root reference nor to a reference starting with "refs/".

fsck.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ enum fsck_msg_type {
8686
FUNC(MAILMAP_SYMLINK, INFO) \
8787
FUNC(BAD_TAG_NAME, INFO) \
8888
FUNC(MISSING_TAGGER_ENTRY, INFO) \
89+
FUNC(SYMLINK_REF, INFO) \
8990
FUNC(REF_MISSING_NEWLINE, INFO) \
9091
FUNC(SYMREF_TARGET_IS_NOT_A_REF, INFO) \
9192
FUNC(TRAILING_REF_CONTENT, INFO) \

refs/files-backend.c

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#define USE_THE_REPOSITORY_VARIABLE
22

33
#include "../git-compat-util.h"
4+
#include "../abspath.h"
45
#include "../config.h"
56
#include "../copy.h"
67
#include "../environment.h"
@@ -3511,7 +3512,8 @@ typedef int (*files_fsck_refs_fn)(struct ref_store *ref_store,
35113512

35123513
static int files_fsck_symref_target(struct fsck_options *o,
35133514
struct fsck_ref_report *report,
3514-
struct strbuf *referent)
3515+
struct strbuf *referent,
3516+
unsigned int symbolic_link)
35153517
{
35163518
int is_referent_root;
35173519
char orig_last_byte;
@@ -3520,7 +3522,8 @@ static int files_fsck_symref_target(struct fsck_options *o,
35203522

35213523
orig_len = referent->len;
35223524
orig_last_byte = referent->buf[orig_len - 1];
3523-
strbuf_rtrim(referent);
3525+
if (!symbolic_link)
3526+
strbuf_rtrim(referent);
35243527

35253528
is_referent_root = is_root_ref(referent->buf);
35263529
if (!is_referent_root &&
@@ -3539,6 +3542,9 @@ static int files_fsck_symref_target(struct fsck_options *o,
35393542
goto out;
35403543
}
35413544

3545+
if (symbolic_link)
3546+
goto out;
3547+
35423548
if (referent->len == orig_len ||
35433549
(referent->len < orig_len && orig_last_byte != '\n')) {
35443550
ret = fsck_report_ref(o, report,
@@ -3562,6 +3568,7 @@ static int files_fsck_refs_content(struct ref_store *ref_store,
35623568
struct dir_iterator *iter)
35633569
{
35643570
struct strbuf ref_content = STRBUF_INIT;
3571+
struct strbuf abs_gitdir = STRBUF_INIT;
35653572
struct strbuf referent = STRBUF_INIT;
35663573
struct fsck_ref_report report = { 0 };
35673574
const char *trailing = NULL;
@@ -3572,8 +3579,30 @@ static int files_fsck_refs_content(struct ref_store *ref_store,
35723579

35733580
report.path = target_name;
35743581

3575-
if (S_ISLNK(iter->st.st_mode))
3582+
if (S_ISLNK(iter->st.st_mode)) {
3583+
const char *relative_referent_path = NULL;
3584+
3585+
ret = fsck_report_ref(o, &report,
3586+
FSCK_MSG_SYMLINK_REF,
3587+
"use deprecated symbolic link for symref");
3588+
3589+
strbuf_add_absolute_path(&abs_gitdir, ref_store->repo->gitdir);
3590+
strbuf_normalize_path(&abs_gitdir);
3591+
if (!is_dir_sep(abs_gitdir.buf[abs_gitdir.len - 1]))
3592+
strbuf_addch(&abs_gitdir, '/');
3593+
3594+
strbuf_add_real_path(&ref_content, iter->path.buf);
3595+
skip_prefix(ref_content.buf, abs_gitdir.buf,
3596+
&relative_referent_path);
3597+
3598+
if (relative_referent_path)
3599+
strbuf_addstr(&referent, relative_referent_path);
3600+
else
3601+
strbuf_addbuf(&referent, &ref_content);
3602+
3603+
ret |= files_fsck_symref_target(o, &report, &referent, 1);
35763604
goto cleanup;
3605+
}
35773606

35783607
if (strbuf_read_file(&ref_content, iter->path.buf, 0) < 0) {
35793608
/*
@@ -3611,13 +3640,14 @@ static int files_fsck_refs_content(struct ref_store *ref_store,
36113640
goto cleanup;
36123641
}
36133642
} else {
3614-
ret = files_fsck_symref_target(o, &report, &referent);
3643+
ret = files_fsck_symref_target(o, &report, &referent, 0);
36153644
goto cleanup;
36163645
}
36173646

36183647
cleanup:
36193648
strbuf_release(&ref_content);
36203649
strbuf_release(&referent);
3650+
strbuf_release(&abs_gitdir);
36213651
return ret;
36223652
}
36233653

t/t0602-reffiles-fsck.sh

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,147 @@ test_expect_success 'the target of the textual symref should be checked' '
395395
done
396396
'
397397

398+
test_expect_success SYMLINKS 'symlink symref content should be checked' '
399+
test_when_finished "rm -rf repo" &&
400+
git init repo &&
401+
branch_dir_prefix=.git/refs/heads &&
402+
tag_dir_prefix=.git/refs/tags &&
403+
cd repo &&
404+
test_commit default &&
405+
mkdir -p "$branch_dir_prefix/a/b" &&
406+
407+
ln -sf ./main $branch_dir_prefix/branch-symbolic-good &&
408+
git refs verify 2>err &&
409+
cat >expect <<-EOF &&
410+
warning: refs/heads/branch-symbolic-good: symlinkRef: use deprecated symbolic link for symref
411+
EOF
412+
rm $branch_dir_prefix/branch-symbolic-good &&
413+
test_cmp expect err &&
414+
415+
ln -sf ../../logs/branch-escape $branch_dir_prefix/branch-symbolic &&
416+
git refs verify 2>err &&
417+
cat >expect <<-EOF &&
418+
warning: refs/heads/branch-symbolic: symlinkRef: use deprecated symbolic link for symref
419+
warning: refs/heads/branch-symbolic: symrefTargetIsNotARef: points to non-ref target '\''logs/branch-escape'\''
420+
EOF
421+
rm $branch_dir_prefix/branch-symbolic &&
422+
test_cmp expect err &&
423+
424+
ln -sf ./"branch " $branch_dir_prefix/branch-symbolic-bad &&
425+
test_must_fail git refs verify 2>err &&
426+
cat >expect <<-EOF &&
427+
warning: refs/heads/branch-symbolic-bad: symlinkRef: use deprecated symbolic link for symref
428+
error: refs/heads/branch-symbolic-bad: badReferentName: points to invalid refname '\''refs/heads/branch '\''
429+
EOF
430+
rm $branch_dir_prefix/branch-symbolic-bad &&
431+
test_cmp expect err &&
432+
433+
ln -sf ./".tag" $tag_dir_prefix/tag-symbolic-1 &&
434+
test_must_fail git refs verify 2>err &&
435+
cat >expect <<-EOF &&
436+
warning: refs/tags/tag-symbolic-1: symlinkRef: use deprecated symbolic link for symref
437+
error: refs/tags/tag-symbolic-1: badReferentName: points to invalid refname '\''refs/tags/.tag'\''
438+
EOF
439+
rm $tag_dir_prefix/tag-symbolic-1 &&
440+
test_cmp expect err
441+
'
442+
443+
test_expect_success SYMLINKS 'symlink symref content should be checked (worktree)' '
444+
test_when_finished "rm -rf repo" &&
445+
git init repo &&
446+
cd repo &&
447+
test_commit default &&
448+
git branch branch-1 &&
449+
git branch branch-2 &&
450+
git branch branch-3 &&
451+
git worktree add ./worktree-1 branch-2 &&
452+
git worktree add ./worktree-2 branch-3 &&
453+
main_worktree_refdir_prefix=.git/refs/heads &&
454+
worktree1_refdir_prefix=.git/worktrees/worktree-1/refs/worktree &&
455+
worktree2_refdir_prefix=.git/worktrees/worktree-2/refs/worktree &&
456+
457+
(
458+
cd worktree-1 &&
459+
git update-ref refs/worktree/branch-4 refs/heads/branch-1
460+
) &&
461+
(
462+
cd worktree-2 &&
463+
git update-ref refs/worktree/branch-4 refs/heads/branch-1
464+
) &&
465+
466+
ln -sf ../../../../refs/heads/good-branch $worktree1_refdir_prefix/branch-symbolic-good &&
467+
git refs verify 2>err &&
468+
cat >expect <<-EOF &&
469+
warning: worktrees/worktree-1/refs/worktree/branch-symbolic-good: symlinkRef: use deprecated symbolic link for symref
470+
EOF
471+
rm $worktree1_refdir_prefix/branch-symbolic-good &&
472+
test_cmp expect err &&
473+
474+
ln -sf ../../../../worktrees/worktree-1/good-branch $worktree2_refdir_prefix/branch-symbolic-good &&
475+
git refs verify 2>err &&
476+
cat >expect <<-EOF &&
477+
warning: worktrees/worktree-2/refs/worktree/branch-symbolic-good: symlinkRef: use deprecated symbolic link for symref
478+
EOF
479+
rm $worktree2_refdir_prefix/branch-symbolic-good &&
480+
test_cmp expect err &&
481+
482+
ln -sf ../../worktrees/worktree-2/good-branch $main_worktree_refdir_prefix/branch-symbolic-good &&
483+
git refs verify 2>err &&
484+
cat >expect <<-EOF &&
485+
warning: refs/heads/branch-symbolic-good: symlinkRef: use deprecated symbolic link for symref
486+
EOF
487+
rm $main_worktree_refdir_prefix/branch-symbolic-good &&
488+
test_cmp expect err &&
489+
490+
ln -sf ../../../../logs/branch-escape $worktree1_refdir_prefix/branch-symbolic &&
491+
git refs verify 2>err &&
492+
cat >expect <<-EOF &&
493+
warning: worktrees/worktree-1/refs/worktree/branch-symbolic: symlinkRef: use deprecated symbolic link for symref
494+
warning: worktrees/worktree-1/refs/worktree/branch-symbolic: symrefTargetIsNotARef: points to non-ref target '\''logs/branch-escape'\''
495+
EOF
496+
rm $worktree1_refdir_prefix/branch-symbolic &&
497+
test_cmp expect err &&
498+
499+
for bad_referent_name in ".tag" "branch "
500+
do
501+
ln -sf ./"$bad_referent_name" $worktree1_refdir_prefix/bad-symbolic &&
502+
test_must_fail git refs verify 2>err &&
503+
cat >expect <<-EOF &&
504+
warning: worktrees/worktree-1/refs/worktree/bad-symbolic: symlinkRef: use deprecated symbolic link for symref
505+
error: worktrees/worktree-1/refs/worktree/bad-symbolic: badReferentName: points to invalid refname '\''worktrees/worktree-1/refs/worktree/$bad_referent_name'\''
506+
EOF
507+
rm $worktree1_refdir_prefix/bad-symbolic &&
508+
test_cmp expect err &&
509+
510+
ln -sf ../../../../refs/heads/"$bad_referent_name" $worktree1_refdir_prefix/bad-symbolic &&
511+
test_must_fail git refs verify 2>err &&
512+
cat >expect <<-EOF &&
513+
warning: worktrees/worktree-1/refs/worktree/bad-symbolic: symlinkRef: use deprecated symbolic link for symref
514+
error: worktrees/worktree-1/refs/worktree/bad-symbolic: badReferentName: points to invalid refname '\''refs/heads/$bad_referent_name'\''
515+
EOF
516+
rm $worktree1_refdir_prefix/bad-symbolic &&
517+
test_cmp expect err &&
518+
519+
ln -sf ./"$bad_referent_name" $worktree2_refdir_prefix/bad-symbolic &&
520+
test_must_fail git refs verify 2>err &&
521+
cat >expect <<-EOF &&
522+
warning: worktrees/worktree-2/refs/worktree/bad-symbolic: symlinkRef: use deprecated symbolic link for symref
523+
error: worktrees/worktree-2/refs/worktree/bad-symbolic: badReferentName: points to invalid refname '\''worktrees/worktree-2/refs/worktree/$bad_referent_name'\''
524+
EOF
525+
rm $worktree2_refdir_prefix/bad-symbolic &&
526+
test_cmp expect err &&
527+
528+
ln -sf ../../../../refs/heads/"$bad_referent_name" $worktree2_refdir_prefix/bad-symbolic &&
529+
test_must_fail git refs verify 2>err &&
530+
cat >expect <<-EOF &&
531+
warning: worktrees/worktree-2/refs/worktree/bad-symbolic: symlinkRef: use deprecated symbolic link for symref
532+
error: worktrees/worktree-2/refs/worktree/bad-symbolic: badReferentName: points to invalid refname '\''refs/heads/$bad_referent_name'\''
533+
EOF
534+
rm $worktree2_refdir_prefix/bad-symbolic &&
535+
test_cmp expect err || return 1
536+
done
537+
'
538+
398539
test_expect_success 'ref content checks should work with worktrees' '
399540
test_when_finished "rm -rf repo" &&
400541
git init repo &&

0 commit comments

Comments
 (0)