Skip to content

Commit

Permalink
files-backend: add unified interface for refs scanning
Browse files Browse the repository at this point in the history
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>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
shejialuo authored and gitster committed Aug 8, 2024
1 parent bf061d2 commit a7600b8
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 1 deletion.
3 changes: 3 additions & 0 deletions Documentation/fsck-msgids.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
1 change: 1 addition & 0 deletions fsck.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) \
Expand Down
73 changes: 72 additions & 1 deletion refs/files-backend.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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 = {
Expand Down

0 comments on commit a7600b8

Please sign in to comment.