diff options
-rw-r--r-- | builtin/fsck.c | 50 | ||||
-rw-r--r-- | fsck.c | 82 | ||||
-rw-r--r-- | fsck.h | 24 | ||||
-rwxr-xr-x | t/t1450-fsck.sh | 2 |
4 files changed, 89 insertions, 69 deletions
diff --git a/builtin/fsck.c b/builtin/fsck.c index 18403a94fa..237643cc1d 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -52,24 +52,7 @@ static int name_objects; static const char *describe_object(struct object *obj) { - static struct strbuf bufs[] = { - STRBUF_INIT, STRBUF_INIT, STRBUF_INIT, STRBUF_INIT - }; - static int b = 0; - struct strbuf *buf; - char *name = NULL; - - if (name_objects) - name = lookup_decoration(fsck_walk_options.object_names, obj); - - buf = bufs + b; - b = (b + 1) % ARRAY_SIZE(bufs); - strbuf_reset(buf); - strbuf_addstr(buf, oid_to_hex(&obj->oid)); - if (name) - strbuf_addf(buf, " (%s)", name); - - return buf->buf; + return fsck_describe_object(&fsck_walk_options, obj); } static const char *printable_type(struct object *obj) @@ -499,10 +482,10 @@ static void fsck_handle_reflog_oid(const char *refname, struct object_id *oid, if (!is_null_oid(oid)) { obj = lookup_object(the_repository, oid); if (obj && (obj->flags & HAS_OBJ)) { - if (timestamp && name_objects) - add_decoration(fsck_walk_options.object_names, - obj, - xstrfmt("%s@{%"PRItime"}", refname, timestamp)); + if (timestamp) + fsck_put_object_name(&fsck_walk_options, obj, + "%s@{%"PRItime"}", + refname, timestamp); obj->flags |= USED; mark_object_reachable(obj); } else if (!is_promisor_object(oid)) { @@ -566,9 +549,8 @@ static int fsck_handle_ref(const char *refname, const struct object_id *oid, } default_refs++; obj->flags |= USED; - if (name_objects) - add_decoration(fsck_walk_options.object_names, - obj, xstrdup(refname)); + fsck_put_object_name(&fsck_walk_options, + obj, "%s", refname); mark_object_reachable(obj); return 0; @@ -742,9 +724,7 @@ static int fsck_cache_tree(struct cache_tree *it) return 1; } obj->flags |= USED; - if (name_objects) - add_decoration(fsck_walk_options.object_names, - obj, xstrdup(":")); + fsck_put_object_name(&fsck_walk_options, obj, ":"); mark_object_reachable(obj); if (obj->type != OBJ_TREE) err |= objerror(obj, _("non-tree in cache-tree")); @@ -830,8 +810,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) } if (name_objects) - fsck_walk_options.object_names = - xcalloc(1, sizeof(struct decoration)); + fsck_enable_object_names(&fsck_walk_options); git_config(fsck_config, NULL); @@ -890,9 +869,8 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) } obj->flags |= USED; - if (name_objects) - add_decoration(fsck_walk_options.object_names, - obj, xstrdup(arg)); + fsck_put_object_name(&fsck_walk_options, obj, + "%s", arg); mark_object_reachable(obj); continue; } @@ -928,10 +906,8 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) continue; obj = &blob->object; obj->flags |= USED; - if (name_objects) - add_decoration(fsck_walk_options.object_names, - obj, - xstrfmt(":%s", active_cache[i]->name)); + fsck_put_object_name(&fsck_walk_options, obj, + ":%s", active_cache[i]->name); mark_object_reachable(obj); } if (active_cache_tree) @@ -312,15 +312,21 @@ static int report(struct fsck_options *options, struct object *object, return result; } -static char *get_object_name(struct fsck_options *options, struct object *obj) +void fsck_enable_object_names(struct fsck_options *options) +{ + if (!options->object_names) + options->object_names = xcalloc(1, sizeof(struct decoration)); +} + +const char *fsck_get_object_name(struct fsck_options *options, struct object *obj) { if (!options->object_names) return NULL; return lookup_decoration(options->object_names, obj); } -static void put_object_name(struct fsck_options *options, struct object *obj, - const char *fmt, ...) +void fsck_put_object_name(struct fsck_options *options, struct object *obj, + const char *fmt, ...) { va_list ap; struct strbuf buf = STRBUF_INIT; @@ -337,17 +343,27 @@ static void put_object_name(struct fsck_options *options, struct object *obj, va_end(ap); } -static const char *describe_object(struct fsck_options *o, struct object *obj) +const char *fsck_describe_object(struct fsck_options *options, + struct object *obj) { - static struct strbuf buf = STRBUF_INIT; - char *name; - - strbuf_reset(&buf); - strbuf_addstr(&buf, oid_to_hex(&obj->oid)); - if (o->object_names && (name = lookup_decoration(o->object_names, obj))) - strbuf_addf(&buf, " (%s)", name); + static struct strbuf bufs[] = { + STRBUF_INIT, STRBUF_INIT, STRBUF_INIT, STRBUF_INIT + }; + static int b = 0; + struct strbuf *buf; + char *name = NULL; + + if (options->object_names) + name = lookup_decoration(options->object_names, obj); + + buf = bufs + b; + b = (b + 1) % ARRAY_SIZE(bufs); + strbuf_reset(buf); + strbuf_addstr(buf, oid_to_hex(&obj->oid)); + if (name) + strbuf_addf(buf, " (%s)", name); - return buf.buf; + return buf->buf; } static int fsck_walk_tree(struct tree *tree, void *data, struct fsck_options *options) @@ -360,7 +376,7 @@ static int fsck_walk_tree(struct tree *tree, void *data, struct fsck_options *op if (parse_tree(tree)) return -1; - name = get_object_name(options, &tree->object); + name = fsck_get_object_name(options, &tree->object); if (init_tree_desc_gently(&desc, tree->buffer, tree->size)) return -1; while (tree_entry_gently(&desc, &entry)) { @@ -373,20 +389,21 @@ static int fsck_walk_tree(struct tree *tree, void *data, struct fsck_options *op if (S_ISDIR(entry.mode)) { obj = (struct object *)lookup_tree(the_repository, &entry.oid); if (name && obj) - put_object_name(options, obj, "%s%s/", name, - entry.path); + fsck_put_object_name(options, obj, "%s%s/", + name, entry.path); result = options->walk(obj, OBJ_TREE, data, options); } else if (S_ISREG(entry.mode) || S_ISLNK(entry.mode)) { obj = (struct object *)lookup_blob(the_repository, &entry.oid); if (name && obj) - put_object_name(options, obj, "%s%s", name, - entry.path); + fsck_put_object_name(options, obj, "%s%s", + name, entry.path); result = options->walk(obj, OBJ_BLOB, data, options); } else { result = error("in tree %s: entry %s has bad mode %.6o", - describe_object(options, &tree->object), entry.path, entry.mode); + fsck_describe_object(options, &tree->object), + entry.path, entry.mode); } if (result < 0) return result; @@ -407,10 +424,10 @@ static int fsck_walk_commit(struct commit *commit, void *data, struct fsck_optio if (parse_commit(commit)) return -1; - name = get_object_name(options, &commit->object); + name = fsck_get_object_name(options, &commit->object); if (name) - put_object_name(options, &get_commit_tree(commit)->object, - "%s:", name); + fsck_put_object_name(options, &get_commit_tree(commit)->object, + "%s:", name); result = options->walk((struct object *)get_commit_tree(commit), OBJ_TREE, data, options); @@ -441,13 +458,15 @@ static int fsck_walk_commit(struct commit *commit, void *data, struct fsck_optio struct object *obj = &parents->item->object; if (counter++) - put_object_name(options, obj, "%s^%d", - name, counter); + fsck_put_object_name(options, obj, "%s^%d", + name, counter); else if (generation > 0) - put_object_name(options, obj, "%.*s~%d", - name_prefix_len, name, generation + 1); + fsck_put_object_name(options, obj, "%.*s~%d", + name_prefix_len, name, + generation + 1); else - put_object_name(options, obj, "%s^", name); + fsck_put_object_name(options, obj, "%s^", + name); } result = options->walk((struct object *)parents->item, OBJ_COMMIT, data, options); if (result < 0) @@ -461,12 +480,12 @@ static int fsck_walk_commit(struct commit *commit, void *data, struct fsck_optio static int fsck_walk_tag(struct tag *tag, void *data, struct fsck_options *options) { - char *name = get_object_name(options, &tag->object); + const char *name = fsck_get_object_name(options, &tag->object); if (parse_tag(tag)) return -1; if (name) - put_object_name(options, tag->tagged, "%s", name); + fsck_put_object_name(options, tag->tagged, "%s", name); return options->walk(tag->tagged, OBJ_ANY, data, options); } @@ -488,7 +507,8 @@ int fsck_walk(struct object *obj, void *data, struct fsck_options *options) case OBJ_TAG: return fsck_walk_tag((struct tag *)obj, data, options); default: - error("Unknown object type for %s", describe_object(options, obj)); + error("Unknown object type for %s", + fsck_describe_object(options, obj)); return -1; } } @@ -962,10 +982,10 @@ int fsck_error_function(struct fsck_options *o, struct object *obj, int msg_type, const char *message) { if (msg_type == FSCK_WARN) { - warning("object %s: %s", describe_object(o, obj), message); + warning("object %s: %s", fsck_describe_object(o, obj), message); return 0; } - error("object %s: %s", describe_object(o, obj), message); + error("object %s: %s", fsck_describe_object(o, obj), message); return 1; } @@ -67,4 +67,28 @@ int fsck_object(struct object *obj, void *data, unsigned long size, */ int fsck_finish(struct fsck_options *options); +/* + * 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, + struct object *obj); +__attribute__((format (printf,3,4))) +void fsck_put_object_name(struct fsck_options *options, struct object *obj, + const char *fmt, ...); +const char *fsck_describe_object(struct fsck_options *options, + struct object *obj); + #endif diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh index 50d28e6fdb..7c7ff7e961 100755 --- a/t/t1450-fsck.sh +++ b/t/t1450-fsck.sh @@ -616,7 +616,7 @@ test_expect_success 'fsck --name-objects' ' remove_object $(git rev-parse julius:caesar.t) && test_must_fail git fsck --name-objects >out && tree=$(git rev-parse --verify julius:) && - test_i18ngrep -E "$tree \((refs/heads/master|HEAD)@\{[0-9]*\}:" out + test_i18ngrep "$tree (refs/tags/julius:" out ) ' |