Re: [PATCH 04/18] Offer a function to demote fsck errors to warnings
Hi Junio, On Mon, 22 Dec 2014, Junio C Hamano wrote: Johannes Schindelin johannes.schinde...@gmx.de writes: For example, try to spot the error here: ... F(ALMOST_HAPPY, INFO) \ F(CANNOT_RECOVER, ERROR) \ F(COFFEE_IS_EMPTY, WARN) \ F(JUST_BEING_CHATTY, INFO) \ F(LIFE_IS_GOOD, INFO) \ F(MISSING_SOMETHING_VITAL, FATAL_ERROR) \ F(NEED_TO_SLEEP, WARN) \ F(SOMETHING_WENT_WRONG, ERROR) \ ... But that is not what is being suggested at all. I already said that FIRST_SOMETHING is fine as a measure to initialize, didn't I? I am only saying that if you have a place to store customized level, you should initialize that part with default levels and always look it up from that place at runtime. It is perfectly fine for the initialization step to take advantage of the ordering and FIRST_SOMETHING constants. Thanks for clarifying, I was worried that you wanted to encode the severity levels explicitly (F(ID, LEVEL) instead of F(ID) in the correct order). The DRY principle also suggests that we should not encode the severity level in two ways (which would leave the door open for inconsistencies). That means that we should not initialize a static array of severity levels, but initialize the array using a loop. Okay, now that we have established that the initial ordering by severity makes sense, let's examine the initialization step. Basically, our approaches differ only in *when* to initialize that array of severity levels: you want to initialize it always, and I want to initialize it only when the severity levels are customized by the caller. Now, let's have a look how the fsck_options are currently initialized. My code follows the convention established with strbufs, argv_arrays, etc: there is a preprocessor definition (_DEFAULT, imitating the _INIT definitions) that allows us to initialize such structs very conveniently. Please note that no loop is required, and certainly no extra code has to be called to initialize the struct. We get away with initializing that array lazily in the fsck_strict_mode() function when we detect that it needs to be initialized, being populated by the very same function that provides the default settings before customization. This is a very robust setup as the knowledge about, say, the size of that array is confined strictly to fsck.c. However, if we had to change the lookup such that it uses an array always, we would have to introduce a function to initialize the struct, always, in particular we would have to find a place to call that initialization function in, say, builtin/fsck.c (actually, in every code path that calls into the fsck machinery). Arguably, the code would get more complex – introducing new call paths just to initialize the fsck_options struct – and I would argue further that there is no gain from an elegance, readability and maintenance point of view: whether the array is initialized lazily or not, it will be initialized the exact same way. All it means is that we have to introduce separate code paths because we would separate explicitly the initialization from the configuration step. Therefore, I do not believe that introducing an fsck_options_init() is what you would really want. An alternative would be to initialize the array at compile time – we would have to violate the DRY principle for that, repeating the severity levels many times over, and we could no longer confine the visibility to the message IDs to fsck.c because not only the size of the array of severity levels would have to be known to every user of fsck.h, but the exact default severity levels themselves, to be able to initialize the struct. But we could initialize the struct with a known set of settings via the _DEFAULTS definition that way. However, you already expressed slight disagreement with the preprocessor magic needed to initialize both the enum and the array of message ID strings from the same list in a way that lets the compiler ensure consistency; I am afraid that if I were to modify _DEFAULTS to populate the entire severity level array, the resulting code would find your utter contempt. I believe, therefore, that this is also not what you want. So that leaves only one alternative: to initialize a global array with the default severity levels at *some* stage. I have no idea what that stage would be, therefore we would have to either establish ugly, and DRY-violating, compile time initialization, or we would have to call a function before using any of the fsck machinery – but that is fragile: it is too easy to forget one call path and access an uninitialized array! Worse, even if we *had* a fully initialized array of default severity levels, we would still have to have an on-demand copy (i.e. lazy initialization) of said array lest we modify the global defaults in fsck_strict_mode()! Essentially, we would just *add* complexity to the current solution, not replace it with anything simpler. Therefore, I believe
Re: [PATCH 04/18] Offer a function to demote fsck errors to warnings
Johannes Schindelin johannes.schinde...@gmx.de writes: However, if we had to change the lookup such that it uses an array always, we would have to introduce a function to initialize the struct, always, in particular we would have to find a place to call that initialization function in, say, builtin/fsck.c (actually, in every code path that calls into the fsck machinery). You would need to call a function to initialize the table if you support customization by reading the configuration files anyway. I am not sure why you think finding such a place is hard. Puzzled. Also I suspect that you can tell the compiler to initialize the array in place with default values, perhaps like this? -- 8 -- #include stdio.h /* sorted by the default severity (lowest impact first) */ #define EVENT_LIST(F) \ F(EVENT_A), \ F(EVENT_B), \ F(EVENT_C), \ F(EVENT_D) #define ID_(event) ID_ ## event enum event_id { EVENT_LIST(ID_) }; enum severity_level { severity_info, severity_warn, severity_error }; /* below this one are INFO */ #define FIRST_WARN_EVENT_ID ID_EVENT_B /* below this one are WARN */ #define FIRST_ERROR_EVENT_IDID_EVENT_C #define STRING_(s) #s #define DESC_(event) \ { \ ID_ ## event, \ STRING_(event), \ (ID_ ## event FIRST_WARN_EVENT_ID \ ? severity_info \ : ID_ ## event FIRST_ERROR_EVENT_ID \ ? severity_warn \ : severity_error) \ } struct event_config { enum event_id id; const char * name; enum severity_level level; } event[] = { EVENT_LIST(DESC_) }; int main(int ac, char **av) { int i; for (i = 0; i sizeof(event) / sizeof(event[0]); i++) { printf(%d, %s, %d\n, event[i].id, event[i].name, event[i].level); } return 0; } -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 04/18] Offer a function to demote fsck errors to warnings
Hi Junio, On Tue, 23 Dec 2014, Junio C Hamano wrote: Johannes Schindelin johannes.schinde...@gmx.de writes: However, if we had to change the lookup such that it uses an array always, we would have to introduce a function to initialize the struct, always, in particular we would have to find a place to call that initialization function in, say, builtin/fsck.c (actually, in every code path that calls into the fsck machinery). You would need to call a function to initialize the table if you support customization by reading the configuration files anyway. Yes, this is the config machinery. But I need employ that only if I want to let the caller customize the severity levels. However, the fsck machinery is also called from places where such a customization is not offered. They would now need to be changed, too. Also I suspect that you can tell the compiler to initialize the array in place with default values, perhaps like this? -- 8 -- #include stdio.h /* sorted by the default severity (lowest impact first) */ #define EVENT_LIST(F) \ F(EVENT_A), \ F(EVENT_B), \ F(EVENT_C), \ F(EVENT_D) #define ID_(event) ID_ ## event enum event_id { EVENT_LIST(ID_) }; enum severity_level { severity_info, severity_warn, severity_error }; /* below this one are INFO */ #define FIRST_WARN_EVENT_ID ID_EVENT_B /* below this one are WARN */ #define FIRST_ERROR_EVENT_ID ID_EVENT_C #define STRING_(s) #s #define DESC_(event) \ { \ ID_ ## event, \ STRING_(event), \ (ID_ ## event FIRST_WARN_EVENT_ID \ ? severity_info \ : ID_ ## event FIRST_ERROR_EVENT_ID \ ? severity_warn \ : severity_error) \ } This is exactly the ugly, ugly preprocessor construct I thought you would meet with contempt. I mean, compared to this, my FUNC() hack is outright pretty ;-) And *still*, this is *just* a global table with defaults. I would *still* need to copy-on-write when the first customization of the severity level takes place because I cannot allow the global defaults to be modified by one caller (that would defeat the whole purpose of having per-caller settings bundled in the fsck_options struct). You see, I still would need to have a lazy initialization, the complexity in that part would not be reduced at all. So I am afraid that this approach really adds complexity rather than replacing it with something simpler than my current code. Ciao, Dscho -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 04/18] Offer a function to demote fsck errors to warnings
Johannes Schindelin johannes.schinde...@gmx.de writes: And *still*, this is *just* a global table with defaults. I would *still* need to copy-on-write when the first customization of the severity level takes place because I cannot allow the global defaults to be modified by one caller (that would defeat the whole purpose of having per-caller settings bundled in the fsck_options struct). If you allocate a per-invocation fsck_options struct, then the initialization the default with code is dead easy---you can just do it immediately after you x[cm]alloc()---no? What am I missing? -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 04/18] Offer a function to demote fsck errors to warnings
Hi Junio, On Tue, 23 Dec 2014, Junio C Hamano wrote: Johannes Schindelin johannes.schinde...@gmx.de writes: And *still*, this is *just* a global table with defaults. I would *still* need to copy-on-write when the first customization of the severity level takes place because I cannot allow the global defaults to be modified by one caller (that would defeat the whole purpose of having per-caller settings bundled in the fsck_options struct). If you allocate a per-invocation fsck_options struct, then the initialization the default with code is dead easy---you can just do it immediately after you x[cm]alloc()---no? There is no alloc. Right now, the initialization reads: struct fsck_options options = strict ? FSCK_OPTIONS_STRICT : FSCK_OPTIONS_DEFAULT; Ciao, Dscho -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 04/18] Offer a function to demote fsck errors to warnings
On Tue, Dec 23, 2014 at 9:28 AM, Johannes Schindelin johannes.schinde...@gmx.de wrote: Johannes Schindelin johannes.schinde...@gmx.de writes: And *still*, this is *just* a global table with defaults. I would *still* need to copy-on-write when the first customization of the severity level takes place because I cannot allow the global defaults to be modified by one caller (that would defeat the whole purpose of having per-caller settings bundled in the fsck_options struct). There is no alloc. Right now, the initialization reads: struct fsck_options options = strict ? FSCK_OPTIONS_STRICT : FSCK_OPTIONS_DEFAULT; Then it is just the matter of having fsck_options_init(options); if (strict) options.some_field = make_it_strict; as the first few statements, no? I am not sure why it is so difficult -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 04/18] Offer a function to demote fsck errors to warnings
Hi Junio, On Tue, 23 Dec 2014, Junio C Hamano wrote: On Tue, Dec 23, 2014 at 9:28 AM, Johannes Schindelin johannes.schinde...@gmx.de wrote: Johannes Schindelin johannes.schinde...@gmx.de writes: And *still*, this is *just* a global table with defaults. I would *still* need to copy-on-write when the first customization of the severity level takes place because I cannot allow the global defaults to be modified by one caller (that would defeat the whole purpose of having per-caller settings bundled in the fsck_options struct). There is no alloc. Right now, the initialization reads: struct fsck_options options = strict ? FSCK_OPTIONS_STRICT : FSCK_OPTIONS_DEFAULT; Then it is just the matter of having fsck_options_init(options); if (strict) options.some_field = make_it_strict; as the first few statements, no? I am not sure why it is so difficult It is not difficult. But I try to avoid complexity when I can. Since you asked specifically, I will introduce it, though. Hopefully still this year (I'll not be available for a while starting tomorrow). Ciao, Dscho -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 04/18] Offer a function to demote fsck errors to warnings
Hi Junio, On Wed, 10 Dec 2014, Junio C Hamano wrote: Johannes Schindelin johannes.schinde...@gmx.de writes: 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 function added by this commit parses a list of settings in the form: missing-email=warn,bad-name=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 default to all FSCK_ERROR in those cases. Signed-off-by: Johannes Schindelin johannes.schinde...@gmx.de --- fsck.c | 58 ++ fsck.h | 7 +-- 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/fsck.c b/fsck.c index 05b146c..9e6d70f 100644 --- a/fsck.c +++ b/fsck.c @@ -97,9 +97,63 @@ static int parse_msg_id(const char *text, int len) int fsck_msg_type(enum fsck_msg_id msg_id, struct fsck_options *options) { + if (options-strict_mode msg_id = 0 msg_id FSCK_MSG_MAX) + return options-strict_mode[msg_id]; + if (options-strict) + return FSCK_ERROR; return msg_id FIRST_WARNING ? FSCK_ERROR : FSCK_WARN; } Hmm, if you are later going to allow demoting (hopefully also promoting) error to warn, etc., would the comparison between msg_id and FIRST_WARNING make much sense? A later patch indeed adds that option. The reason the comparison still makes sense is that the pure infos do not return at all so far, but all of the reported warnings are fatal in strict mode (i.e. when receive.fsckObjects = true). In another later patch it is made possible to promote even infos (such as 'missing tagger') to warnings or even errors, and that is when the return FSCK_ERROR is changed to return msg_id FIRST_INFO ? FSCK_ERROR : FSCK_WARN. In other words, at some point wouldn't we be better off with something like this struct { enum id; const char *id_string; enum error_level { FSCK_PASS, FSCK_WARN, FSCK_ERROR }; } possible_fsck_errors[]; I considered that, and Michael Haggerty also suggested that in a private mail. However, I find that there is a clear hierarchy in the default messages: fatal errors, errors, warnings and infos. This should be reflected by the order IMHO. But I guess it would make a lot of sense to insert those levels as special enum values to make it harder to forget to adjust, say, #define FIRST_WARNING FSCK_MSG_BAD_FILEMODE when introducing another warning that sorts before said ID alphabetically. In other words, I think that we can really afford to put something like ... FUNC(UNKNOWN_TYPE) \ FUNC(ZERO_PADDED_DATE) \ FUNC(___WARNINGS) \ FUNC(BAD_FILEMODE) \ FUNC(EMPTY_NAME) \ ... at the price of making the parsing a little more complicated and wasting a slight bit of more space for the msg_id_str array. What do you think? Ciao, Dscho Ciao, Dscho -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 04/18] Offer a function to demote fsck errors to warnings
Johannes Schindelin johannes.schinde...@gmx.de writes: In other words, at some point wouldn't we be better off with something like this struct { enum id; const char *id_string; enum error_level { FSCK_PASS, FSCK_WARN, FSCK_ERROR }; } possible_fsck_errors[]; I considered that, and Michael Haggerty also suggested that in a private mail. However, I find that there is a clear hierarchy in the default messages: fatal errors, errors, warnings and infos. I am glad I am not alone ;-) These classes are ordered from more severe to less, but I do not think it makes much sense to force the default view of if you customize to demote a questionable Q that is classified as an error by default as an warning, you must demote all the other ones that we deem less serious than Q, which come earlier (or later---I do not remember which) in our predefined list. So in that sense, I do not consider that various kinds of questionables fsck can detect are hierarchical at all. I do agree that it makes it easier to code the initialization of such an array to have up to this point we assign the level 'fatal error' by default constants. Then the initialization can become for (i = 0; i FIRST_WARN; i++) possible_fsck_errors[i].error_level = FSCK_INFO; while (i FIRST_ERROR) possible_fsck_errors[i++].error_level = FSCK_WARN; while (i ARRAY_SIZE(possible_fsck_errors)) possible_fsck_errors[i++].error_level = FSCK_ERROR; or something. So I am not against the FIRST_WARNING constant at all, but I find it very questionable in a fully customizable system to use such a constant anywhere other than the initialization time. -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 04/18] Offer a function to demote fsck errors to warnings
Hi Junio, On Mon, 22 Dec 2014, Junio C Hamano wrote: Johannes Schindelin johannes.schinde...@gmx.de writes: In other words, at some point wouldn't we be better off with something like this struct { enum id; const char *id_string; enum error_level { FSCK_PASS, FSCK_WARN, FSCK_ERROR }; } possible_fsck_errors[]; I considered that, and Michael Haggerty also suggested that in a private mail. However, I find that there is a clear hierarchy in the default messages: fatal errors, errors, warnings and infos. I am glad I am not alone ;-) These classes are ordered from more severe to less, but I do not think it makes much sense to force the default view of if you customize to demote a questionable Q that is classified as an error by default as an warning, you must demote all the other ones that we deem less serious than Q, which come earlier (or later---I do not remember which) in our predefined list. So in that sense, I do not consider that various kinds of questionables fsck can detect are hierarchical at all. Oh, but please understand that this hierarchy only applies to the default settings. All of these settings can be overridden individually – and the first override will initialize a full array with the default settings. So the order really only plays a role for the defaults, no more. I do agree that it makes it easier to code the initialization of such an array to have up to this point we assign the level 'fatal error' by default constants. Then the initialization can become for (i = 0; i FIRST_WARN; i++) possible_fsck_errors[i].error_level = FSCK_INFO; while (i FIRST_ERROR) possible_fsck_errors[i++].error_level = FSCK_WARN; while (i ARRAY_SIZE(possible_fsck_errors)) possible_fsck_errors[i++].error_level = FSCK_ERROR; or something. So I am not against the FIRST_WARNING constant at all, but I find it very questionable in a fully customizable system to use such a constant anywhere other than the initialization time. This is indeed the case. The code we are discussing comes after the if (options-strict_mode) return options-strict_mode[msg_id]; In other words, once the overrides are in place, the default settings are skipped entirely. Ciao, Dscho
Re: [PATCH 04/18] Offer a function to demote fsck errors to warnings
Johannes Schindelin johannes.schinde...@gmx.de writes: Hi Junio, On Mon, 22 Dec 2014, Junio C Hamano wrote: Johannes Schindelin johannes.schinde...@gmx.de writes: In other words, at some point wouldn't we be better off with something like this struct { enum id; const char *id_string; enum error_level { FSCK_PASS, FSCK_WARN, FSCK_ERROR }; } possible_fsck_errors[]; I considered that, and Michael Haggerty also suggested that in a private mail. However, I find that there is a clear hierarchy in the default messages: fatal errors, errors, warnings and infos. I am glad I am not alone ;-) ... Oh, but please understand that this hierarchy only applies to the default settings. All of these settings can be overridden individually – and the first override will initialize a full array with the default settings. But that means that the runtime needs to switch between two code with and without override, no? if (options-strict_mode) return options-strict_mode[msg_id]; In other words, I think this is misleading and unnecessary optimization for the full array allocation. A code that uses an array of a struct like the above that Michael and I independently suggested would initialize once with or without an override and then at the runtime there is no if the array is there use it conditional. I do not know why Michael suggested the same thing, but the reason why I prefer that arrangement is because I think it would be easier to read and maintain. Thanks. -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 04/18] Offer a function to demote fsck errors to warnings
Hi Junio, On Mon, 22 Dec 2014, Junio C Hamano wrote: Johannes Schindelin johannes.schinde...@gmx.de writes: On Mon, 22 Dec 2014, Junio C Hamano wrote: Johannes Schindelin johannes.schinde...@gmx.de writes: In other words, at some point wouldn't we be better off with something like this struct { enum id; const char *id_string; enum error_level { FSCK_PASS, FSCK_WARN, FSCK_ERROR }; } possible_fsck_errors[]; I considered that, and Michael Haggerty also suggested that in a private mail. However, I find that there is a clear hierarchy in the default messages: fatal errors, errors, warnings and infos. I am glad I am not alone ;-) ... Oh, but please understand that this hierarchy only applies to the default settings. All of these settings can be overridden individually – and the first override will initialize a full array with the default settings. But that means that the runtime needs to switch between two code with and without override, no? if (options-strict_mode) return options-strict_mode[msg_id]; In other words, I think this is misleading and unnecessary optimization for the full array allocation. A code that uses an array of a struct like the above that Michael and I independently suggested would initialize once with or without an override and then at the runtime there is no if the array is there use it conditional. I do not know why Michael suggested the same thing, but the reason why I prefer that arrangement is because I think it would be easier to read and maintain. Well, I disagree that it would be easier to maintain, because it appears to me that the clear hierarchy keeps things simple. For example if some clearly fatal error is clustered with non-fatal ones due to alphabetical ordering, it is much harder to spot when it is marked as a demoteable error by mistake. For example, try to spot the error here: ... F(ALMOST_HAPPY, INFO) \ F(CANNOT_RECOVER, ERROR) \ F(COFFEE_IS_EMPTY, WARN) \ F(JUST_BEING_CHATTY, INFO) \ F(LIFE_IS_GOOD, INFO) \ F(MISSING_SOMETHING_VITAL, FATAL_ERROR) \ F(NEED_TO_SLEEP, WARN) \ F(SOMETHING_WENT_WRONG, ERROR) \ ... Personally, I find it very, very hard to spot that CANNOT_RECOVER is marked as a mere ERROR instead of a FATAL_ERROR. Even if it is nicely alphabetically ordered. I will sleep over this, though. Maybe I can come up with a solution that makes all three of us happy. Ciao, Dscho
Re: [PATCH 04/18] Offer a function to demote fsck errors to warnings
Johannes Schindelin johannes.schinde...@gmx.de writes: For example, try to spot the error here: ... F(ALMOST_HAPPY, INFO) \ F(CANNOT_RECOVER, ERROR) \ F(COFFEE_IS_EMPTY, WARN) \ F(JUST_BEING_CHATTY, INFO) \ F(LIFE_IS_GOOD, INFO) \ F(MISSING_SOMETHING_VITAL, FATAL_ERROR) \ F(NEED_TO_SLEEP, WARN) \ F(SOMETHING_WENT_WRONG, ERROR) \ ... But that is not what is being suggested at all. I already said that FIRST_SOMETHING is fine as a measure to initialize, didn't I? I am only saying that if you have a place to store customized level, you should initialize that part with default levels and always look it up from that place at runtime. It is perfectly fine for the initialization step to take advantage of the ordering and FIRST_SOMETHING constants. -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 04/18] Offer a function to demote fsck errors to warnings
Johannes Schindelin johannes.schinde...@gmx.de writes: 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 function added by this commit parses a list of settings in the form: missing-email=warn,bad-name=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 default to all FSCK_ERROR in those cases. Signed-off-by: Johannes Schindelin johannes.schinde...@gmx.de --- fsck.c | 58 ++ fsck.h | 7 +-- 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/fsck.c b/fsck.c index 05b146c..9e6d70f 100644 --- a/fsck.c +++ b/fsck.c @@ -97,9 +97,63 @@ static int parse_msg_id(const char *text, int len) int fsck_msg_type(enum fsck_msg_id msg_id, struct fsck_options *options) { + if (options-strict_mode msg_id = 0 msg_id FSCK_MSG_MAX) + return options-strict_mode[msg_id]; + if (options-strict) + return FSCK_ERROR; return msg_id FIRST_WARNING ? FSCK_ERROR : FSCK_WARN; } Hmm, if you are later going to allow demoting (hopefully also promoting) error to warn, etc., would the comparison between msg_id and FIRST_WARNING make much sense? In other words, at some point wouldn't we be better off with something like this struct { enum id; const char *id_string; enum error_level { FSCK_PASS, FSCK_WARN, FSCK_ERROR }; } possible_fsck_errors[]; -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 04/18] 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 function added by this commit parses a list of settings in the form: missing-email=warn,bad-name=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 default to all FSCK_ERROR in those cases. Signed-off-by: Johannes Schindelin johannes.schinde...@gmx.de --- fsck.c | 58 ++ fsck.h | 7 +-- 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/fsck.c b/fsck.c index 05b146c..9e6d70f 100644 --- a/fsck.c +++ b/fsck.c @@ -97,9 +97,63 @@ static int parse_msg_id(const char *text, int len) int fsck_msg_type(enum fsck_msg_id msg_id, struct fsck_options *options) { + if (options-strict_mode msg_id = 0 msg_id FSCK_MSG_MAX) + return options-strict_mode[msg_id]; + if (options-strict) + return FSCK_ERROR; return msg_id FIRST_WARNING ? FSCK_ERROR : FSCK_WARN; } +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); +} + +void fsck_strict_mode(struct fsck_options *options, const char *mode) +{ + int type = FSCK_ERROR; + + if (!options-strict_mode) { + int i; + int *strict_mode = malloc(sizeof(int) * FSCK_MSG_MAX); + for (i = 0; i FSCK_MSG_MAX; i++) + strict_mode[i] = fsck_msg_type(i, options); + options-strict_mode = strict_mode; + } + + while (*mode) { + int len = strcspn(mode, ,|), equal, msg_id; + + if (!len) { + mode++; + continue; + } + + for (equal = 0; equal len; equal++) + if (mode[equal] == '=') + break; + + if (equal len) { + const char *type_str = mode + equal + 1; + int type_len = len - equal - 1; + if (!substrcmp(type_str, type_len, error)) + type = FSCK_ERROR; + else if (!substrcmp(type_str, type_len, warn)) + type = FSCK_WARN; + else + die(Unknown fsck message type: '%.*s', + len - equal - 1, type_str); + } + + msg_id = parse_msg_id(mode, equal); + options-strict_mode[msg_id] = type; + mode += len; + } +} + __attribute__((format (printf, 4, 5))) static int report(struct fsck_options *options, struct object *object, enum fsck_msg_id id, const char *fmt, ...) @@ -585,6 +639,10 @@ int fsck_object(struct object *obj, void *data, unsigned long size, int fsck_error_function(struct object *obj, int type, const char *message) { + if (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 a18e9a6..9d67ea2 100644 --- a/fsck.h +++ b/fsck.h @@ -6,6 +6,8 @@ struct fsck_options; +void fsck_strict_mode(struct fsck_options *options, const char *mode); + /* * callback function for fsck_walk * type is the expected type of the object or OBJ_ANY @@ -25,10 +27,11 @@ struct fsck_options { fsck_walk_func walk; fsck_error error_func; int strict:1; + int *strict_mode; }; -#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: -- 2.0.0.rc3.9669.g840d1f9 -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html