Merge branch 'ab/fsck-api-cleanup'

Fsck API clean-up.

* ab/fsck-api-cleanup:
  fetch-pack: use new fsck API to printing dangling submodules
  fetch-pack: use file-scope static struct for fsck_options
  fetch-pack: don't needlessly copy fsck_options
  fsck.c: move gitmodules_{found,done} into fsck_options
  fsck.c: add an fsck_set_msg_type() API that takes enums
  fsck.c: pass along the fsck_msg_id in the fsck_error callback
  fsck.[ch]: move FOREACH_FSCK_MSG_ID & fsck_msg_id from *.c to *.h
  fsck.c: give "FOREACH_MSG_ID" a more specific name
  fsck.c: undefine temporary STR macro after use
  fsck.c: call parse_msg_type() early in fsck_set_msg_type()
  fsck.h: re-order and re-assign "enum fsck_msg_type"
  fsck.h: move FSCK_{FATAL,INFO,ERROR,WARN,IGNORE} into an enum
  fsck.c: refactor fsck_msg_type() to limit scope of "int msg_type"
  fsck.c: rename remaining fsck_msg_id "id" to "msg_id"
  fsck.c: remove (mostly) redundant append_msg_id() function
  fsck.c: rename variables in fsck_set_msg_type() for less confusion
  fsck.h: use "enum object_type" instead of "int"
  fsck.h: use designed initializers for FSCK_OPTIONS_{DEFAULT,STRICT}
  fsck.c: refactor and rename common config callback
This commit is contained in:
Junio C Hamano
2021-04-07 16:54:09 -07:00
7 changed files with 210 additions and 216 deletions

View File

