|
6 | 6 | #include "../gettext.h"
|
7 | 7 | #include "../hash.h"
|
8 | 8 | #include "../hex.h"
|
| 9 | +#include "../fsck.h" |
9 | 10 | #include "../refs.h"
|
10 | 11 | #include "refs-internal.h"
|
11 | 12 | #include "ref-cache.h"
|
@@ -3408,13 +3409,83 @@ static int files_ref_store_remove_on_disk(struct ref_store *ref_store,
|
3408 | 3409 | return ret;
|
3409 | 3410 | }
|
3410 | 3411 |
|
| 3412 | +/* |
| 3413 | + * For refs and reflogs, they share a unified interface when scanning |
| 3414 | + * the whole directory. This function is used as the callback for each |
| 3415 | + * regular file or symlink in the directory. |
| 3416 | + */ |
| 3417 | +typedef int (*files_fsck_refs_fn)(struct ref_store *ref_store, |
| 3418 | + struct fsck_options *o, |
| 3419 | + const char *refs_check_dir, |
| 3420 | + struct dir_iterator *iter); |
| 3421 | + |
| 3422 | +static int files_fsck_refs_dir(struct ref_store *ref_store, |
| 3423 | + struct fsck_options *o, |
| 3424 | + const char *refs_check_dir, |
| 3425 | + files_fsck_refs_fn *fsck_refs_fn) |
| 3426 | +{ |
| 3427 | + struct strbuf sb = STRBUF_INIT; |
| 3428 | + struct dir_iterator *iter; |
| 3429 | + int iter_status; |
| 3430 | + int ret = 0; |
| 3431 | + |
| 3432 | + strbuf_addf(&sb, "%s/%s", ref_store->gitdir, refs_check_dir); |
| 3433 | + |
| 3434 | + iter = dir_iterator_begin(sb.buf, 0); |
| 3435 | + if (!iter) { |
| 3436 | + ret = error_errno(_("cannot open directory %s"), sb.buf); |
| 3437 | + goto out; |
| 3438 | + } |
| 3439 | + |
| 3440 | + while ((iter_status = dir_iterator_advance(iter)) == ITER_OK) { |
| 3441 | + if (S_ISDIR(iter->st.st_mode)) { |
| 3442 | + continue; |
| 3443 | + } else if (S_ISREG(iter->st.st_mode) || |
| 3444 | + S_ISLNK(iter->st.st_mode)) { |
| 3445 | + if (o->verbose) |
| 3446 | + fprintf_ln(stderr, "Checking %s/%s", |
| 3447 | + refs_check_dir, iter->relative_path); |
| 3448 | + for (size_t i = 0; fsck_refs_fn[i]; i++) { |
| 3449 | + if (fsck_refs_fn[i](ref_store, o, refs_check_dir, iter)) |
| 3450 | + ret = -1; |
| 3451 | + } |
| 3452 | + } else { |
| 3453 | + struct fsck_ref_report report = { .path = iter->basename }; |
| 3454 | + if (fsck_report_ref(o, &report, |
| 3455 | + FSCK_MSG_BAD_REF_FILETYPE, |
| 3456 | + "unexpected file type")) |
| 3457 | + ret = -1; |
| 3458 | + } |
| 3459 | + } |
| 3460 | + |
| 3461 | + if (iter_status != ITER_DONE) |
| 3462 | + ret = error(_("failed to iterate over '%s'"), sb.buf); |
| 3463 | + |
| 3464 | +out: |
| 3465 | + strbuf_release(&sb); |
| 3466 | + return ret; |
| 3467 | +} |
| 3468 | + |
| 3469 | +static int files_fsck_refs(struct ref_store *ref_store, |
| 3470 | + struct fsck_options *o) |
| 3471 | +{ |
| 3472 | + files_fsck_refs_fn fsck_refs_fn[]= { |
| 3473 | + NULL, |
| 3474 | + }; |
| 3475 | + |
| 3476 | + if (o->verbose) |
| 3477 | + fprintf_ln(stderr, _("Checking references consistency")); |
| 3478 | + return files_fsck_refs_dir(ref_store, o, "refs", fsck_refs_fn); |
| 3479 | +} |
| 3480 | + |
3411 | 3481 | static int files_fsck(struct ref_store *ref_store,
|
3412 | 3482 | struct fsck_options *o)
|
3413 | 3483 | {
|
3414 | 3484 | struct files_ref_store *refs =
|
3415 | 3485 | files_downcast(ref_store, REF_STORE_READ, "fsck");
|
3416 | 3486 |
|
3417 |
| - return refs->packed_ref_store->be->fsck(refs->packed_ref_store, o); |
| 3487 | + return files_fsck_refs(ref_store, o) | |
| 3488 | + refs->packed_ref_store->be->fsck(refs->packed_ref_store, o); |
3418 | 3489 | }
|
3419 | 3490 |
|
3420 | 3491 | struct ref_storage_be refs_be_files = {
|
|
0 commit comments