@@ -19,6 +19,9 @@
`badParentSha1`::
(ERROR) A commit object has a bad parent sha1.
+`badRefFiletype`::
+ (ERROR) A ref has a bad file type.
+
`badTagName`::
(INFO) A tag has an invalid format.
@@ -31,6 +31,7 @@ enum fsck_msg_type {
FUNC(BAD_NAME, ERROR) \
FUNC(BAD_OBJECT_SHA1, ERROR) \
FUNC(BAD_PARENT_SHA1, ERROR) \
+ FUNC(BAD_REF_FILETYPE, ERROR) \
FUNC(BAD_TIMEZONE, ERROR) \
FUNC(BAD_TREE, ERROR) \
FUNC(BAD_TREE_SHA1, ERROR) \
@@ -6,6 +6,7 @@
#include "../gettext.h"
#include "../hash.h"
#include "../hex.h"
+#include "../fsck.h"
#include "../refs.h"
#include "refs-internal.h"
#include "ref-cache.h"
@@ -3408,13 +3409,83 @@ static int files_ref_store_remove_on_disk(struct ref_store *ref_store,
return ret;
}
+/*
+ * For refs and reflogs, they share a unified interface when scanning
+ * the whole directory. This function is used as the callback for each
+ * regular file or symlink in the directory.
+ */
+typedef int (*files_fsck_refs_fn)(struct ref_store *ref_store,
+ struct fsck_options *o,
+ const char *refs_check_dir,
+ struct dir_iterator *iter);
+
+static int files_fsck_refs_dir(struct ref_store *ref_store,
+ struct fsck_options *o,
+ const char *refs_check_dir,
+ files_fsck_refs_fn *fsck_refs_fn)
+{
+ struct strbuf sb = STRBUF_INIT;
+ struct dir_iterator *iter;
+ int iter_status;
+ int ret = 0;
+
+ strbuf_addf(&sb, "%s/%s", ref_store->gitdir, refs_check_dir);
+
+ iter = dir_iterator_begin(sb.buf, 0);
+ if (!iter) {
+ ret = error_errno(_("cannot open directory %s"), sb.buf);
+ goto out;
+ }
+
+ while ((iter_status = dir_iterator_advance(iter)) == ITER_OK) {
+ if (S_ISDIR(iter->st.st_mode)) {
+ continue;
+ } else if (S_ISREG(iter->st.st_mode) ||
+ S_ISLNK(iter->st.st_mode)) {
+ if (o->verbose)
+ fprintf_ln(stderr, "Checking %s/%s",
+ refs_check_dir, iter->relative_path);
+ for (size_t i = 0; fsck_refs_fn[i]; i++) {
+ if (fsck_refs_fn[i](ref_store, o, refs_check_dir, iter))
+ ret = -1;
+ }
+ } else {
+ struct fsck_ref_report report = { .path = iter->basename };
+ if (fsck_report_ref(o, &report,
+ FSCK_MSG_BAD_REF_FILETYPE,
+ "unexpected file type"))
+ ret = -1;
+ }
+ }
+
+ if (iter_status != ITER_DONE)
+ ret = error(_("failed to iterate over '%s'"), sb.buf);
+
+out:
+ strbuf_release(&sb);
+ return ret;
+}
+
+static int files_fsck_refs(struct ref_store *ref_store,
+ struct fsck_options *o)
+{
+ files_fsck_refs_fn fsck_refs_fn[]= {
+ NULL,
+ };
+
+ if (o->verbose)
+ fprintf_ln(stderr, _("Checking references consistency"));
+ return files_fsck_refs_dir(ref_store, o, "refs", fsck_refs_fn);
+}
+
static int files_fsck(struct ref_store *ref_store,
struct fsck_options *o)
{
struct files_ref_store *refs =
files_downcast(ref_store, REF_STORE_READ, "fsck");
- return refs->packed_ref_store->be->fsck(refs->packed_ref_store, o);
+ return files_fsck_refs(ref_store, o) |
+ refs->packed_ref_store->be->fsck(refs->packed_ref_store, o);
}
struct ref_storage_be refs_be_files = {
For refs and reflogs, we need to scan its corresponding directories to check every regular file or symbolic link which shares the same pattern. Introduce a unified interface for scanning directories for files-backend. 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 | 3 ++ fsck.h | 1 + refs/files-backend.c | 73 ++++++++++++++++++++++++++++++++++- 3 files changed, 76 insertions(+), 1 deletion(-)