odb: provide infrastructure for pluggable fsck checks
The on-disk consistency checks in git-fsck(1) are conceptually backend-specific: while connectivity checks and object-level parsing checks are generic, verifying the physical integrity of packfiles and loose objects is meaningful only to backends that use these formats: Having these checks live in "builtin/fsck.c" violates that layering, because it forces the command to reach directly into format-specific internals. Provide new infrastructure to make these format-specific checks pluggable and implement stubs for the different source types we already have. In subsequent commits we'll move functionality over piece by piece. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>main
parent
485f5aeb94
commit
a51b77aa1d
|
|
@ -965,7 +965,9 @@ int cmd_fsck(int argc,
|
|||
const char *prefix,
|
||||
struct repository *repo)
|
||||
{
|
||||
int check_full = 1;
|
||||
struct odb_fsck_options odb_fsck_opts = {
|
||||
.flags = ODB_FSCK_FULL,
|
||||
};
|
||||
int keep_cache_objects = 0;
|
||||
int name_objects = 0;
|
||||
int check_references = 1;
|
||||
|
|
@ -977,7 +979,8 @@ int cmd_fsck(int argc,
|
|||
OPT_BOOL(0, "root", &show_root, N_("report root nodes")),
|
||||
OPT_BOOL(0, "cache", &keep_cache_objects, N_("make index objects head nodes")),
|
||||
OPT_BOOL(0, "reflogs", &include_reflogs, N_("make reflogs head nodes (default)")),
|
||||
OPT_BOOL(0, "full", &check_full, N_("also consider packs and alternate objects")),
|
||||
OPT_BIT(0, "full", &odb_fsck_opts.flags,
|
||||
N_("also consider packs and alternate objects"), ODB_FSCK_FULL),
|
||||
OPT_BOOL(0, "connectivity-only", &connectivity_only, N_("check only connectivity")),
|
||||
OPT_BOOL(0, "strict", &check_strict, N_("enable more strict checking")),
|
||||
OPT_BOOL(0, "lost-found", &write_lost_and_found,
|
||||
|
|
@ -1018,7 +1021,7 @@ int cmd_fsck(int argc,
|
|||
show_progress = 0;
|
||||
|
||||
if (write_lost_and_found) {
|
||||
check_full = 1;
|
||||
odb_fsck_opts.flags |= ODB_FSCK_FULL;
|
||||
include_reflogs = 0;
|
||||
}
|
||||
|
||||
|
|
@ -1047,10 +1050,13 @@ int cmd_fsck(int argc,
|
|||
mark_object_for_connectivity, repo, 0);
|
||||
} else {
|
||||
for (source = repo->objects->sources; source; source = source->next)
|
||||
if (check_full || source->local)
|
||||
if ((odb_fsck_opts.flags & ODB_FSCK_FULL) || source->local)
|
||||
fsck_source(repo, source);
|
||||
|
||||
if (check_full) {
|
||||
if (odb_fsck(repo->objects, &odb_fsck_opts) < 0)
|
||||
errors_found |= ERROR_OBJECT;
|
||||
|
||||
if (odb_fsck_opts.flags & ODB_FSCK_FULL) {
|
||||
struct packed_git *p;
|
||||
uint32_t total = 0, count = 0;
|
||||
struct progress *progress = NULL;
|
||||
|
|
|
|||
8
odb.c
8
odb.c
|
|
@ -1177,3 +1177,11 @@ void odb_reprepare(struct object_database *o)
|
|||
{
|
||||
odb_prepare(o, ODB_PREPARE_FLUSH_CACHES);
|
||||
}
|
||||
|
||||
int odb_fsck(struct object_database *odb, struct odb_fsck_options *options)
|
||||
{
|
||||
int ret = 0;
|
||||
for (struct odb_source *source = odb->sources; source; source = source->next)
|
||||
ret |= odb_source_fsck(source, options);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
23
odb.h
23
odb.h
|
|
@ -206,6 +206,29 @@ void odb_prepare(struct object_database *o, enum odb_prepare_flags flags);
|
|||
/* Equivalent to `odb_prepare(o, ODB_PREPARE_FLUSH_CACHES)`. */
|
||||
void odb_reprepare(struct object_database *o);
|
||||
|
||||
enum odb_fsck_flags {
|
||||
/*
|
||||
* If set, perform a full consistency check for the full object
|
||||
* database, including all of its sources and the contents of their
|
||||
* optimized formats. Otherwise, only check the local source, and
|
||||
* restrict checks of its optimized formats to cheap structural
|
||||
* verification of their metadata.
|
||||
*/
|
||||
ODB_FSCK_FULL = (1 << 0),
|
||||
};
|
||||
|
||||
/* Options that shall be passed to `odb_fsck()`. */
|
||||
struct odb_fsck_options {
|
||||
enum odb_fsck_flags flags;
|
||||
};
|
||||
|
||||
/*
|
||||
* Run backend-specific integrity checks on all object sources. Each source
|
||||
* performs the checks appropriate to its type. Returns 0 on success, a
|
||||
* negative error code otherwise.
|
||||
*/
|
||||
int odb_fsck(struct object_database *odb, struct odb_fsck_options *opts);
|
||||
|
||||
/*
|
||||
* Find source by its object directory path. Returns a `NULL` pointer in case
|
||||
* the source could not be found.
|
||||
|
|
|
|||
|
|
@ -893,6 +893,21 @@ static int odb_source_files_generate_pack(struct odb_source *source UNUSED,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int odb_source_files_fsck(struct odb_source *source,
|
||||
struct odb_fsck_options *opts)
|
||||
{
|
||||
struct odb_source_files *files = odb_source_files_downcast(source);
|
||||
int ret = 0;
|
||||
|
||||
if (!(opts->flags & ODB_FSCK_FULL) && !source->local)
|
||||
return 0;
|
||||
|
||||
ret |= odb_source_fsck(&files->loose->base, opts);
|
||||
ret |= odb_source_fsck(&files->packed->base, opts);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct odb_source_files *odb_source_files_new(struct object_database *odb,
|
||||
const char *path,
|
||||
bool local)
|
||||
|
|
@ -908,6 +923,7 @@ struct odb_source_files *odb_source_files_new(struct object_database *odb,
|
|||
files->base.close = odb_source_files_close;
|
||||
files->base.create_on_disk = odb_source_files_create_on_disk;
|
||||
files->base.prepare = odb_source_files_prepare;
|
||||
files->base.fsck = odb_source_files_fsck;
|
||||
files->base.read_object_info = odb_source_files_read_object_info;
|
||||
files->base.read_object_stream = odb_source_files_read_object_stream;
|
||||
files->base.for_each_object = odb_source_files_for_each_object;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include "git-compat-util.h"
|
||||
#include "object-file.h"
|
||||
#include "odb.h"
|
||||
#include "fsck.h"
|
||||
#include "odb/source-inmemory.h"
|
||||
#include "odb/streaming.h"
|
||||
#include "oidtree.h"
|
||||
|
|
@ -368,6 +369,12 @@ static void odb_source_inmemory_free(struct odb_source *source)
|
|||
free(inmemory);
|
||||
}
|
||||
|
||||
static int odb_source_inmemory_fsck(struct odb_source *source UNUSED,
|
||||
struct odb_fsck_options *opts UNUSED)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct odb_source_inmemory *odb_source_inmemory_new(struct object_database *odb)
|
||||
{
|
||||
struct odb_source_inmemory *source;
|
||||
|
|
@ -378,6 +385,7 @@ struct odb_source_inmemory *odb_source_inmemory_new(struct object_database *odb)
|
|||
source->base.free = odb_source_inmemory_free;
|
||||
source->base.close = odb_source_inmemory_close;
|
||||
source->base.prepare = odb_source_inmemory_prepare;
|
||||
source->base.fsck = odb_source_inmemory_fsck;
|
||||
source->base.read_object_info = odb_source_inmemory_read_object_info;
|
||||
source->base.read_object_stream = odb_source_inmemory_read_object_stream;
|
||||
source->base.for_each_object = odb_source_inmemory_for_each_object;
|
||||
|
|
|
|||
|
|
@ -1031,6 +1031,12 @@ static void odb_source_loose_free(struct odb_source *source)
|
|||
free(loose);
|
||||
}
|
||||
|
||||
static int odb_source_loose_fsck(struct odb_source *source UNUSED,
|
||||
struct odb_fsck_options *opts UNUSED)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct odb_source_loose *odb_source_loose_new(struct object_database *odb,
|
||||
const char *path,
|
||||
bool local)
|
||||
|
|
@ -1043,6 +1049,7 @@ struct odb_source_loose *odb_source_loose_new(struct object_database *odb,
|
|||
loose->base.free = odb_source_loose_free;
|
||||
loose->base.close = odb_source_loose_close;
|
||||
loose->base.prepare = odb_source_loose_prepare;
|
||||
loose->base.fsck = odb_source_loose_fsck;
|
||||
loose->base.read_object_info = odb_source_loose_read_object_info;
|
||||
loose->base.read_object_stream = odb_source_loose_read_object_stream;
|
||||
loose->base.for_each_object = odb_source_loose_for_each_object;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#include "abspath.h"
|
||||
#include "chdir-notify.h"
|
||||
#include "dir.h"
|
||||
#include "fsck.h"
|
||||
#include "git-zlib.h"
|
||||
#include "list-objects-filter-options.h"
|
||||
#include "mergesort.h"
|
||||
|
|
@ -826,6 +827,12 @@ static void odb_source_packed_free(struct odb_source *source)
|
|||
free(packed);
|
||||
}
|
||||
|
||||
static int odb_source_packed_fsck(struct odb_source *source UNUSED,
|
||||
struct odb_fsck_options *opts UNUSED)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct odb_source_packed *odb_source_packed_new(struct object_database *odb,
|
||||
const char *path,
|
||||
bool local)
|
||||
|
|
@ -839,6 +846,7 @@ struct odb_source_packed *odb_source_packed_new(struct object_database *odb,
|
|||
packed->base.free = odb_source_packed_free;
|
||||
packed->base.close = odb_source_packed_close;
|
||||
packed->base.prepare = odb_source_packed_prepare;
|
||||
packed->base.fsck = odb_source_packed_fsck;
|
||||
packed->base.read_object_info = odb_source_packed_read_object_info;
|
||||
packed->base.read_object_stream = odb_source_packed_read_object_stream;
|
||||
packed->base.for_each_object = odb_source_packed_for_each_object;
|
||||
|
|
|
|||
21
odb/source.h
21
odb/source.h
|
|
@ -320,6 +320,17 @@ struct odb_source {
|
|||
int (*generate_pack)(struct odb_source *source,
|
||||
struct odb_pack_generator **out,
|
||||
const struct odb_generate_pack_options *opts);
|
||||
|
||||
/*
|
||||
* This callback is expected to check the integrity of the object source
|
||||
* and report any errors found via the fsck options. The checks performed
|
||||
* are backend-specific.
|
||||
*
|
||||
* The callback is expected to return 0 on success, a negative error
|
||||
* code otherwise.
|
||||
*/
|
||||
int (*fsck)(struct odb_source *source,
|
||||
struct odb_fsck_options *options);
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -588,4 +599,14 @@ static inline int odb_source_generate_pack(struct odb_source *source,
|
|||
return source->generate_pack(source, out, opts);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check the integrity of the object database source. The checks performed
|
||||
* are backend-specific. Returns 0 on success, a negative error code otherwise.
|
||||
*/
|
||||
static inline int odb_source_fsck(struct odb_source *source,
|
||||
struct odb_fsck_options *opts)
|
||||
{
|
||||
return source->fsck(source, opts);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in New Issue