Files
git/lib/fsck.h
Patrick Steinhardt 9759608622 Move libgit.a sources into separate "lib/" directory
The Git project is not exactly the easiest project to get started in:
it's written in C and POSIX shell, with bits of Perl, Rust and other
languages sprinkled into it. On top of that, the project has grown
somewhat organically over time, making the codebase hard to navigate.

These are problems that we're aware of, and there have been and still
are efforts to clean up some of the technical debt that is natural to
exist an a project that is more than 20 years old. Furthermore, we
provide resources to newcomers that help them out like our coding
guidelines, code of conduct or "MyFirstContribution.adoc".

But there is a rather practical problem: finding your way around in our
project's tree is not easy. Doing a directory listing in the top-level
directory will present you with more than 550 files, which makes it
extremely hard for a newcomer to figure out what files they are even
supposed to look at. This makes the onboarding experience somewhat
harder than it really needs to be. This isn't only a problem for
newcomers though, as I myself struggle to find the files I am looking
for because of the sheer number of files.

Besides the problem of discoverability it also creates a problem of
structure. It is not obvious at all which files are part of "libgit.a"
and which files are only linked into our final executables. So while we
have this split in our build systems, that split is not evident at all
in our tree.

Introduce a new "lib/" directory and move all of our sources for
"libgit.a" into it to fix these issues. It makes the split we have
evident and reduces the number of files in our top-level tree from 550
files to ~80 files.

This is still a lot of files, but it's significantly easier to navigate
already. Furthermore, we can further iterate after this step and think
about introducing a better structure for remaining files, as well.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-22 10:58:23 -07:00

293 lines
8.6 KiB
C

