Thread (3 messages) flat view 3 messages, 2 authors, 2016-06-15

Re: [PATCH v6 04/19] fsck: Offer a function to demote fsck errors to warnings

From: Junio C Hamano <hidden>
Date: 2016-06-15 23:05:24

Johannes Schindelin [off-list ref] writes:
quoted hunk
diff --git a/fsck.c b/fsck.c
index da5717c..8c3caff 100644
--- a/fsck.c
+++ b/fsck.c
@@ -103,13 +103,85 @@ static int fsck_msg_type(enum fsck_msg_id msg_id,
 {
 	int msg_type;
 
-	msg_type = msg_id_info[msg_id].msg_type;
-	if (options->strict && msg_type == FSCK_WARN)
-		msg_type = FSCK_ERROR;
+	assert(msg_id >= 0 && msg_id < FSCK_MSG_MAX);
+
+	if (options->msg_type)
+		msg_type = options->msg_type[msg_id];
+	else {
+		msg_type = msg_id_info[msg_id].msg_type;
+		if (options->strict && msg_type == FSCK_WARN)
+			msg_type = FSCK_ERROR;
+	}
 
 	return msg_type;
 }
Nice.
+static inline int substrcmp(const char *string, int len, const char *match)
+{
+	int match_len = strlen(match);
+	if (match_len != len)
+		return -1;
+	return memcmp(string, match, len);
+}
What this does looks suspiciously like starts_with(), but its name
"substrcmp()" does not give any hint that this is about the beginnig
part of "string"; if anything, it gives a wrong hint that it may be
any substring.  prefixcmp() might be a better name but that was the
old name for !starts_with() so we cannot use it here.  It is a
mouthful, but starts_with_counted() may be.

But the whole thing may be moot.

If we take the "why not upcase the end-user string upfront"
suggestion from the previous review, fsck_set_msg_types() would have
an upcased copy of the end-user string that it can muck with; it can
turn "badfoo=error,poorbar=..." into "BADFOO=error,POORBAR=..."
that is stored in its own writable memory (possibly a strbuf), and
at that point it can afford to NUL-terminate BADFOO=error after
finding where one specification ends with strcspn() before calling
fsck_set_msg_type(), which in turn calls parse_msg_type().

So all parse_msg_type() needs to do is just !strcmp().
+
+static int parse_msg_type(const char *str, int len)
+{
+	if (len < 0)
+		len = strlen(str);
+
+	if (!substrcmp(str, len, "error"))
+		return FSCK_ERROR;
+	else if (!substrcmp(str, len, "warn"))
+		return FSCK_WARN;
quoted hunk
+	else
+		die("Unknown fsck message type: '%.*s'",
+				len, str);
+}
+
+void fsck_set_msg_type(struct fsck_options *options,
+		const char *msg_id, int msg_id_len,
+		const char *msg_type, int msg_type_len)
+{
+	int id = parse_msg_id(msg_id, msg_id_len), type;
+
+	if (id < 0)
+		die("Unhandled message id: %.*s", msg_id_len, msg_id);
+	type = parse_msg_type(msg_type, msg_type_len);
+
+	if (!options->msg_type) {
+		int i;
+		int *msg_type = xmalloc(sizeof(int) * FSCK_MSG_MAX);
+		for (i = 0; i < FSCK_MSG_MAX; i++)
+			msg_type[i] = fsck_msg_type(i, options);
+		options->msg_type = msg_type;
+	}
+
+	options->msg_type[id] = type;
+}
+
+void fsck_set_msg_types(struct fsck_options *options, const char *values)
+{
+	while (*values) {
+		int len = strcspn(values, " ,|"), equal;
+
+		if (!len) {
+			values++;
+			continue;
+		}
+
+		for (equal = 0; equal < len; equal++)
+			if (values[equal] == '=' || values[equal] == ':')
+				break;
+
+		if (equal == len)
+			die("Missing '=': '%.*s'", len, values);
+
+		fsck_set_msg_type(options, values, equal,
+				values + equal + 1, len - equal - 1);
+		values += len;
+	}
+}
+
 __attribute__((format (printf, 4, 5)))
 static int report(struct fsck_options *options, struct object *object,
 	enum fsck_msg_id id, const char *fmt, ...)
@@ -599,6 +671,10 @@ int fsck_object(struct object *obj, void *data, unsigned long size,
 
 int fsck_error_function(struct object *obj, int msg_type, const char *message)
 {
+	if (msg_type == FSCK_WARN) {
+		warning("object %s: %s", sha1_to_hex(obj->sha1), message);
+		return 0;
+	}
 	error("object %s: %s", sha1_to_hex(obj->sha1), message);
 	return 1;
 }
diff --git a/fsck.h b/fsck.h
index f6f268a..edb4540 100644
--- a/fsck.h
+++ b/fsck.h
@@ -6,6 +6,11 @@
 
 struct fsck_options;
 
+void fsck_set_msg_type(struct fsck_options *options,
+		const char *msg_id, int msg_id_len,
+		const char *msg_type, int msg_type_len);
+void fsck_set_msg_types(struct fsck_options *options, const char *values);
+
 /*
  * callback function for fsck_walk
  * type is the expected type of the object or OBJ_ANY
@@ -25,10 +30,11 @@ struct fsck_options {
 	fsck_walk_func walk;
 	fsck_error error_func;
 	unsigned strict:1;
+	int *msg_type;
 };
 
-#define FSCK_OPTIONS_DEFAULT { NULL, fsck_error_function, 0 }
-#define FSCK_OPTIONS_STRICT { NULL, fsck_error_function, 1 }
+#define FSCK_OPTIONS_DEFAULT { NULL, fsck_error_function, 0, NULL }
+#define FSCK_OPTIONS_STRICT { NULL, fsck_error_function, 1, NULL }
 
 /* descend in all linked child objects
  * the return value is:
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help