Skip to content

Commit 0282f4d

Browse files
dschogitster
authored andcommitted
fsck: offer a function to demote fsck errors to warnings
There are legacy repositories out there whose older commits and tags have issues that prevent pushing them when 'receive.fsckObjects' is set. One real-life example is a commit object that has been hand-crafted to list two authors. Often, it is not possible to fix those issues without disrupting the work with said repositories, yet it is still desirable to perform checks by setting `receive.fsckObjects = true`. This commit is the first step to allow demoting specific fsck issues to mere warnings. The `fsck_set_msg_types()` function added by this commit parses a list of settings in the form: missingemail=warn,badname=warn,... Unfortunately, the FSCK_WARN/FSCK_ERROR flag is only really heeded by git fsck so far, but other call paths (e.g. git index-pack --strict) error out *always* no matter what type was specified. Therefore, we need to take extra care to set all message types to FSCK_ERROR by default in those cases. Signed-off-by: Johannes Schindelin <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent f417eed commit 0282f4d

File tree

2 files changed

+80
-5
lines changed

2 files changed

+80
-5
lines changed

fsck.c

Lines changed: 73 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,13 +108,79 @@ static int fsck_msg_type(enum fsck_msg_id msg_id,
108108
{
109109
int msg_type;
110110

111-
msg_type = msg_id_info[msg_id].msg_type;
112-
if (options->strict && msg_type == FSCK_WARN)
113-
msg_type = FSCK_ERROR;
111+
assert(msg_id >= 0 && msg_id < FSCK_MSG_MAX);
112+
113+
if (options->msg_type)
114+
msg_type = options->msg_type[msg_id];
115+
else {
116+
msg_type = msg_id_info[msg_id].msg_type;
117+
if (options->strict && msg_type == FSCK_WARN)
118+
msg_type = FSCK_ERROR;
119+
}
114120

115121
return msg_type;
116122
}
117123

124+
static int parse_msg_type(const char *str)
125+
{
126+
if (!strcmp(str, "error"))
127+
return FSCK_ERROR;
128+
else if (!strcmp(str, "warn"))
129+
return FSCK_WARN;
130+
else
131+
die("Unknown fsck message type: '%s'", str);
132+
}
133+
134+
void fsck_set_msg_type(struct fsck_options *options,
135+
const char *msg_id, const char *msg_type)
136+
{
137+
int id = parse_msg_id(msg_id), type;
138+
139+
if (id < 0)
140+
die("Unhandled message id: %s", msg_id);
141+
type = parse_msg_type(msg_type);
142+
143+
if (!options->msg_type) {
144+
int i;
145+
int *msg_type = xmalloc(sizeof(int) * FSCK_MSG_MAX);
146+
for (i = 0; i < FSCK_MSG_MAX; i++)
147+
msg_type[i] = fsck_msg_type(i, options);
148+
options->msg_type = msg_type;
149+
}
150+
151+
options->msg_type[id] = type;
152+
}
153+
154+
void fsck_set_msg_types(struct fsck_options *options, const char *values)
155+
{
156+
char *buf = xstrdup(values), *to_free = buf;
157+
int done = 0;
158+
159+
while (!done) {
160+
int len = strcspn(buf, " ,|"), equal;
161+
162+
done = !buf[len];
163+
if (!len) {
164+
buf++;
165+
continue;
166+
}
167+
buf[len] = '\0';
168+
169+
for (equal = 0;
170+
equal < len && buf[equal] != '=' && buf[equal] != ':';
171+
equal++)
172+
buf[equal] = tolower(buf[equal]);
173+
buf[equal] = '\0';
174+
175+
if (equal == len)
176+
die("Missing '=': '%s'", buf);
177+
178+
fsck_set_msg_type(options, buf, buf + equal + 1);
179+
buf += len + 1;
180+
}
181+
free(to_free);
182+
}
183+
118184
__attribute__((format (printf, 4, 5)))
119185
static int report(struct fsck_options *options, struct object *object,
120186
enum fsck_msg_id id, const char *fmt, ...)
@@ -604,6 +670,10 @@ int fsck_object(struct object *obj, void *data, unsigned long size,
604670

605671
int fsck_error_function(struct object *obj, int msg_type, const char *message)
606672
{
673+
if (msg_type == FSCK_WARN) {
674+
warning("object %s: %s", sha1_to_hex(obj->sha1), message);
675+
return 0;
676+
}
607677
error("object %s: %s", sha1_to_hex(obj->sha1), message);
608678
return 1;
609679
}

fsck.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66

77
struct fsck_options;
88

9+
void fsck_set_msg_type(struct fsck_options *options,
10+
const char *msg_id, const char *msg_type);
11+
void fsck_set_msg_types(struct fsck_options *options, const char *values);
12+
913
/*
1014
* callback function for fsck_walk
1115
* type is the expected type of the object or OBJ_ANY
@@ -25,10 +29,11 @@ struct fsck_options {
2529
fsck_walk_func walk;
2630
fsck_error error_func;
2731
unsigned strict:1;
32+
int *msg_type;
2833
};
2934

30-
#define FSCK_OPTIONS_DEFAULT { NULL, fsck_error_function, 0 }
31-
#define FSCK_OPTIONS_STRICT { NULL, fsck_error_function, 1 }
35+
#define FSCK_OPTIONS_DEFAULT { NULL, fsck_error_function, 0, NULL }
36+
#define FSCK_OPTIONS_STRICT { NULL, fsck_error_function, 1, NULL }
3237

3338
/* descend in all linked child objects
3439
* the return value is:

0 commit comments

Comments
 (0)