git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 2/3] fsck_walk(): optionally name objects on the go

From
Johannes Schindelin <johannes.schindelin@gmx.de>
Date
Jul 14, 2016, 15:30 UTC
Message-ID
<f5ef009d2be6bf0137b33ac9ce85ff0ce03a48e8.1468510191.git.johannes.schindelin@gmx.de>
In-Reply-To
<cover.1468510191.git.johannes.schindelin@gmx.de>

If fsck_options->name_objects is initialized, and if it already has name(s) for the object(s) that are to be the starting point(s) for fsck_walk(), then that function will now add names for the objects that were walked.

This will be highly useful for teaching git-fsck to identify root causes for broken links, which is the task for the next patch in this series.

Note that this patch opts for decorating the objects with plain strings instead of full-blown structs (à la `struct rev_name` in the code of the `git name-rev` command), for several reasons:

- the code is much simpler than if it had to work with structs that
  describe arbitrarily long names such as "master~14^2~5:builtin/am.c",
- the string processing is actually quite light-weight compared to the
  rest of fsck's operation,
- the caller of fsck_walk() is expected to provide names for the
  starting points, and using plain and simple strings is just the
  easiest way to do that.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 fsck.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 fsck.h |  1 +
 2 files changed, 73 insertions(+)
diff --git a/fsck.c b/fsck.c
index 0531545..fe6a28a 100644
--- a/fsck.c
+++ b/fsck.c
@@ -9,6 +9,7 @@
 #include "refs.h"
 #include "utf8.h"
 #include "sha1-array.h"
+#include "decorate.h"
 
 #define FSCK_FATAL -1
 #define FSCK_INFO -2
@@ -297,19 +298,51 @@ static int report(struct fsck_options *options, struct object *object,
 	return result;
 }
 
+static char *get_object_name(struct fsck_options *options, struct object *obj)
+{
+	return options->object_names ?
+		lookup_decoration(options->object_names, obj) : NULL;
+}
+
+static void put_object_name(struct fsck_options *options, struct object *obj,
+	const char *fmt, ...)
+{
+	va_list ap;
+	char *existing = lookup_decoration(options->object_names, obj);
+	struct strbuf buf = STRBUF_INIT;
+
+	if (existing)
+		return;
+	va_start(ap, fmt);
+	strbuf_vaddf(&buf, fmt, ap);
+	add_decoration(options->object_names, obj, strbuf_detach(&buf, NULL));
+	va_end(ap);
+}
+
 static int fsck_walk_tree(struct tree *tree, void *data, struct fsck_options *options)
 {
 	struct tree_desc desc;
 	struct name_entry entry;
 	int res = 0;
+	const char *name;
 
 	if (parse_tree(tree))
 		return -1;
 
+	name = get_object_name(options, &tree->object);
 	init_tree_desc(&desc, tree->buffer, tree->size);
 	while (tree_entry(&desc, &entry)) {
 		int result;
 
+		if (name) {
+			struct object *obj = parse_object(entry.oid->hash);
+
+			if (obj)
+				put_object_name(options, obj, "%s%s%s", name,
+					entry.path,
+					S_ISDIR(entry.mode) ? "/" : "");
+		}
+
 		if (S_ISGITLINK(entry.mode))
 			continue;
 		if (S_ISDIR(entry.mode))
@@ -330,20 +363,55 @@ static int fsck_walk_tree(struct tree *tree, void *data, struct fsck_options *op
 
 static int fsck_walk_commit(struct commit *commit, void *data, struct fsck_options *options)
 {
+	int counter = 0, generation = 0, name_prefix_len = 0;
 	struct commit_list *parents;
 	int res;
 	int result;
+	const char *name;
 
 	if (parse_commit(commit))
 		return -1;
 
+	name = get_object_name(options, &commit->object);
+	if (name)
+		put_object_name(options, &commit->tree->object, "%s:", name);
+
 	result = options->walk((struct object *)commit->tree, OBJ_TREE, data, options);
 	if (result < 0)
 		return result;
 	res = result;
 
 	parents = commit->parents;
+	if (name && parents) {
+		int len = strlen(name), power;
+
+		if (len && name[len - 1] == '^') {
+			generation = 1;
+			name_prefix_len = len - 1;
+		}
+		else { /* parse ~<generation> suffix */
+			for (generation = 0, power = 1;
+			     len && isdigit(name[len - 1]);
+			     power *= 10)
+				generation += power * (name[--len] - '0');
+			if (power > 1 && len && name[len - 1] == '~')
+				name_prefix_len = len - 1;
+		}
+	}
+
 	while (parents) {
+		if (name) {
+			struct object *obj = &parents->item->object;
+
+			if (++counter > 1)
+				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);
+			else
+				put_object_name(options, obj, "%s^", name);
+		}
 		result = options->walk((struct object *)parents->item, OBJ_COMMIT, data, options);
 		if (result < 0)
 			return result;
@@ -356,8 +424,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);
+
 	if (parse_tag(tag))
 		return -1;
+	if (name)
+		put_object_name(options, tag->tagged, "%s", name);
 	return options->walk(tag->tagged, OBJ_ANY, data, options);
 }
 
diff --git a/fsck.h b/fsck.h
index dded84b..26c0d41 100644
--- a/fsck.h
+++ b/fsck.h
@@ -33,6 +33,7 @@ struct fsck_options {
 	unsigned strict:1;
 	int *msg_type;
 	struct sha1_array *skiplist;
+	struct decoration *object_names;
 };
 
 #define FSCK_OPTIONS_DEFAULT { NULL, fsck_error_function, 0, NULL }
-- 
2.9.0.278.g1caae67
Previous: Junio C HamanoNext: Junio C Hamano
Message 4 of 16 in “Teach `git fsck` a new option: `--name-objects`”
  1. 0/3 Teach `git fsck` a new option: `--name-objects`Johannes Schindelin, Jul 14, 2016
  2. 1/3 fsck: refactor how to describe objectsJohannes Schindelin, Jul 14, 2016
  3. Junio C HamanoJul 14, 2016
  4. 2/3 fsck_walk(): optionally name objects on the goJohannes Schindelin, Jul 14, 2016
  5. Junio C HamanoJul 14, 2016
  6. Johannes SchindelinJul 17, 2016
  7. 3/3 fsck: optionally show more helpful info for broken linksJohannes Schindelin, Jul 14, 2016
  8. Eric SunshineJul 15, 2016
  9. Johannes SchindelinJul 17, 2016
  10. Junio C HamanoJul 14, 2016
  11. 0/4 Teach `git fsck` a new option: `--name-objects`Johannes Schindelin, Jul 17, 2016
  12. 2/4 fsck_walk(): optionally name objects on the goJohannes Schindelin, Jul 17, 2016
  13. 3/4 fsck: give the error function a chance to see the fsck_optionsJohannes Schindelin, Jul 17, 2016
  14. 4/4 fsck: optionally show more helpful info for broken linksJohannes Schindelin, Jul 17, 2016
  15. 1/4 fsck: refactor how to describe objectsJohannes Schindelin, Jul 17, 2016
  16. Junio C HamanoJul 18, 2016

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.