aboutsummaryrefslogtreecommitdiff
path: root/builtin
diff options
context:
space:
mode:
Diffstat (limited to 'builtin')
-rw-r--r--builtin/fsck.c78
-rw-r--r--builtin/index-pack.c13
-rw-r--r--builtin/receive-pack.c28
-rw-r--r--builtin/unpack-objects.c16
4 files changed, 99 insertions, 36 deletions
diff --git a/builtin/fsck.c b/builtin/fsck.c
index 267979304..f4b87e9b3 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -23,8 +23,11 @@ static int show_tags;
static int show_unreachable;
static int include_reflogs = 1;
static int check_full = 1;
+static int connectivity_only;
static int check_strict;
static int keep_cache_objects;
+static struct fsck_options fsck_walk_options = FSCK_OPTIONS_DEFAULT;
+static struct fsck_options fsck_obj_options = FSCK_OPTIONS_DEFAULT;
static struct object_id head_oid;
static const char *head_points_at;
static int errors_found;
@@ -44,39 +47,52 @@ static int show_dangling = 1;
#define DIRENT_SORT_HINT(de) ((de)->d_ino)
#endif
-static void objreport(struct object *obj, const char *severity,
- const char *err, va_list params)
+static int fsck_config(const char *var, const char *value, void *cb)
{
- fprintf(stderr, "%s in %s %s: ",
- severity, typename(obj->type), sha1_to_hex(obj->sha1));
- vfprintf(stderr, err, params);
- fputs("\n", stderr);
+ if (strcmp(var, "fsck.skiplist") == 0) {
+ const char *path;
+ struct strbuf sb = STRBUF_INIT;
+
+ if (git_config_pathname(&path, var, value))
+ return 1;
+ strbuf_addf(&sb, "skiplist=%s", path);
+ free((char *)path);
+ fsck_set_msg_types(&fsck_obj_options, sb.buf);
+ strbuf_release(&sb);
+ return 0;
+ }
+
+ if (skip_prefix(var, "fsck.", &var)) {
+ fsck_set_msg_type(&fsck_obj_options, var, value);
+ return 0;
+ }
+
+ return git_default_config(var, value, cb);
+}
+
+static void objreport(struct object *obj, const char *msg_type,
+ const char *err)
+{
+ fprintf(stderr, "%s in %s %s: %s\n",
+ msg_type, typename(obj->type), sha1_to_hex(obj->sha1), err);
}
-__attribute__((format (printf, 2, 3)))
-static int objerror(struct object *obj, const char *err, ...)
+static int objerror(struct object *obj, const char *err)
{
- va_list params;
- va_start(params, err);
errors_found |= ERROR_OBJECT;
- objreport(obj, "error", err, params);
- va_end(params);
+ objreport(obj, "error", err);
return -1;
}
-__attribute__((format (printf, 3, 4)))
-static int fsck_error_func(struct object *obj, int type, const char *err, ...)
+static int fsck_error_func(struct object *obj, int type, const char *message)
{
- va_list params;
- va_start(params, err);
- objreport(obj, (type == FSCK_WARN) ? "warning" : "error", err, params);
- va_end(params);
+ objreport(obj, (type == FSCK_WARN) ? "warning" : "error", message);
return (type == FSCK_WARN) ? 0 : 1;
}
static struct object_array pending;
-static int mark_object(struct object *obj, int type, void *data)
+static int mark_object(struct object *obj, int type, void *data, struct fsck_options *options)
{
struct object *parent = data;
@@ -119,7 +135,7 @@ static int mark_object(struct object *obj, int type, void *data)
static void mark_object_reachable(struct object *obj)
{
- mark_object(obj, OBJ_ANY, NULL);
+ mark_object(obj, OBJ_ANY, NULL, NULL);
}
static int traverse_one_object(struct object *obj)
@@ -132,7 +148,7 @@ static int traverse_one_object(struct object *obj)
if (parse_tree(tree) < 0)
return 1; /* error already displayed */
}
- result = fsck_walk(obj, mark_object, obj);
+ result = fsck_walk(obj, obj, &fsck_walk_options);
if (tree)
free_tree_buffer(tree);
return result;
@@ -158,7 +174,7 @@ static int traverse_reachable(void)
return !!result;
}
-static int mark_used(struct object *obj, int type, void *data)
+static int mark_used(struct object *obj, int type, void *data, struct fsck_options *options)
{
if (!obj)
return 1;
@@ -179,6 +195,8 @@ static void check_reachable_object(struct object *obj)
if (!(obj->flags & HAS_OBJ)) {
if (has_sha1_pack(obj->sha1))
return; /* it is in pack - forget about it */
+ if (connectivity_only && has_sha1_file(obj->sha1))
+ return;
printf("missing %s %s\n", typename(obj->type), sha1_to_hex(obj->sha1));
errors_found |= ERROR_REACHABLE;
return;
@@ -296,9 +314,9 @@ static int fsck_obj(struct object *obj)
fprintf(stderr, "Checking %s %s\n",
typename(obj->type), sha1_to_hex(obj->sha1));
- if (fsck_walk(obj, mark_used, NULL))
+ if (fsck_walk(obj, NULL, &fsck_obj_options))
objerror(obj, "broken links");
- if (fsck_object(obj, NULL, 0, check_strict, fsck_error_func))
+ if (fsck_object(obj, NULL, 0, &fsck_obj_options))
return -1;
if (obj->type == OBJ_TREE) {
@@ -621,6 +639,7 @@ static struct option fsck_opts[] = {
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_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,
N_("write dangling objects in .git/lost-found")),
@@ -638,6 +657,12 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
argc = parse_options(argc, argv, prefix, fsck_opts, fsck_usage, 0);
+ fsck_walk_options.walk = mark_object;
+ fsck_obj_options.walk = mark_used;
+ fsck_obj_options.error_func = fsck_error_func;
+ if (check_strict)
+ fsck_obj_options.strict = 1;
+
if (show_progress == -1)
show_progress = isatty(2);
if (verbose)
@@ -648,8 +673,11 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
include_reflogs = 0;
}
+ git_config(fsck_config, NULL);
+
fsck_head_link();
- fsck_object_dir(get_object_directory());
+ if (!connectivity_only)
+ fsck_object_dir(get_object_directory());
prepare_alt_odb();
for (alt = alt_odb_list; alt; alt = alt->next) {
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index f07bc66ed..3f1084044 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -75,6 +75,7 @@ static int nr_threads;
static int from_stdin;
static int strict;
static int do_fsck_object;
+static struct fsck_options fsck_options = FSCK_OPTIONS_STRICT;
static int verbose;
static int show_stat;
static int check_self_contained_and_connected;
@@ -192,7 +193,7 @@ static void cleanup_thread(void)
#endif
-static int mark_link(struct object *obj, int type, void *data)
+static int mark_link(struct object *obj, int type, void *data, struct fsck_options *options)
{
if (!obj)
return -1;
@@ -838,10 +839,9 @@ static void sha1_object(const void *data, struct object_entry *obj_entry,
if (!obj)
die(_("invalid %s"), typename(type));
if (do_fsck_object &&
- fsck_object(obj, buf, size, 1,
- fsck_error_function))
+ fsck_object(obj, buf, size, &fsck_options))
die(_("Error in object"));
- if (fsck_walk(obj, mark_link, NULL))
+ if (fsck_walk(obj, NULL, &fsck_options))
die(_("Not all child objects of %s are reachable"), sha1_to_hex(obj->sha1));
if (obj->type == OBJ_TREE) {
@@ -1615,6 +1615,7 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
usage(index_pack_usage);
check_replace_refs = 0;
+ fsck_options.walk = mark_link;
reset_pack_idx_option(&opts);
git_config(git_index_pack_config, &opts);
@@ -1632,6 +1633,10 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
} else if (!strcmp(arg, "--strict")) {
strict = 1;
do_fsck_object = 1;
+ } else if (skip_prefix(arg, "--strict=", &arg)) {
+ strict = 1;
+ do_fsck_object = 1;
+ fsck_set_msg_types(&fsck_options, arg);
} else if (!strcmp(arg, "--check-self-contained-and-connected")) {
strict = 1;
check_self_contained_and_connected = 1;
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index 94d057177..4ced2eba3 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -19,6 +19,7 @@
#include "tag.h"
#include "gpg-interface.h"
#include "sigchain.h"
+#include "fsck.h"
static const char receive_pack_usage[] = "git receive-pack <git-dir>";
@@ -36,6 +37,7 @@ static enum deny_action deny_current_branch = DENY_UNCONFIGURED;
static enum deny_action deny_delete_current = DENY_UNCONFIGURED;
static int receive_fsck_objects = -1;
static int transfer_fsck_objects = -1;
+static struct strbuf fsck_msg_types = STRBUF_INIT;
static int receive_unpack_limit = -1;
static int transfer_unpack_limit = -1;
static int advertise_atomic_push = 1;
@@ -115,6 +117,26 @@ static int receive_pack_config(const char *var, const char *value, void *cb)
return 0;
}
+ if (strcmp(var, "receive.fsck.skiplist") == 0) {
+ const char *path;
+
+ if (git_config_pathname(&path, var, value))
+ return 1;
+ strbuf_addf(&fsck_msg_types, "%cskiplist=%s",
+ fsck_msg_types.len ? ',' : '=', path);
+ free((char *)path);
+ return 0;
+ }
+
+ if (skip_prefix(var, "receive.fsck.", &var)) {
+ if (is_valid_msg_type(var, value))
+ strbuf_addf(&fsck_msg_types, "%c%s=%s",
+ fsck_msg_types.len ? ',' : '=', var, value);
+ else
+ warning("Skipping unknown msg id '%s'", var);
+ return 0;
+ }
+
if (strcmp(var, "receive.fsckobjects") == 0) {
receive_fsck_objects = git_config_bool(var, value);
return 0;
@@ -1490,7 +1512,8 @@ static const char *unpack(int err_fd, struct shallow_info *si)
if (quiet)
argv_array_push(&child.args, "-q");
if (fsck_objects)
- argv_array_push(&child.args, "--strict");
+ argv_array_pushf(&child.args, "--strict%s",
+ fsck_msg_types.buf);
child.no_stdout = 1;
child.err = err_fd;
child.git_cmd = 1;
@@ -1508,7 +1531,8 @@ static const char *unpack(int err_fd, struct shallow_info *si)
argv_array_pushl(&child.args, "index-pack",
"--stdin", hdr_arg, keep_arg, NULL);
if (fsck_objects)
- argv_array_push(&child.args, "--strict");
+ argv_array_pushf(&child.args, "--strict%s",
+ fsck_msg_types.buf);
if (fix_thin)
argv_array_push(&child.args, "--fix-thin");
child.out = -1;
diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c
index ac6667242..7cc086f5f 100644
--- a/builtin/unpack-objects.c
+++ b/builtin/unpack-objects.c
@@ -20,6 +20,7 @@ static unsigned char buffer[4096];
static unsigned int offset, len;
static off_t consumed_bytes;
static git_SHA_CTX ctx;
+static struct fsck_options fsck_options = FSCK_OPTIONS_STRICT;
/*
* When running under --strict mode, objects whose reachability are
@@ -178,7 +179,7 @@ static void write_cached_object(struct object *obj, struct obj_buffer *obj_buf)
* that have reachability requirements and calls this function.
* Verify its reachability and validity recursively and write it out.
*/
-static int check_object(struct object *obj, int type, void *data)
+static int check_object(struct object *obj, int type, void *data, struct fsck_options *options)
{
struct obj_buffer *obj_buf;
@@ -203,10 +204,10 @@ static int check_object(struct object *obj, int type, void *data)
obj_buf = lookup_object_buffer(obj);
if (!obj_buf)
die("Whoops! Cannot find object '%s'", sha1_to_hex(obj->sha1));
- if (fsck_object(obj, obj_buf->buffer, obj_buf->size, 1,
- fsck_error_function))
+ if (fsck_object(obj, obj_buf->buffer, obj_buf->size, &fsck_options))
die("Error in object");
- if (fsck_walk(obj, check_object, NULL))
+ fsck_options.walk = check_object;
+ if (fsck_walk(obj, NULL, &fsck_options))
die("Error on reachable objects of %s", sha1_to_hex(obj->sha1));
write_cached_object(obj, obj_buf);
return 0;
@@ -217,7 +218,7 @@ static void write_rest(void)
unsigned i;
for (i = 0; i < nr_objects; i++) {
if (obj_list[i].obj)
- check_object(obj_list[i].obj, OBJ_ANY, NULL);
+ check_object(obj_list[i].obj, OBJ_ANY, NULL, NULL);
}
}
@@ -529,6 +530,11 @@ int cmd_unpack_objects(int argc, const char **argv, const char *prefix)
strict = 1;
continue;
}
+ if (skip_prefix(arg, "--strict=", &arg)) {
+ strict = 1;
+ fsck_set_msg_types(&fsck_options, arg);
+ continue;
+ }
if (starts_with(arg, "--pack_header=")) {
struct pack_header *hdr;
char *c;