@ -71,11 +71,6 @@ static const char *printable_type(const struct object_id *oid,
return ret; return ret;
} }
static int fsck_config(const char *var, const char *value, void *cb)
{
return fsck_config_internal(var, value, cb, &fsck_obj_options);
}
static int objerror(struct object *obj, const char *err) static int objerror(struct object *obj, const char *err)
{ {
errors_found |= ERROR_OBJECT; errors_found |= ERROR_OBJECT;
@ -89,7 +84,9 @@ static int objerror(struct object *obj, const char *err)
static int fsck_error_func(struct fsck_options *o, static int fsck_error_func(struct fsck_options *o,
const struct object_id *oid, const struct object_id *oid,
enum object_type object_type, enum object_type object_type,
int msg_type, const char *message) enum fsck_msg_type msg_type,
enum fsck_msg_id msg_id,
const char *message)
{ {
switch (msg_type) { switch (msg_type) {
case FSCK_WARN: case FSCK_WARN:
@ -197,7 +194,8 @@ static int traverse_reachable(void)
return !!result; return !!result;
} }
static int mark_used(struct object *obj, int type, void *data, struct fsck_options *options) static int mark_used(struct object *obj, enum object_type object_type,
void *data, struct fsck_options *options)
{ {
if (!obj) if (!obj)
return 1; return 1;
@ -803,7 +801,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
if (name_objects) if (name_objects)
fsck_enable_object_names(&fsck_walk_options); fsck_enable_object_names(&fsck_walk_options);
git_config(fsck_config, NULL); git_config(git_fsck_config, &fsck_obj_options);
if (connectivity_only) { if (connectivity_only) {
for_each_loose_object(mark_loose_for_connectivity, NULL, 0); for_each_loose_object(mark_loose_for_connectivity, NULL, 0);

View File

@ -120,7 +120,7 @@ static int nr_threads;
static int from_stdin; static int from_stdin;
static int strict; static int strict;
static int do_fsck_object; static int do_fsck_object;
static struct fsck_options fsck_options = FSCK_OPTIONS_STRICT; static struct fsck_options fsck_options = FSCK_OPTIONS_MISSING_GITMODULES;
static int verbose; static int verbose;
static int show_resolving_progress; static int show_resolving_progress;
static int show_stat; static int show_stat;
@ -212,7 +212,8 @@ static void cleanup_thread(void)
free(thread_data); free(thread_data);
} }
static int mark_link(struct object *obj, int type, void *data, struct fsck_options *options) static int mark_link(struct object *obj, enum object_type type,
void *data, struct fsck_options *options)
{ {
if (!obj) if (!obj)
return -1; return -1;
@ -1712,22 +1713,6 @@ static void show_pack_info(int stat_only)
} }
} }
static int print_dangling_gitmodules(struct fsck_options *o,
const struct object_id *oid,
enum object_type object_type,
int msg_type, const char *message)
{
/*
* NEEDSWORK: Plumb the MSG_ID (from fsck.c) here and use it
* instead of relying on this string check.
*/
if (starts_with(message, "gitmodulesMissing")) {
printf("%s\n", oid_to_hex(oid));
return 0;
}
return fsck_error_function(o, oid, object_type, msg_type, message);
}
int cmd_index_pack(int argc, const char **argv, const char *prefix) int cmd_index_pack(int argc, const char **argv, const char *prefix)
{ {
int i, fix_thin_pack = 0, verify = 0, stat_only = 0, rev_index; int i, fix_thin_pack = 0, verify = 0, stat_only = 0, rev_index;
@ -1948,13 +1933,8 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
else else
close(input_fd); close(input_fd);
if (do_fsck_object) { if (do_fsck_object && fsck_finish(&fsck_options))
struct fsck_options fo = fsck_options; die(_("fsck error in pack objects"));
fo.error_func = print_dangling_gitmodules;
if (fsck_finish(&fo))
die(_("fsck error in pack objects"));
}
free(objects); free(objects);
strbuf_release(&index_name_buf); strbuf_release(&index_name_buf);

View File

@ -14,15 +14,12 @@ static int option_strict = 1;
static struct fsck_options fsck_options = FSCK_OPTIONS_STRICT; static struct fsck_options fsck_options = FSCK_OPTIONS_STRICT;
static int mktag_config(const char *var, const char *value, void *cb)
{
return fsck_config_internal(var, value, cb, &fsck_options);
}
static int mktag_fsck_error_func(struct fsck_options *o, static int mktag_fsck_error_func(struct fsck_options *o,
const struct object_id *oid, const struct object_id *oid,
enum object_type object_type, enum object_type object_type,
int msg_type, const char *message) enum fsck_msg_type msg_type,
enum fsck_msg_id msg_id,
const char *message)
{ {
switch (msg_type) { switch (msg_type) {
case FSCK_WARN: case FSCK_WARN:
@ -91,9 +88,10 @@ int cmd_mktag(int argc, const char **argv, const char *prefix)
die_errno(_("could not read from stdin")); die_errno(_("could not read from stdin"));
fsck_options.error_func = mktag_fsck_error_func; fsck_options.error_func = mktag_fsck_error_func;
fsck_set_msg_type(&fsck_options, "extraheaderentry", "warn"); fsck_set_msg_type_from_ids(&fsck_options, FSCK_MSG_EXTRA_HEADER_ENTRY,
FSCK_WARN);
/* config might set fsck.extraHeaderEntry=* again */ /* config might set fsck.extraHeaderEntry=* again */
git_config(mktag_config, NULL); git_config(git_fsck_config, &fsck_options);
if (fsck_tag_standalone(NULL, buf.buf, buf.len, &fsck_options, if (fsck_tag_standalone(NULL, buf.buf, buf.len, &fsck_options,
&tagged_oid, &tagged_type)) &tagged_oid, &tagged_type))
die(_("tag on stdin did not pass our strict fsck check")); die(_("tag on stdin did not pass our strict fsck check"));

View File

@ -187,7 +187,8 @@ static void write_cached_object(struct object *obj, struct obj_buffer *obj_buf)
* that have reachability requirements and calls this function. * that have reachability requirements and calls this function.
* Verify its reachability and validity recursively and write it out. * Verify its reachability and validity recursively and write it out.
*/ */
static int check_object(struct object *obj, int type, void *data, struct fsck_options *options) static int check_object(struct object *obj, enum object_type type,
void *data, struct fsck_options *options)
{ {
struct obj_buffer *obj_buf; struct obj_buffer *obj_buf;

View File

@ -38,6 +38,7 @@ static int server_supports_filtering;
static int advertise_sid; static int advertise_sid;
static struct shallow_lock shallow_lock; static struct shallow_lock shallow_lock;
static const char *alternate_shallow_file; static const char *alternate_shallow_file;
static struct fsck_options fsck_options = FSCK_OPTIONS_MISSING_GITMODULES;
static struct strbuf fsck_msg_types = STRBUF_INIT; static struct strbuf fsck_msg_types = STRBUF_INIT;
static struct string_list uri_protocols = STRING_LIST_INIT_DUP; static struct string_list uri_protocols = STRING_LIST_INIT_DUP;
@ -987,22 +988,6 @@ static int cmp_ref_by_name(const void *a_, const void *b_)
return strcmp(a->name, b->name); return strcmp(a->name, b->name);
} }
static void fsck_gitmodules_oids(struct oidset *gitmodules_oids)
{
struct oidset_iter iter;
const struct object_id *oid;
struct fsck_options fo = FSCK_OPTIONS_STRICT;
if (!oidset_size(gitmodules_oids))
return;
oidset_iter_init(gitmodules_oids, &iter);
while ((oid = oidset_iter_next(&iter)))
register_found_gitmodules(oid);
if (fsck_finish(&fo))
die("fsck failed");
}
static struct ref *do_fetch_pack(struct fetch_pack_args *args, static struct ref *do_fetch_pack(struct fetch_pack_args *args,
int fd[2], int fd[2],
const struct ref *orig_ref, const struct ref *orig_ref,
@ -1017,7 +1002,6 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
int agent_len; int agent_len;
struct fetch_negotiator negotiator_alloc; struct fetch_negotiator negotiator_alloc;
struct fetch_negotiator *negotiator; struct fetch_negotiator *negotiator;
struct oidset gitmodules_oids = OIDSET_INIT;
negotiator = &negotiator_alloc; negotiator = &negotiator_alloc;
fetch_negotiator_init(r, negotiator); fetch_negotiator_init(r, negotiator);
@ -1134,9 +1118,10 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
else else
alternate_shallow_file = NULL; alternate_shallow_file = NULL;
if (get_pack(args, fd, pack_lockfiles, NULL, sought, nr_sought, if (get_pack(args, fd, pack_lockfiles, NULL, sought, nr_sought,
&gitmodules_oids)) &fsck_options.gitmodules_found))
die(_("git fetch-pack: fetch failed.")); die(_("git fetch-pack: fetch failed."));
fsck_gitmodules_oids(&gitmodules_oids); if (fsck_finish(&fsck_options))
die("fsck failed");
all_done: all_done:
if (negotiator) if (negotiator)
@ -1587,7 +1572,6 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
struct string_list packfile_uris = STRING_LIST_INIT_DUP; struct string_list packfile_uris = STRING_LIST_INIT_DUP;
int i; int i;
struct strvec index_pack_args = STRVEC_INIT; struct strvec index_pack_args = STRVEC_INIT;
struct oidset gitmodules_oids = OIDSET_INIT;
negotiator = &negotiator_alloc; negotiator = &negotiator_alloc;
fetch_negotiator_init(r, negotiator); fetch_negotiator_init(r, negotiator);
@ -1678,7 +1662,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
process_section_header(&reader, "packfile", 0); process_section_header(&reader, "packfile", 0);
if (get_pack(args, fd, pack_lockfiles, if (get_pack(args, fd, pack_lockfiles,
packfile_uris.nr ? &index_pack_args : NULL, packfile_uris.nr ? &index_pack_args : NULL,
sought, nr_sought, &gitmodules_oids)) sought, nr_sought, &fsck_options.gitmodules_found))
die(_("git fetch-pack: fetch failed.")); die(_("git fetch-pack: fetch failed."));
do_check_stateless_delimiter(args, &reader); do_check_stateless_delimiter(args, &reader);
@ -1721,7 +1705,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
packname[the_hash_algo->hexsz] = '\0'; packname[the_hash_algo->hexsz] = '\0';
parse_gitmodules_oids(cmd.out, &gitmodules_oids); parse_gitmodules_oids(cmd.out, &fsck_options.gitmodules_found);
close(cmd.out); close(cmd.out);
@ -1742,7 +1726,8 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
string_list_clear(&packfile_uris, 0); string_list_clear(&packfile_uris, 0);
strvec_clear(&index_pack_args); strvec_clear(&index_pack_args);
fsck_gitmodules_oids(&gitmodules_oids); if (fsck_finish(&fsck_options))
die("fsck failed");
if (negotiator) if (negotiator)
negotiator->release(negotiator); negotiator->release(negotiator);

207
fsck.c
View File

@ -19,90 +19,19 @@
#include "credential.h" #include "credential.h"
#include "help.h" #include "help.h"
static struct oidset gitmodules_found = OIDSET_INIT;
static struct oidset gitmodules_done = OIDSET_INIT;
#define FSCK_FATAL -1
#define FSCK_INFO -2
#define FOREACH_MSG_ID(FUNC) \
/* fatal errors */ \
FUNC(NUL_IN_HEADER, FATAL) \
FUNC(UNTERMINATED_HEADER, FATAL) \
/* errors */ \
FUNC(BAD_DATE, ERROR) \
FUNC(BAD_DATE_OVERFLOW, ERROR) \
FUNC(BAD_EMAIL, ERROR) \
FUNC(BAD_NAME, ERROR) \
FUNC(BAD_OBJECT_SHA1, ERROR) \
FUNC(BAD_PARENT_SHA1, ERROR) \
FUNC(BAD_TAG_OBJECT, ERROR) \
FUNC(BAD_TIMEZONE, ERROR) \
FUNC(BAD_TREE, ERROR) \
FUNC(BAD_TREE_SHA1, ERROR) \
FUNC(BAD_TYPE, ERROR) \
FUNC(DUPLICATE_ENTRIES, 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_TREE_OBJECT, ERROR) \
FUNC(MISSING_TYPE, ERROR) \
FUNC(MISSING_TYPE_ENTRY, ERROR) \
FUNC(MULTIPLE_AUTHORS, ERROR) \
FUNC(TREE_NOT_SORTED, ERROR) \
FUNC(UNKNOWN_TYPE, ERROR) \
FUNC(ZERO_PADDED_DATE, ERROR) \
FUNC(GITMODULES_MISSING, ERROR) \
FUNC(GITMODULES_BLOB, ERROR) \
FUNC(GITMODULES_LARGE, ERROR) \
FUNC(GITMODULES_NAME, ERROR) \
FUNC(GITMODULES_SYMLINK, ERROR) \
FUNC(GITMODULES_URL, ERROR) \
FUNC(GITMODULES_PATH, ERROR) \
FUNC(GITMODULES_UPDATE, ERROR) \
/* warnings */ \
FUNC(BAD_FILEMODE, WARN) \
FUNC(EMPTY_NAME, WARN) \
FUNC(FULL_PATHNAME, WARN) \
FUNC(HAS_DOT, WARN) \
FUNC(HAS_DOTDOT, WARN) \
FUNC(HAS_DOTGIT, WARN) \
FUNC(NULL_SHA1, WARN) \
FUNC(ZERO_PADDED_FILEMODE, WARN) \
FUNC(NUL_IN_COMMIT, WARN) \
/* infos (reported as warnings, but ignored by default) */ \
FUNC(GITMODULES_PARSE, INFO) \
FUNC(BAD_TAG_NAME, INFO) \
FUNC(MISSING_TAGGER_ENTRY, INFO) \
/* ignored (elevated when requested) */ \
FUNC(EXTRA_HEADER_ENTRY, IGNORE)
#define MSG_ID(id, msg_type) FSCK_MSG_##id,
enum fsck_msg_id {
FOREACH_MSG_ID(MSG_ID)
FSCK_MSG_MAX
};
#undef MSG_ID
#define STR(x) #x #define STR(x) #x
#define MSG_ID(id, msg_type) { STR(id), NULL, NULL, FSCK_##msg_type }, #define MSG_ID(id, msg_type) { STR(id), NULL, NULL, FSCK_##msg_type },
static struct { static struct {
const char *id_string; const char *id_string;
const char *downcased; const char *downcased;
const char *camelcased; const char *camelcased;
int msg_type; enum fsck_msg_type msg_type;
} msg_id_info[FSCK_MSG_MAX + 1] = { } msg_id_info[FSCK_MSG_MAX + 1] = {
FOREACH_MSG_ID(MSG_ID) FOREACH_FSCK_MSG_ID(MSG_ID)
{ NULL, NULL, NULL, -1 } { NULL, NULL, NULL, -1 }
}; };
#undef MSG_ID #undef MSG_ID
#undef STR
static void prepare_msg_ids(void) static void prepare_msg_ids(void)
{ {
@ -164,25 +93,23 @@ void list_config_fsck_msg_ids(struct string_list *list, const char *prefix)
list_config_item(list, prefix, msg_id_info[i].camelcased); list_config_item(list, prefix, msg_id_info[i].camelcased);
} }
static int fsck_msg_type(enum fsck_msg_id msg_id, static enum fsck_msg_type fsck_msg_type(enum fsck_msg_id msg_id,
struct fsck_options *options) struct fsck_options *options)
{ {
int msg_type;
assert(msg_id >= 0 && msg_id < FSCK_MSG_MAX); assert(msg_id >= 0 && msg_id < FSCK_MSG_MAX);
if (options->msg_type) if (!options->msg_type) {
msg_type = options->msg_type[msg_id]; enum fsck_msg_type msg_type = msg_id_info[msg_id].msg_type;
else {
msg_type = msg_id_info[msg_id].msg_type;
if (options->strict && msg_type == FSCK_WARN) if (options->strict && msg_type == FSCK_WARN)
msg_type = FSCK_ERROR; msg_type = FSCK_ERROR;
return msg_type;
} }
return msg_type; return options->msg_type[msg_id];
} }
static int parse_msg_type(const char *str) static enum fsck_msg_type parse_msg_type(const char *str)
{ {
if (!strcmp(str, "error")) if (!strcmp(str, "error"))
return FSCK_ERROR; return FSCK_ERROR;
@ -202,28 +129,35 @@ int is_valid_msg_type(const char *msg_id, const char *msg_type)
return 1; return 1;
} }
void fsck_set_msg_type(struct fsck_options *options, void fsck_set_msg_type_from_ids(struct fsck_options *options,
const char *msg_id, const char *msg_type) enum fsck_msg_id msg_id,
enum fsck_msg_type msg_type)
{ {
int id = parse_msg_id(msg_id), type;
if (id < 0)
die("Unhandled message id: %s", msg_id);
type = parse_msg_type(msg_type);
if (type != FSCK_ERROR && msg_id_info[id].msg_type == FSCK_FATAL)
die("Cannot demote %s to %s", msg_id, msg_type);
if (!options->msg_type) { if (!options->msg_type) {
int i; int i;
int *msg_type; enum fsck_msg_type *severity;
ALLOC_ARRAY(msg_type, FSCK_MSG_MAX); ALLOC_ARRAY(severity, FSCK_MSG_MAX);
for (i = 0; i < FSCK_MSG_MAX; i++) for (i = 0; i < FSCK_MSG_MAX; i++)
msg_type[i] = fsck_msg_type(i, options); severity[i] = fsck_msg_type(i, options);
options->msg_type = msg_type; options->msg_type = severity;
} }
options->msg_type[id] = type; options->msg_type[msg_id] = msg_type;
}
void fsck_set_msg_type(struct fsck_options *options,
const char *msg_id_str, const char *msg_type_str)
{
int msg_id = parse_msg_id(msg_id_str);
enum fsck_msg_type msg_type = parse_msg_type(msg_type_str);
if (msg_id < 0)
die("Unhandled message id: %s", msg_id_str);
if (msg_type != FSCK_ERROR && msg_id_info[msg_id].msg_type == FSCK_FATAL)
die("Cannot demote %s to %s", msg_id_str, msg_type_str);
fsck_set_msg_type_from_ids(options, msg_id, msg_type);
} }
void fsck_set_msg_types(struct fsck_options *options, const char *values) void fsck_set_msg_types(struct fsck_options *options, const char *values)
@ -264,24 +198,6 @@ void fsck_set_msg_types(struct fsck_options *options, const char *values)
free(to_free); free(to_free);
} }
static void append_msg_id(struct strbuf *sb, const char *msg_id)
{
for (;;) {
char c = *(msg_id)++;
if (!c)
break;
if (c != '_')
strbuf_addch(sb, tolower(c));
else {
assert(*msg_id);
strbuf_addch(sb, *(msg_id)++);
}
}
strbuf_addstr(sb, ": ");
}
static int object_on_skiplist(struct fsck_options *opts, static int object_on_skiplist(struct fsck_options *opts,
const struct object_id *oid) const struct object_id *oid)
{ {
@ -291,11 +207,12 @@ static int object_on_skiplist(struct fsck_options *opts,
__attribute__((format (printf, 5, 6))) __attribute__((format (printf, 5, 6)))
static int report(struct fsck_options *options, static int report(struct fsck_options *options,
const struct object_id *oid, enum object_type object_type, const struct object_id *oid, enum object_type object_type,
enum fsck_msg_id id, const char *fmt, ...) enum fsck_msg_id msg_id, const char *fmt, ...)
{ {
va_list ap; va_list ap;
struct strbuf sb = STRBUF_INIT; struct strbuf sb = STRBUF_INIT;
int msg_type = fsck_msg_type(id, options), result; enum fsck_msg_type msg_type = fsck_msg_type(msg_id, options);
int result;
if (msg_type == FSCK_IGNORE) if (msg_type == FSCK_IGNORE)
return 0; return 0;
@ -308,12 +225,13 @@ static int report(struct fsck_options *options,
else if (msg_type == FSCK_INFO) else if (msg_type == FSCK_INFO)
msg_type = FSCK_WARN; msg_type = FSCK_WARN;
append_msg_id(&sb, msg_id_info[id].id_string); prepare_msg_ids();
strbuf_addf(&sb, "%s: ", msg_id_info[msg_id].camelcased);
va_start(ap, fmt); va_start(ap, fmt);
strbuf_vaddf(&sb, fmt, ap); strbuf_vaddf(&sb, fmt, ap);
result = options->error_func(options, oid, object_type, result = options->error_func(options, oid, object_type,
msg_type, sb.buf); msg_type, msg_id, sb.buf);
strbuf_release(&sb); strbuf_release(&sb);
va_end(ap); va_end(ap);
@ -685,7 +603,7 @@ static int fsck_tree(const struct object_id *oid,
if (is_hfs_dotgitmodules(name) || is_ntfs_dotgitmodules(name)) { if (is_hfs_dotgitmodules(name) || is_ntfs_dotgitmodules(name)) {
if (!S_ISLNK(mode)) if (!S_ISLNK(mode))
oidset_insert(&gitmodules_found, oid); oidset_insert(&options->gitmodules_found, oid);
else else
retval += report(options, retval += report(options,
oid, OBJ_TREE, oid, OBJ_TREE,
@ -699,7 +617,7 @@ static int fsck_tree(const struct object_id *oid,
has_dotgit |= is_ntfs_dotgit(backslash); has_dotgit |= is_ntfs_dotgit(backslash);
if (is_ntfs_dotgitmodules(backslash)) { if (is_ntfs_dotgitmodules(backslash)) {
if (!S_ISLNK(mode)) if (!S_ISLNK(mode))
oidset_insert(&gitmodules_found, oid); oidset_insert(&options->gitmodules_found, oid);
else else
retval += report(options, oid, OBJ_TREE, retval += report(options, oid, OBJ_TREE,
FSCK_MSG_GITMODULES_SYMLINK, FSCK_MSG_GITMODULES_SYMLINK,
@ -1211,9 +1129,9 @@ static int fsck_blob(const struct object_id *oid, const char *buf,
struct fsck_gitmodules_data data; struct fsck_gitmodules_data data;
struct config_options config_opts = { 0 }; struct config_options config_opts = { 0 };
if (!oidset_contains(&gitmodules_found, oid)) if (!oidset_contains(&options->gitmodules_found, oid))
return 0; return 0;
oidset_insert(&gitmodules_done, oid); oidset_insert(&options->gitmodules_done, oid);
if (object_on_skiplist(options, oid)) if (object_on_skiplist(options, oid))
return 0; return 0;
@ -1266,7 +1184,9 @@ int fsck_object(struct object *obj, void *data, unsigned long size,
int fsck_error_function(struct fsck_options *o, int fsck_error_function(struct fsck_options *o,
const struct object_id *oid, const struct object_id *oid,
enum object_type object_type, enum object_type object_type,
int msg_type, const char *message) enum fsck_msg_type msg_type,
enum fsck_msg_id msg_id,
const char *message)
{ {
if (msg_type == FSCK_WARN) { if (msg_type == FSCK_WARN) {
warning("object %s: %s", fsck_describe_object(o, oid), message); warning("object %s: %s", fsck_describe_object(o, oid), message);
@ -1276,24 +1196,19 @@ int fsck_error_function(struct fsck_options *o,
return 1; return 1;
} }
void register_found_gitmodules(const struct object_id *oid)
{
oidset_insert(&gitmodules_found, oid);
}
int fsck_finish(struct fsck_options *options) int fsck_finish(struct fsck_options *options)
{ {
int ret = 0; int ret = 0;
struct oidset_iter iter; struct oidset_iter iter;
const struct object_id *oid; const struct object_id *oid;
oidset_iter_init(&gitmodules_found, &iter); oidset_iter_init(&options->gitmodules_found, &iter);
while ((oid = oidset_iter_next(&iter))) { while ((oid = oidset_iter_next(&iter))) {
enum object_type type; enum object_type type;
unsigned long size; unsigned long size;
char *buf; char *buf;
if (oidset_contains(&gitmodules_done, oid)) if (oidset_contains(&options->gitmodules_done, oid))
continue; continue;
buf = read_object_file(oid, &type, &size); buf = read_object_file(oid, &type, &size);
@ -1318,14 +1233,14 @@ int fsck_finish(struct fsck_options *options)
} }
oidset_clear(&gitmodules_found); oidset_clear(&options->gitmodules_found);
oidset_clear(&gitmodules_done); oidset_clear(&options->gitmodules_done);
return ret; return ret;
} }
int fsck_config_internal(const char *var, const char *value, void *cb, int git_fsck_config(const char *var, const char *value, void *cb)
struct fsck_options *options)
{ {
struct fsck_options *options = cb;
if (strcmp(var, "fsck.skiplist") == 0) { if (strcmp(var, "fsck.skiplist") == 0) {
const char *path; const char *path;
struct strbuf sb = STRBUF_INIT; struct strbuf sb = STRBUF_INIT;
@ -1346,3 +1261,21 @@ int fsck_config_internal(const char *var, const char *value, void *cb,
return git_default_config(var, value, cb); return git_default_config(var, value, cb);
} }
/*
* Custom error callbacks that are used in more than one place.
*/
int fsck_error_cb_print_missing_gitmodules(struct fsck_options *o,
const struct object_id *oid,
enum object_type object_type,
enum fsck_msg_type msg_type,
enum fsck_msg_id msg_id,
const char *message)
{
if (msg_id == FSCK_MSG_GITMODULES_MISSING) {
puts(oid_to_hex(oid));
return 0;
}
return fsck_error_function(o, oid, object_type, msg_type, msg_id, message);
}

127
fsck.h
View File

@ -3,15 +3,90 @@
#include "oidset.h" #include "oidset.h"
#define FSCK_ERROR 1 enum fsck_msg_type {
#define FSCK_WARN 2 /* for internal use only */
#define FSCK_IGNORE 3 FSCK_IGNORE,
FSCK_INFO,
FSCK_FATAL,
/* "public", fed to e.g. error_func callbacks */
FSCK_ERROR,
FSCK_WARN,
};
#define FOREACH_FSCK_MSG_ID(FUNC) \
/* fatal errors */ \
FUNC(NUL_IN_HEADER, FATAL) \
FUNC(UNTERMINATED_HEADER, FATAL) \
/* errors */ \
FUNC(BAD_DATE, ERROR) \
FUNC(BAD_DATE_OVERFLOW, ERROR) \
FUNC(BAD_EMAIL, ERROR) \
FUNC(BAD_NAME, ERROR) \
FUNC(BAD_OBJECT_SHA1, ERROR) \
FUNC(BAD_PARENT_SHA1, ERROR) \
FUNC(BAD_TAG_OBJECT, ERROR) \
FUNC(BAD_TIMEZONE, ERROR) \
FUNC(BAD_TREE, ERROR) \
FUNC(BAD_TREE_SHA1, ERROR) \
FUNC(BAD_TYPE, ERROR) \
FUNC(DUPLICATE_ENTRIES, 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_TREE_OBJECT, ERROR) \
FUNC(MISSING_TYPE, ERROR) \
FUNC(MISSING_TYPE_ENTRY, ERROR) \
FUNC(MULTIPLE_AUTHORS, ERROR) \
FUNC(TREE_NOT_SORTED, ERROR) \
FUNC(UNKNOWN_TYPE, ERROR) \
FUNC(ZERO_PADDED_DATE, ERROR) \
FUNC(GITMODULES_MISSING, ERROR) \
FUNC(GITMODULES_BLOB, ERROR) \
FUNC(GITMODULES_LARGE, ERROR) \
FUNC(GITMODULES_NAME, ERROR) \
FUNC(GITMODULES_SYMLINK, ERROR) \
FUNC(GITMODULES_URL, ERROR) \
FUNC(GITMODULES_PATH, ERROR) \
FUNC(GITMODULES_UPDATE, ERROR) \
/* warnings */ \
FUNC(BAD_FILEMODE, WARN) \
FUNC(EMPTY_NAME, WARN) \
FUNC(FULL_PATHNAME, WARN) \
FUNC(HAS_DOT, WARN) \
FUNC(HAS_DOTDOT, WARN) \
FUNC(HAS_DOTGIT, WARN) \
FUNC(NULL_SHA1, WARN) \
FUNC(ZERO_PADDED_FILEMODE, WARN) \
FUNC(NUL_IN_COMMIT, WARN) \
/* infos (reported as warnings, but ignored by default) */ \
FUNC(GITMODULES_PARSE, INFO) \
FUNC(BAD_TAG_NAME, INFO) \
FUNC(MISSING_TAGGER_ENTRY, 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 fsck_options;
struct object; 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, void fsck_set_msg_type(struct fsck_options *options,
const char *msg_id, const char *msg_type); const char *msg_id, const char *msg_type);
void fsck_set_msg_types(struct fsck_options *options, const char *values); 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); int is_valid_msg_type(const char *msg_id, const char *msg_type);
@ -23,28 +98,55 @@ int is_valid_msg_type(const char *msg_id, const char *msg_type);
* <0 error signaled and abort * <0 error signaled and abort
* >0 error signaled and do not abort * >0 error signaled and do not abort
*/ */
typedef int (*fsck_walk_func)(struct object *obj, int type, void *data, struct fsck_options *options); typedef int (*fsck_walk_func)(struct object *obj, enum object_type object_type,
void *data, struct fsck_options *options);
/* callback for fsck_object, type is FSCK_ERROR or FSCK_WARN */ /* callback for fsck_object, type is FSCK_ERROR or FSCK_WARN */
typedef int (*fsck_error)(struct fsck_options *o, typedef int (*fsck_error)(struct fsck_options *o,
const struct object_id *oid, enum object_type object_type, const struct object_id *oid, enum object_type object_type,
int msg_type, const char *message); enum fsck_msg_type msg_type, enum fsck_msg_id msg_id,
const char *message);
int fsck_error_function(struct fsck_options *o, int fsck_error_function(struct fsck_options *o,
const struct object_id *oid, enum object_type object_type, const struct object_id *oid, enum object_type object_type,
int msg_type, const char *message); enum fsck_msg_type msg_type, enum fsck_msg_id msg_id,
const char *message);
int fsck_error_cb_print_missing_gitmodules(struct fsck_options *o,
const struct object_id *oid,
enum object_type object_type,
enum fsck_msg_type msg_type,
enum fsck_msg_id msg_id,
const char *message);
struct fsck_options { struct fsck_options {
fsck_walk_func walk; fsck_walk_func walk;
fsck_error error_func; fsck_error error_func;
unsigned strict:1; unsigned strict:1;
int *msg_type; enum fsck_msg_type *msg_type;
struct oidset skiplist; struct oidset skiplist;
struct oidset gitmodules_found;
struct oidset gitmodules_done;
kh_oid_map_t *object_names; kh_oid_map_t *object_names;
}; };
#define FSCK_OPTIONS_DEFAULT { NULL, fsck_error_function, 0, NULL, OIDSET_INIT } #define FSCK_OPTIONS_DEFAULT { \
#define FSCK_OPTIONS_STRICT { NULL, fsck_error_function, 1, NULL, OIDSET_INIT } .skiplist = OIDSET_INIT, \
.gitmodules_found = OIDSET_INIT, \
.gitmodules_done = OIDSET_INIT, \
.error_func = fsck_error_function \
}
#define FSCK_OPTIONS_STRICT { \
.strict = 1, \
.gitmodules_found = OIDSET_INIT, \
.gitmodules_done = OIDSET_INIT, \
.error_func = fsck_error_function, \
}
#define FSCK_OPTIONS_MISSING_GITMODULES { \
.strict = 1, \
.gitmodules_found = OIDSET_INIT, \
.gitmodules_done = OIDSET_INIT, \
.error_func = fsck_error_cb_print_missing_gitmodules, \
}
/* descend in all linked child objects /* descend in all linked child objects
* the return value is: * the return value is:
@ -62,8 +164,6 @@ int fsck_walk(struct object *obj, void *data, struct fsck_options *options);
int fsck_object(struct object *obj, void *data, unsigned long size, int fsck_object(struct object *obj, void *data, unsigned long size,
struct fsck_options *options); struct fsck_options *options);
void register_found_gitmodules(const struct object_id *oid);
/* /*
* fsck a tag, and pass info about it back to the caller. This is * fsck a tag, and pass info about it back to the caller. This is
* exposed fsck_object() internals for git-mktag(1). * exposed fsck_object() internals for git-mktag(1).
@ -109,7 +209,6 @@ const char *fsck_describe_object(struct fsck_options *options,
* git_config() callback for use by fsck-y tools that want to support * git_config() callback for use by fsck-y tools that want to support
* fsck.<msg> fsck.skipList etc. * fsck.<msg> fsck.skipList etc.
*/ */
int fsck_config_internal(const char *var, const char *value, void *cb, int git_fsck_config(const char *var, const char *value, void *cb);
struct fsck_options *options);
#endif #endif