refs/files: extract function to check single ref
When checking the consistency of references we create a directory iterator and then verify each single reference in a loop. The logic to perform the actual checks is embedded into that loop, which makes it hard to reuse. But In a subsequent commit we're about to introduce a second path that wants to verify references. Prepare for this by extracting the logic to check a single reference into a standalone function. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Patrick Steinhardt committed
Jan 12, 2026 at 10:02 UTC
0ff9cf40b2ce3df2f6eda0875eb54fe3c3487f5b
1 file changed
+51
-29
refs/files-backend.c
+51
-29
@@ -3715,7 +3715,8 @@ static int files_ref_store_remove_on_disk(struct ref_store *ref_store,
3715
typedef int (*files_fsck_refs_fn)(struct ref_store *ref_store,
3716
struct fsck_options *o,
3717
const char *refname,
3718
- struct dir_iterator *iter);
3718
+ const char *path,
3719
+ int mode);
3720
3721
static int files_fsck_symref_target(struct fsck_options *o,
3722
struct fsck_ref_report *report,
@@ -3772,7 +3773,8 @@ out:
3773
static int files_fsck_refs_content(struct ref_store *ref_store,
3774
struct fsck_options *o,
3775
const char *target_name,
3775
- struct dir_iterator *iter)
3776
+ const char *path,
3777
+ int mode)
3778
{
3779
struct strbuf ref_content = STRBUF_INIT;
3780
struct strbuf abs_gitdir = STRBUF_INIT;
@@ -3786,7 +3788,7 @@ static int files_fsck_refs_content(struct ref_store *ref_store,
3788
3789
report.path = target_name;
3790
3789
- if (S_ISLNK(iter->st.st_mode)) {
3791
+ if (S_ISLNK(mode)) {
3792
const char *relative_referent_path = NULL;
3793
3794
ret = fsck_report_ref(o, &report,
@@ -3798,7 +3800,7 @@ static int files_fsck_refs_content(struct ref_store *ref_store,
3800
if (!is_dir_sep(abs_gitdir.buf[abs_gitdir.len - 1]))
3801
strbuf_addch(&abs_gitdir, '/');
3802
3801
- strbuf_add_real_path(&ref_content, iter->path.buf);
3803
+ strbuf_add_real_path(&ref_content, path);
3804
skip_prefix(ref_content.buf, abs_gitdir.buf,
3805
&relative_referent_path);
3806
@@ -3811,7 +3813,7 @@ static int files_fsck_refs_content(struct ref_store *ref_store,
3813
goto cleanup;
3814
}
3815
3814
- if (strbuf_read_file(&ref_content, iter->path.buf, 0) < 0) {
3816
+ if (strbuf_read_file(&ref_content, path, 0) < 0) {
3817
/*
3818
* Ref file could be removed by another concurrent process. We should
3819
* ignore this error and continue to the next ref.
@@ -3819,7 +3821,7 @@ static int files_fsck_refs_content(struct ref_store *ref_store,
3821
if (errno == ENOENT)
3822
goto cleanup;
3823
3822
- ret = error_errno(_("cannot read ref file '%s'"), iter->path.buf);
3824
+ ret = error_errno(_("cannot read ref file '%s'"), path);
3825
goto cleanup;
3826
}
3827
@@ -3861,16 +3863,20 @@ cleanup:
3863
static int files_fsck_refs_name(struct ref_store *ref_store UNUSED,
3864
struct fsck_options *o,
3865
const char *refname,
3864
- struct dir_iterator *iter)
3866
+ const char *path,
3867
+ int mode UNUSED)
3868
{
3869
struct strbuf sb = STRBUF_INIT;
3870
+ const char *filename;
3871
int ret = 0;
3872
3873
+ filename = basename((char *) path);
3874
+
3875
/*
3876
* Ignore the files ending with ".lock" as they may be lock files
3877
* However, do not allow bare ".lock" files.
3878
*/
3873
- if (iter->basename[0] != '.' && ends_with(iter->basename, ".lock"))
3879
+ if (filename[0] != '.' && ends_with(filename, ".lock"))
3880
goto cleanup;
3881
3882
/*
@@ -3896,6 +3902,35 @@ static const files_fsck_refs_fn fsck_refs_fn[]= {
3902
NULL,
3903
};
3904
3905
+static int files_fsck_ref(struct ref_store *ref_store,
3906
+ struct fsck_options *o,
3907
+ const char *refname,
3908
+ const char *path,
3909
+ int mode)
3910
+{
3911
+ int ret = 0;
3912
+
3913
+ if (o->verbose)
3914
+ fprintf_ln(stderr, "Checking %s", refname);
3915
+
3916
+ if (!S_ISREG(mode) && !S_ISLNK(mode)) {
3917
+ struct fsck_ref_report report = { .path = refname };
3918
+
3919
+ if (fsck_report_ref(o, &report,
3920
+ FSCK_MSG_BAD_REF_FILETYPE,
3921
+ "unexpected file type"))
3922
+ ret = -1;
3923
+ goto out;
3924
+ }
3925
+
3926
+ for (size_t i = 0; fsck_refs_fn[i]; i++)
3927
+ if (fsck_refs_fn[i](ref_store, o, refname, path, mode))
3928
+ ret = -1;
3929
+
3930
+out:
3931
+ return ret;
3932
+}
3933
+
3934
static int files_fsck_refs_dir(struct ref_store *ref_store,
3935
struct fsck_options *o,
3936
struct worktree *wt)
@@ -3918,30 +3953,17 @@ static int files_fsck_refs_dir(struct ref_store *ref_store,
3953
}
3954
3955
while ((iter_status = dir_iterator_advance(iter)) == ITER_OK) {
3921
- if (S_ISDIR(iter->st.st_mode)) {
3956
+ if (S_ISDIR(iter->st.st_mode))
3957
continue;
3923
- } else if (S_ISREG(iter->st.st_mode) ||
3924
- S_ISLNK(iter->st.st_mode)) {
3925
- strbuf_reset(&refname);
3926
-
3927
- if (!is_main_worktree(wt))
3928
- strbuf_addf(&refname, "worktrees/%s/", wt->id);
3929
- strbuf_addf(&refname, "refs/%s", iter->relative_path);
3958
3931
- if (o->verbose)
3932
- fprintf_ln(stderr, "Checking %s", refname.buf);
3959
+ strbuf_reset(&refname);
3960
+ if (!is_main_worktree(wt))
3961
+ strbuf_addf(&refname, "worktrees/%s/", wt->id);
3962
+ strbuf_addf(&refname, "refs/%s", iter->relative_path);
3963
3934
- for (size_t i = 0; fsck_refs_fn[i]; i++) {
3935
- if (fsck_refs_fn[i](ref_store, o, refname.buf, iter))
3936
- ret = -1;
3937
- }
3938
- } else {
3939
- struct fsck_ref_report report = { .path = iter->basename };
3940
- if (fsck_report_ref(o, &report,
3941
- FSCK_MSG_BAD_REF_FILETYPE,
3942
- "unexpected file type"))
3943
- ret = -1;
3944
- }
3964
+ if (files_fsck_ref(ref_store, o, refname.buf,
3965
+ iter->path.buf, iter->st.st_mode) < 0)
3966
+ ret = -1;
3967
}
3968
3969
if (iter_status != ITER_DONE)