#ifndef GIT_FSCK_H
#define GIT_FSCK_H
#include "object.h"
#include "oidset.h"
enum fsck_msg_type {
/* for internal use only */
FSCK_IGNORE,
FSCK_INFO,
FSCK_FATAL,
/* "public", fed to e.g. error_func callbacks */
FSCK_ERROR,
FSCK_WARN,
};
/*
* Documentation/fsck-msgids.adoc documents these; when
* modifying this list in any way, make sure to keep the
* two in sync.
*/
#define FOREACH_FSCK_MSG_ID(FUNC) \
/* fatal errors */ \
FUNC(NUL_IN_HEADER, FATAL) \
FUNC(UNTERMINATED_HEADER, FATAL) \
/* errors */ \
FUNC(BAD_HEADER_CONTINUATION, ERROR) \
FUNC(BAD_DATE, ERROR) \
FUNC(BAD_DATE_OVERFLOW, ERROR) \
FUNC(BAD_EMAIL, ERROR) \
FUNC(BAD_GPGSIG, ERROR) \
FUNC(BAD_HEAD_TARGET, ERROR) \
FUNC(BAD_NAME, ERROR) \
FUNC(BAD_OBJECT_SHA1, ERROR) \
FUNC(BAD_PACKED_REF_ENTRY, ERROR) \
FUNC(BAD_PACKED_REF_HEADER, ERROR) \
FUNC(BAD_PARENT_SHA1, ERROR) \
FUNC(BAD_REFERENT_NAME, ERROR) \
FUNC(BAD_REF_CONTENT, ERROR) \
FUNC(BAD_REF_FILETYPE, ERROR) \
FUNC(BAD_REF_NAME, ERROR) \
FUNC(BAD_REF_OID, ERROR) \
FUNC(BAD_TIMEZONE, ERROR) \
FUNC(BAD_TREE, ERROR) \
FUNC(BAD_TREE_SHA1, ERROR) \
FUNC(BAD_TYPE, ERROR) \
FUNC(DUPLICATE_ENTRIES, ERROR) \
FUNC(GITATTRIBUTES_BLOB, ERROR) \
FUNC(GITATTRIBUTES_LARGE, ERROR) \
FUNC(GITATTRIBUTES_LINE_LENGTH, ERROR) \
FUNC(GITATTRIBUTES_MISSING, ERROR) \
FUNC(GITMODULES_BLOB, ERROR) \
FUNC(GITMODULES_LARGE, ERROR) \
FUNC(GITMODULES_MISSING, ERROR) \
FUNC(GITMODULES_NAME, ERROR) \
FUNC(GITMODULES_PATH, ERROR) \
FUNC(GITMODULES_SYMLINK, ERROR) \
FUNC(GITMODULES_UPDATE, ERROR) \
FUNC(GITMODULES_URL, ERROR) \
FUNC(MISSING_AUTHOR, ERROR) \
FUNC(MISSING_COMMITTER, ERROR) \
FUNC(MISSING_EMAIL, ERROR) \
FUNC(MISSING_NAME_BEFORE_EMAIL, ERROR) \
FUNC(MISSING_OBJECT, ERROR) \
FUNC(MISSING_SPACE_BEFORE_DATE, ERROR) \
FUNC(MISSING_SPACE_BEFORE_EMAIL, ERROR) \
FUNC(MISSING_TAG, ERROR) \
FUNC(MISSING_TAG_ENTRY, ERROR) \
FUNC(MISSING_TREE, ERROR) \
FUNC(MISSING_TYPE, ERROR) \
FUNC(MISSING_TYPE_ENTRY, ERROR) \
FUNC(MULTIPLE_AUTHORS, ERROR) \
FUNC(PACKED_REF_ENTRY_NOT_TERMINATED, ERROR) \
FUNC(PACKED_REF_UNSORTED, ERROR) \
FUNC(TREE_NOT_SORTED, ERROR) \
FUNC(UNKNOWN_TYPE, ERROR) \
FUNC(ZERO_PADDED_DATE, ERROR) \
/* warnings */ \
FUNC(BAD_REFTABLE_TABLE_NAME, WARN) \
FUNC(EMPTY_NAME, WARN) \
FUNC(FULL_PATHNAME, WARN) \
FUNC(HAS_DOT, WARN) \
FUNC(HAS_DOTDOT, WARN) \
FUNC(HAS_DOTGIT, WARN) \
FUNC(LARGE_PATHNAME, WARN) \
FUNC(NULL_SHA1, WARN) \
FUNC(NUL_IN_COMMIT, WARN) \
FUNC(ZERO_PADDED_FILEMODE, WARN) \
/* infos (reported as warnings, but ignored by default) */ \
FUNC(BAD_FILEMODE, INFO) \
FUNC(BAD_TAG_NAME, INFO) \
FUNC(EMPTY_PACKED_REFS_FILE, INFO) \
FUNC(GITATTRIBUTES_SYMLINK, INFO) \
FUNC(GITIGNORE_SYMLINK, INFO) \
FUNC(GITMODULES_PARSE, INFO) \
FUNC(MAILMAP_SYMLINK, INFO) \
FUNC(MISSING_TAGGER_ENTRY, INFO) \
FUNC(REF_MISSING_NEWLINE, INFO) \
FUNC(SYMLINK_REF, INFO) \
FUNC(SYMREF_TARGET_IS_NOT_A_REF, INFO) \
FUNC(TRAILING_REF_CONTENT, INFO) \
/* ignored (elevated when requested) */ \
FUNC(EXTRA_HEADER_ENTRY, IGNORE)
#define MSG_ID(id, msg_type) FSCK_MSG_##id,
enum fsck_msg_id {
FOREACH_FSCK_MSG_ID(MSG_ID)
FSCK_MSG_MAX
};
#undef MSG_ID
struct fsck_options;
struct object;
void fsck_set_msg_type_from_ids(struct fsck_options *options,
enum fsck_msg_id msg_id,
enum fsck_msg_type msg_type);
void fsck_set_msg_type(struct fsck_options *options,
const char *msg_id, const char *msg_type);
void fsck_set_msg_types(struct fsck_options *options, const char *values);
int is_valid_msg_type(const char *msg_id, const char *msg_type);
/*
* callback function for fsck_walk
* type is the expected type of the object or OBJ_ANY
* the return value is:
* 0 everything OK
* <0 error signaled and abort
* >0 error signaled and do not abort
*/
typedef int (*fsck_walk_func)(struct object *obj, enum object_type object_type,
void *data, struct fsck_options *options);
/*
* Callback for reporting errors either for objects or refs. The "fsck_report"
* is a generic pointer that can be used to pass any information.
*/
typedef int (*fsck_error)(struct fsck_options *o,
void *fsck_report,
enum fsck_msg_type msg_type, enum fsck_msg_id msg_id,
const char *message);
int fsck_objects_error_function(struct fsck_options *o,
void *fsck_report,
enum fsck_msg_type msg_type, enum fsck_msg_id msg_id,
const char *message);
int fsck_objects_error_cb_print_missing_gitmodules(struct fsck_options *o,
void *fsck_report,
enum fsck_msg_type msg_type,
enum fsck_msg_id msg_id,
const char *message);
int fsck_refs_error_function(struct fsck_options *options,
void *fsck_report,
enum fsck_msg_type msg_type,
enum fsck_msg_id msg_id,
const char *message);
struct fsck_object_report {
const struct object_id *oid;
enum object_type object_type;
};
struct fsck_ref_report {
const char *path;
};
struct repository;
struct fsck_options {
struct repository *repo;
fsck_walk_func walk;
fsck_error error_func;
unsigned strict;
unsigned verbose;
enum fsck_msg_type *msg_type;
struct oidset skip_oids;
struct oidset gitmodules_found;
struct oidset gitmodules_done;
struct oidset gitattributes_found;
struct oidset gitattributes_done;
kh_oid_map_t *object_names;
};
/* descend in all linked child objects
* the return value is:
* -1 error in processing the object
* <0 return value of the callback, which lead to an abort
* >0 return value of the first signaled error >0 (in the case of no other errors)
* 0 everything OK
*/
int fsck_walk(struct object *obj, void *data, struct fsck_options *options);
/*
* Blob objects my pass a NULL data pointer, which indicates they are too large
* to fit in memory. All other types must pass a real buffer.
*/
int fsck_object(struct object *obj, void *data, unsigned long size,
struct fsck_options *options);
/*
* Same as fsck_object(), but for when the caller doesn't have an object
* struct.
*/
int fsck_buffer(const struct object_id *oid, enum object_type,
const void *data, unsigned long size,
struct fsck_options *options);
/*
* fsck a tag, and pass info about it back to the caller. This is
* exposed fsck_object() internals for git-mktag(1).
*/
int fsck_tag_standalone(const struct object_id *oid, const char *buffer,
unsigned long size, struct fsck_options *options,
struct object_id *tagged_oid,
int *tag_type);
/*
* Some fsck checks are context-dependent, and may end up queued; run this
* after completing all fsck_object() calls in order to resolve any remaining
* checks.
*/
int fsck_finish(struct fsck_options *options);
/*
* Check whether there are any checks that have been queued up and that still
* need to be run. Returns `false` iff `fsck_finish()` wouldn't perform any
* actions, `true` otherwise.
*/
bool fsck_has_queued_checks(struct fsck_options *options);
enum fsck_options_type {
FSCK_OPTIONS_DEFAULT,
FSCK_OPTIONS_STRICT,
FSCK_OPTIONS_MISSING_GITMODULES,
FSCK_OPTIONS_REFS,
};
void fsck_options_init(struct fsck_options *options,
struct repository *repo,
enum fsck_options_type type);
/*
* Clear the fsck_options struct, freeing any allocated memory.
*/
void fsck_options_clear(struct fsck_options *options);
/*
* Report an error or warning for refs.
*/
__attribute__((format (printf, 4, 5)))
int fsck_report_ref(struct fsck_options *options,
struct fsck_ref_report *report,
enum fsck_msg_id msg_id,
const char *fmt, ...);
/*
* Subsystem for storing human-readable names for each object.
*
* If fsck_enable_object_names() has not been called, all other functions are
* noops.
*
* Use fsck_put_object_name() to seed initial names (e.g. from refnames); the
* fsck code will extend that while walking trees, etc.
*
* Use fsck_get_object_name() to get a single name (or NULL if none). Or the
* more convenient describe_object(), which always produces an output string
* with the oid combined with the name (if any). Note that the return value
* points to a rotating array of static buffers, and may be invalidated by a
* subsequent call.
*/
void fsck_enable_object_names(struct fsck_options *options);
const char *fsck_get_object_name(struct fsck_options *options,
const struct object_id *oid);
__attribute__((format (printf,3,4)))
void fsck_put_object_name(struct fsck_options *options,
const struct object_id *oid,
const char *fmt, ...);
const char *fsck_describe_object(struct fsck_options *options,
const struct object_id *oid);
struct key_value_info;
/*
* repo_config() callback for use by fsck-y tools that want to support
* fsck.<msg> fsck.skipList etc.
*/
int git_fsck_config(const char *var, const char *value,
const struct config_context *ctx, void *cb);
#endif