| 1 | #ifndef GIT_FSCK_H |
| 2 | #define GIT_FSCK_H |
| 3 | |
| 4 | #include "object.h" |
| 5 | #include "oidset.h" |
| 6 | |
| 7 | enum fsck_msg_type { |
| 8 | /* for internal use only */ |
| 9 | FSCK_IGNORE, |
| 10 | FSCK_INFO, |
| 11 | FSCK_FATAL, |
| 12 | /* "public", fed to e.g. error_func callbacks */ |
| 13 | FSCK_ERROR, |
| 14 | FSCK_WARN, |
| 15 | }; |
| 16 | |
| 17 | /* |
| 18 | * Documentation/fsck-msgids.adoc documents these; when |
| 19 | * modifying this list in any way, make sure to keep the |
| 20 | * two in sync. |
| 21 | */ |
| 22 | |
| 23 | #define FOREACH_FSCK_MSG_ID(FUNC) \ |
| 24 | /* fatal errors */ \ |
| 25 | FUNC(NUL_IN_HEADER, FATAL) \ |
| 26 | FUNC(UNTERMINATED_HEADER, FATAL) \ |
| 27 | /* errors */ \ |
| 28 | FUNC(BAD_HEADER_CONTINUATION, ERROR) \ |
| 29 | FUNC(BAD_DATE, ERROR) \ |
| 30 | FUNC(BAD_DATE_OVERFLOW, ERROR) \ |
| 31 | FUNC(BAD_EMAIL, ERROR) \ |
| 32 | FUNC(BAD_GPGSIG, ERROR) \ |
| 33 | FUNC(BAD_HEAD_TARGET, ERROR) \ |
| 34 | FUNC(BAD_NAME, ERROR) \ |
| 35 | FUNC(BAD_OBJECT_SHA1, ERROR) \ |
| 36 | FUNC(BAD_PACKED_REF_ENTRY, ERROR) \ |
| 37 | FUNC(BAD_PACKED_REF_HEADER, ERROR) \ |
| 38 | FUNC(BAD_PARENT_SHA1, ERROR) \ |
| 39 | FUNC(BAD_REFERENT_NAME, ERROR) \ |
| 40 | FUNC(BAD_REF_CONTENT, ERROR) \ |
| 41 | FUNC(BAD_REF_FILETYPE, ERROR) \ |
| 42 | FUNC(BAD_REF_NAME, ERROR) \ |
| 43 | FUNC(BAD_REF_OID, ERROR) \ |
| 44 | FUNC(BAD_TIMEZONE, ERROR) \ |
| 45 | FUNC(BAD_TREE, ERROR) \ |
| 46 | FUNC(BAD_TREE_SHA1, ERROR) \ |
| 47 | FUNC(BAD_TYPE, ERROR) \ |
| 48 | FUNC(DUPLICATE_ENTRIES, ERROR) \ |
| 49 | FUNC(GITATTRIBUTES_BLOB, ERROR) \ |
| 50 | FUNC(GITATTRIBUTES_LARGE, ERROR) \ |
| 51 | FUNC(GITATTRIBUTES_LINE_LENGTH, ERROR) \ |
| 52 | FUNC(GITATTRIBUTES_MISSING, ERROR) \ |
| 53 | FUNC(GITMODULES_BLOB, ERROR) \ |
| 54 | FUNC(GITMODULES_LARGE, ERROR) \ |
| 55 | FUNC(GITMODULES_MISSING, ERROR) \ |
| 56 | FUNC(GITMODULES_NAME, ERROR) \ |
| 57 | FUNC(GITMODULES_PATH, ERROR) \ |
| 58 | FUNC(GITMODULES_SYMLINK, ERROR) \ |
| 59 | FUNC(GITMODULES_UPDATE, ERROR) \ |
| 60 | FUNC(GITMODULES_URL, ERROR) \ |
| 61 | FUNC(MISSING_AUTHOR, ERROR) \ |
| 62 | FUNC(MISSING_COMMITTER, ERROR) \ |
| 63 | FUNC(MISSING_EMAIL, ERROR) \ |
| 64 | FUNC(MISSING_NAME_BEFORE_EMAIL, ERROR) \ |
| 65 | FUNC(MISSING_OBJECT, ERROR) \ |
| 66 | FUNC(MISSING_SPACE_BEFORE_DATE, ERROR) \ |
| 67 | FUNC(MISSING_SPACE_BEFORE_EMAIL, ERROR) \ |
| 68 | FUNC(MISSING_TAG, ERROR) \ |
| 69 | FUNC(MISSING_TAG_ENTRY, ERROR) \ |
| 70 | FUNC(MISSING_TREE, ERROR) \ |
| 71 | FUNC(MISSING_TYPE, ERROR) \ |
| 72 | FUNC(MISSING_TYPE_ENTRY, ERROR) \ |
| 73 | FUNC(MULTIPLE_AUTHORS, ERROR) \ |
| 74 | FUNC(PACKED_REF_ENTRY_NOT_TERMINATED, ERROR) \ |
| 75 | FUNC(PACKED_REF_UNSORTED, ERROR) \ |
| 76 | FUNC(TREE_NOT_SORTED, ERROR) \ |
| 77 | FUNC(UNKNOWN_TYPE, ERROR) \ |
| 78 | FUNC(ZERO_PADDED_DATE, ERROR) \ |
| 79 | /* warnings */ \ |
| 80 | FUNC(BAD_REFTABLE_TABLE_NAME, WARN) \ |
| 81 | FUNC(EMPTY_NAME, WARN) \ |
| 82 | FUNC(FULL_PATHNAME, WARN) \ |
| 83 | FUNC(HAS_DOT, WARN) \ |
| 84 | FUNC(HAS_DOTDOT, WARN) \ |
| 85 | FUNC(HAS_DOTGIT, WARN) \ |
| 86 | FUNC(LARGE_PATHNAME, WARN) \ |
| 87 | FUNC(NULL_SHA1, WARN) \ |
| 88 | FUNC(NUL_IN_COMMIT, WARN) \ |
| 89 | FUNC(ZERO_PADDED_FILEMODE, WARN) \ |
| 90 | /* infos (reported as warnings, but ignored by default) */ \ |
| 91 | FUNC(BAD_FILEMODE, INFO) \ |
| 92 | FUNC(BAD_TAG_NAME, INFO) \ |
| 93 | FUNC(EMPTY_PACKED_REFS_FILE, INFO) \ |
| 94 | FUNC(GITATTRIBUTES_SYMLINK, INFO) \ |
| 95 | FUNC(GITIGNORE_SYMLINK, INFO) \ |
| 96 | FUNC(GITMODULES_PARSE, INFO) \ |
| 97 | FUNC(MAILMAP_SYMLINK, INFO) \ |
| 98 | FUNC(MISSING_TAGGER_ENTRY, INFO) \ |
| 99 | FUNC(REF_MISSING_NEWLINE, INFO) \ |
| 100 | FUNC(SYMLINK_REF, INFO) \ |
| 101 | FUNC(SYMREF_TARGET_IS_NOT_A_REF, INFO) \ |
| 102 | FUNC(TRAILING_REF_CONTENT, INFO) \ |
| 103 | /* ignored (elevated when requested) */ \ |
| 104 | FUNC(EXTRA_HEADER_ENTRY, IGNORE) |
| 105 | |
| 106 | #define MSG_ID(id, msg_type) FSCK_MSG_##id, |
| 107 | enum fsck_msg_id { |
| 108 | FOREACH_FSCK_MSG_ID(MSG_ID) |
| 109 | FSCK_MSG_MAX |
| 110 | }; |
| 111 | #undef MSG_ID |
| 112 | |
| 113 | struct fsck_options; |
| 114 | struct object; |
| 115 | |
| 116 | void fsck_set_msg_type_from_ids(struct fsck_options *options, |
| 117 | enum fsck_msg_id msg_id, |
| 118 | enum fsck_msg_type msg_type); |
| 119 | void fsck_set_msg_type(struct fsck_options *options, |
| 120 | const char *msg_id, const char *msg_type); |
| 121 | void fsck_set_msg_types(struct fsck_options *options, const char *values); |
| 122 | int is_valid_msg_type(const char *msg_id, const char *msg_type); |
| 123 | |
| 124 | /* |
| 125 | * callback function for fsck_walk |
| 126 | * type is the expected type of the object or OBJ_ANY |
| 127 | * the return value is: |
| 128 | * 0 everything OK |
| 129 | * <0 error signaled and abort |
| 130 | * >0 error signaled and do not abort |
| 131 | */ |
| 132 | typedef int (*fsck_walk_func)(struct object *obj, enum object_type object_type, |
| 133 | void *data, struct fsck_options *options); |
| 134 | |
| 135 | /* |
| 136 | * Callback for reporting errors either for objects or refs. The "fsck_report" |
| 137 | * is a generic pointer that can be used to pass any information. |
| 138 | */ |
| 139 | typedef int (*fsck_error)(struct fsck_options *o, |
| 140 | void *fsck_report, |
| 141 | enum fsck_msg_type msg_type, enum fsck_msg_id msg_id, |
| 142 | const char *message); |
| 143 | |
| 144 | int fsck_objects_error_function(struct fsck_options *o, |
| 145 | void *fsck_report, |
| 146 | enum fsck_msg_type msg_type, enum fsck_msg_id msg_id, |
| 147 | const char *message); |
| 148 | int fsck_objects_error_cb_print_missing_gitmodules(struct fsck_options *o, |
| 149 | void *fsck_report, |
| 150 | enum fsck_msg_type msg_type, |
| 151 | enum fsck_msg_id msg_id, |
| 152 | const char *message); |
| 153 | |
| 154 | int fsck_refs_error_function(struct fsck_options *options, |
| 155 | void *fsck_report, |
| 156 | enum fsck_msg_type msg_type, |
| 157 | enum fsck_msg_id msg_id, |
| 158 | const char *message); |
| 159 | |
| 160 | struct fsck_object_report { |
| 161 | const struct object_id *oid; |
| 162 | enum object_type object_type; |
| 163 | }; |
| 164 | |
| 165 | struct fsck_ref_report { |
| 166 | const char *path; |
| 167 | }; |
| 168 | |
| 169 | struct repository; |
| 170 | |
| 171 | struct fsck_options { |
| 172 | struct repository *repo; |
| 173 | fsck_walk_func walk; |
| 174 | fsck_error error_func; |
| 175 | unsigned strict; |
| 176 | unsigned verbose; |
| 177 | enum fsck_msg_type *msg_type; |
| 178 | struct oidset skip_oids; |
| 179 | struct oidset gitmodules_found; |
| 180 | struct oidset gitmodules_done; |
| 181 | struct oidset gitattributes_found; |
| 182 | struct oidset gitattributes_done; |
| 183 | kh_oid_map_t *object_names; |
| 184 | }; |
| 185 | |
| 186 | /* descend in all linked child objects |
| 187 | * the return value is: |
| 188 | * -1 error in processing the object |
| 189 | * <0 return value of the callback, which lead to an abort |
| 190 | * >0 return value of the first signaled error >0 (in the case of no other errors) |
| 191 | * 0 everything OK |
| 192 | */ |
| 193 | int fsck_walk(struct object *obj, void *data, struct fsck_options *options); |
| 194 | |
| 195 | /* |
| 196 | * Blob objects my pass a NULL data pointer, which indicates they are too large |
| 197 | * to fit in memory. All other types must pass a real buffer. |
| 198 | */ |
| 199 | int fsck_object(struct object *obj, void *data, unsigned long size, |
| 200 | struct fsck_options *options); |
| 201 | |
| 202 | /* |
| 203 | * Same as fsck_object(), but for when the caller doesn't have an object |
| 204 | * struct. |
| 205 | */ |
| 206 | int fsck_buffer(const struct object_id *oid, enum object_type, |
| 207 | const void *data, unsigned long size, |
| 208 | struct fsck_options *options); |
| 209 | |
| 210 | /* |
| 211 | * fsck a tag, and pass info about it back to the caller. This is |
| 212 | * exposed fsck_object() internals for git-mktag(1). |
| 213 | */ |
| 214 | int fsck_tag_standalone(const struct object_id *oid, const char *buffer, |
| 215 | unsigned long size, struct fsck_options *options, |
| 216 | struct object_id *tagged_oid, |
| 217 | int *tag_type); |
| 218 | |
| 219 | /* |
| 220 | * Some fsck checks are context-dependent, and may end up queued; run this |
| 221 | * after completing all fsck_object() calls in order to resolve any remaining |
| 222 | * checks. |
| 223 | */ |
| 224 | int fsck_finish(struct fsck_options *options); |
| 225 | |
| 226 | /* |
| 227 | * Check whether there are any checks that have been queued up and that still |
| 228 | * need to be run. Returns `false` iff `fsck_finish()` wouldn't perform any |
| 229 | * actions, `true` otherwise. |
| 230 | */ |
| 231 | bool fsck_has_queued_checks(struct fsck_options *options); |
| 232 | |
| 233 | enum fsck_options_type { |
| 234 | FSCK_OPTIONS_DEFAULT, |
| 235 | FSCK_OPTIONS_STRICT, |
| 236 | FSCK_OPTIONS_MISSING_GITMODULES, |
| 237 | FSCK_OPTIONS_REFS, |
| 238 | }; |
| 239 | |
| 240 | void fsck_options_init(struct fsck_options *options, |
| 241 | struct repository *repo, |
| 242 | enum fsck_options_type type); |
| 243 | |
| 244 | /* |
| 245 | * Clear the fsck_options struct, freeing any allocated memory. |
| 246 | */ |
| 247 | void fsck_options_clear(struct fsck_options *options); |
| 248 | |
| 249 | /* |
| 250 | * Report an error or warning for refs. |
| 251 | */ |
| 252 | __attribute__((format (printf, 4, 5))) |
| 253 | int fsck_report_ref(struct fsck_options *options, |
| 254 | struct fsck_ref_report *report, |
| 255 | enum fsck_msg_id msg_id, |
| 256 | const char *fmt, ...); |
| 257 | |
| 258 | |
| 259 | /* |
| 260 | * Subsystem for storing human-readable names for each object. |
| 261 | * |
| 262 | * If fsck_enable_object_names() has not been called, all other functions are |
| 263 | * noops. |
| 264 | * |
| 265 | * Use fsck_put_object_name() to seed initial names (e.g. from refnames); the |
| 266 | * fsck code will extend that while walking trees, etc. |
| 267 | * |
| 268 | * Use fsck_get_object_name() to get a single name (or NULL if none). Or the |
| 269 | * more convenient describe_object(), which always produces an output string |
| 270 | * with the oid combined with the name (if any). Note that the return value |
| 271 | * points to a rotating array of static buffers, and may be invalidated by a |
| 272 | * subsequent call. |
| 273 | */ |
| 274 | void fsck_enable_object_names(struct fsck_options *options); |
| 275 | const char *fsck_get_object_name(struct fsck_options *options, |
| 276 | const struct object_id *oid); |
| 277 | __attribute__((format (printf,3,4))) |
| 278 | void fsck_put_object_name(struct fsck_options *options, |
| 279 | const struct object_id *oid, |
| 280 | const char *fmt, ...); |
| 281 | const char *fsck_describe_object(struct fsck_options *options, |
| 282 | const struct object_id *oid); |
| 283 | |
| 284 | struct key_value_info; |
| 285 | /* |
| 286 | * repo_config() callback for use by fsck-y tools that want to support |
| 287 | * fsck.<msg> fsck.skipList etc. |
| 288 | */ |
| 289 | int git_fsck_config(const char *var, const char *value, |
| 290 | const struct config_context *ctx, void *cb); |
| 291 | |
| 292 | #endif |