From 993a21b0a05bf2e2063c58e5722c29f5747e39d4 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sun, 17 Jul 2016 12:59:44 +0200 Subject: fsck: refactor how to describe objects In many places, we refer to objects via their SHA-1s. Let's abstract that into a function. For the moment, it does nothing else than what we did previously: print out the 40-digit hex string. But that will change over the course of the next patches. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- builtin/fsck.c | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) (limited to 'builtin') diff --git a/builtin/fsck.c b/builtin/fsck.c index 3f27456883..87df191e49 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -40,6 +40,11 @@ static int show_dangling = 1; #define ERROR_PACK 04 #define ERROR_REFS 010 +static const char *describe_object(struct object *obj) +{ + return oid_to_hex(&obj->oid); +} + static int fsck_config(const char *var, const char *value, void *cb) { if (strcmp(var, "fsck.skiplist") == 0) { @@ -67,7 +72,7 @@ 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), oid_to_hex(&obj->oid), err); + msg_type, typename(obj->type), describe_object(obj), err); } static int objerror(struct object *obj, const char *err) @@ -97,7 +102,7 @@ static int mark_object(struct object *obj, int type, void *data, struct fsck_opt if (!obj) { /* ... these references to parent->fld are safe here */ printf("broken link from %7s %s\n", - typename(parent->type), oid_to_hex(&parent->oid)); + typename(parent->type), describe_object(parent)); printf("broken link from %7s %s\n", (type == OBJ_ANY ? "unknown" : typename(type)), "unknown"); errors_found |= ERROR_REACHABLE; @@ -114,9 +119,9 @@ static int mark_object(struct object *obj, int type, void *data, struct fsck_opt if (!(obj->flags & HAS_OBJ)) { if (parent && !has_object_file(&obj->oid)) { printf("broken link from %7s %s\n", - typename(parent->type), oid_to_hex(&parent->oid)); + typename(parent->type), describe_object(parent)); printf(" to %7s %s\n", - typename(obj->type), oid_to_hex(&obj->oid)); + typename(obj->type), describe_object(obj)); errors_found |= ERROR_REACHABLE; } return 1; @@ -190,7 +195,8 @@ static void check_reachable_object(struct object *obj) return; /* it is in pack - forget about it */ if (connectivity_only && has_object_file(&obj->oid)) return; - printf("missing %s %s\n", typename(obj->type), oid_to_hex(&obj->oid)); + printf("missing %s %s\n", typename(obj->type), + describe_object(obj)); errors_found |= ERROR_REACHABLE; return; } @@ -215,7 +221,8 @@ static void check_unreachable_object(struct object *obj) * since this is something that is prunable. */ if (show_unreachable) { - printf("unreachable %s %s\n", typename(obj->type), oid_to_hex(&obj->oid)); + printf("unreachable %s %s\n", typename(obj->type), + describe_object(obj)); return; } @@ -234,11 +241,11 @@ static void check_unreachable_object(struct object *obj) if (!obj->used) { if (show_dangling) printf("dangling %s %s\n", typename(obj->type), - oid_to_hex(&obj->oid)); + describe_object(obj)); if (write_lost_and_found) { char *filename = git_pathdup("lost-found/%s/%s", obj->type == OBJ_COMMIT ? "commit" : "other", - oid_to_hex(&obj->oid)); + describe_object(obj)); FILE *f; if (safe_create_leading_directories_const(filename)) { @@ -252,7 +259,7 @@ static void check_unreachable_object(struct object *obj) if (stream_blob_to_fd(fileno(f), obj->oid.hash, NULL, 1)) die_errno("Could not write '%s'", filename); } else - fprintf(f, "%s\n", oid_to_hex(&obj->oid)); + fprintf(f, "%s\n", describe_object(obj)); if (fclose(f)) die_errno("Could not finish '%s'", filename); @@ -271,7 +278,7 @@ static void check_unreachable_object(struct object *obj) static void check_object(struct object *obj) { if (verbose) - fprintf(stderr, "Checking %s\n", oid_to_hex(&obj->oid)); + fprintf(stderr, "Checking %s\n", describe_object(obj)); if (obj->flags & REACHABLE) check_reachable_object(obj); @@ -307,7 +314,7 @@ static int fsck_obj(struct object *obj) if (verbose) fprintf(stderr, "Checking %s %s\n", - typename(obj->type), oid_to_hex(&obj->oid)); + typename(obj->type), describe_object(obj)); if (fsck_walk(obj, NULL, &fsck_obj_options)) objerror(obj, "broken links"); @@ -326,15 +333,17 @@ static int fsck_obj(struct object *obj) free_commit_buffer(commit); if (!commit->parents && show_root) - printf("root %s\n", oid_to_hex(&commit->object.oid)); + printf("root %s\n", describe_object(&commit->object)); } if (obj->type == OBJ_TAG) { struct tag *tag = (struct tag *) obj; if (show_tags && tag->tagged) { - printf("tagged %s %s", typename(tag->tagged->type), oid_to_hex(&tag->tagged->oid)); - printf(" (%s) in %s\n", tag->tag, oid_to_hex(&tag->object.oid)); + printf("tagged %s %s", typename(tag->tagged->type), + describe_object(tag->tagged)); + printf(" (%s) in %s\n", tag->tag, + describe_object(&tag->object)); } } -- cgit v1.2.3 From 1cd772cc4124e43b14231dcaeae8a5dddf4ffdb9 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sun, 17 Jul 2016 12:59:57 +0200 Subject: fsck: give the error function a chance to see the fsck_options We will need this in the next commit, where fsck will be taught to optionally name the objects when reporting issues about them. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- builtin/fsck.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'builtin') diff --git a/builtin/fsck.c b/builtin/fsck.c index 87df191e49..6c9d598853 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -82,7 +82,8 @@ static int objerror(struct object *obj, const char *err) return -1; } -static int fsck_error_func(struct object *obj, int type, const char *message) +static int fsck_error_func(struct fsck_options *o, + struct object *obj, int type, const char *message) { objreport(obj, (type == FSCK_WARN) ? "warning" : "error", message); return (type == FSCK_WARN) ? 0 : 1; -- cgit v1.2.3 From 90cf590f53f2939a47ca7b397e270e8228699829 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sun, 17 Jul 2016 13:00:02 +0200 Subject: fsck: optionally show more helpful info for broken links When reporting broken links between commits/trees/blobs, it would be quite helpful at times if the user would be told how the object is supposed to be reachable. With the new --name-objects option, git-fsck will try to do exactly that: name the objects in a way that shows how they are reachable. For example, when some reflog got corrupted and a blob is missing that should not be, the user might want to remove the corresponding reflog entry. This option helps them find that entry: `git fsck` will now report something like this: broken link from tree b5eb6ff... (refs/stash@{}~37:) to blob ec5cf80... Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- builtin/fsck.c | 42 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) (limited to 'builtin') diff --git a/builtin/fsck.c b/builtin/fsck.c index 6c9d598853..c6d17e63fd 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -13,6 +13,7 @@ #include "dir.h" #include "progress.h" #include "streaming.h" +#include "decorate.h" #define REACHABLE 0x0001 #define SEEN 0x0002 @@ -35,6 +36,7 @@ static int write_lost_and_found; static int verbose; static int show_progress = -1; static int show_dangling = 1; +static int name_objects; #define ERROR_OBJECT 01 #define ERROR_REACHABLE 02 #define ERROR_PACK 04 @@ -42,7 +44,16 @@ static int show_dangling = 1; static const char *describe_object(struct object *obj) { - return oid_to_hex(&obj->oid); + static struct strbuf buf = STRBUF_INIT; + char *name = name_objects ? + lookup_decoration(fsck_walk_options.object_names, obj) : NULL; + + strbuf_reset(&buf); + strbuf_addstr(&buf, oid_to_hex(&obj->oid)); + if (name) + strbuf_addf(&buf, " (%s)", name); + + return buf.buf; } static int fsck_config(const char *var, const char *value, void *cb) @@ -378,13 +389,18 @@ static int fsck_obj_buffer(const unsigned char *sha1, enum object_type type, static int default_refs; -static void fsck_handle_reflog_sha1(const char *refname, unsigned char *sha1) +static void fsck_handle_reflog_sha1(const char *refname, unsigned char *sha1, + unsigned long timestamp) { struct object *obj; if (!is_null_sha1(sha1)) { obj = lookup_object(sha1); if (obj) { + if (timestamp && name_objects) + add_decoration(fsck_walk_options.object_names, + obj, + xstrfmt("%s@{%ld}", refname, timestamp)); obj->used = 1; mark_object_reachable(obj); } else { @@ -404,8 +420,8 @@ static int fsck_handle_reflog_ent(unsigned char *osha1, unsigned char *nsha1, fprintf(stderr, "Checking reflog %s->%s\n", sha1_to_hex(osha1), sha1_to_hex(nsha1)); - fsck_handle_reflog_sha1(refname, osha1); - fsck_handle_reflog_sha1(refname, nsha1); + fsck_handle_reflog_sha1(refname, osha1, 0); + fsck_handle_reflog_sha1(refname, nsha1, timestamp); return 0; } @@ -434,6 +450,9 @@ static int fsck_handle_ref(const char *refname, const struct object_id *oid, } default_refs++; obj->used = 1; + if (name_objects) + add_decoration(fsck_walk_options.object_names, + obj, xstrdup(refname)); mark_object_reachable(obj); return 0; @@ -549,6 +568,9 @@ static int fsck_cache_tree(struct cache_tree *it) return 1; } obj->used = 1; + if (name_objects) + add_decoration(fsck_walk_options.object_names, + obj, xstrdup(":")); mark_object_reachable(obj); if (obj->type != OBJ_TREE) err |= objerror(obj, "non-tree in cache-tree"); @@ -577,6 +599,7 @@ static struct option fsck_opts[] = { OPT_BOOL(0, "lost-found", &write_lost_and_found, N_("write dangling objects in .git/lost-found")), OPT_BOOL(0, "progress", &show_progress, N_("show progress")), + OPT_BOOL(0, "name-objects", &name_objects, N_("show verbose names for reachable objects")), OPT_END(), }; @@ -606,6 +629,10 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) include_reflogs = 0; } + if (name_objects) + fsck_walk_options.object_names = + xcalloc(1, sizeof(struct decoration)); + git_config(fsck_config, NULL); fsck_head_link(); @@ -661,6 +688,9 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) continue; obj->used = 1; + if (name_objects) + add_decoration(fsck_walk_options.object_names, + obj, xstrdup(arg)); mark_object_reachable(obj); heads++; continue; @@ -693,6 +723,10 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) continue; obj = &blob->object; obj->used = 1; + if (name_objects) + add_decoration(fsck_walk_options.object_names, + obj, + xstrfmt(":%s", active_cache[i]->name)); mark_object_reachable(obj); } if (active_cache_tree) -- cgit v1.2.3