[pacman-dev] [PATCH] Show progress processing hooks
Introduces the ALPM_EVENT_HOOK_RUN_{START,DONE} events that are triggered at the start and end of running an individual hook. Signed-off-by: Allan McRae <allan@archlinux.org> --- The output looks like: $ sudo ./src/pacman/pacman -S abs warning: abs-2.4.4-2 is up to date -- reinstalling resolving dependencies... looking for conflicting packages... Packages (1) abs-2.4.4-2 Total Installed Size: 0.03 MiB Net Upgrade Size: 0.00 MiB :: Proceed with installation? [Y/n] (1/1) checking keys in keyring [######################] 100% (1/1) checking package integrity [######################] 100% (1/1) loading package files [######################] 100% (1/1) checking for file conflicts [######################] 100% :: Processing package changes... (1/1) reinstalling abs [######################] 100% :: Running post-transaction hooks... (1/2) one.hook (2/2) two.hook lib/libalpm/alpm.h | 18 +++++++++++++++++- lib/libalpm/hook.c | 14 +++++++++++++- src/pacman/callback.c | 13 +++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h index 8fcdfdf..f6e6b86 100644 --- a/lib/libalpm/alpm.h +++ b/lib/libalpm/alpm.h @@ -461,7 +461,11 @@ typedef enum _alpm_event_type_t { /** Processing hooks will be started. */ ALPM_EVENT_HOOK_START, /** Processing hooks is finished. */ - ALPM_EVENT_HOOK_DONE + ALPM_EVENT_HOOK_DONE, + /** A hook is starting */ + ALPM_EVENT_HOOK_RUN_START, + /** A hook has finnished runnning */ + ALPM_EVENT_HOOK_RUN_DONE } alpm_event_type_t; typedef struct _alpm_event_any_t { @@ -559,6 +563,17 @@ typedef struct _alpm_event_hook_t { alpm_hook_when_t when; } alpm_event_hook_t; +typedef struct _alpm_event_hook_run_t { + /** Type of event.*/ + alpm_event_type_t type; + /** Text to be outputted */ + const char *desc; + /** position of hook being run */ + size_t position; + /** total hooks being run */ + size_t total; +} alpm_event_hook_run_t; + /** Events. * This is an union passed to the callback, that allows the frontend to know * which type of event was triggered (via type). It is then possible to @@ -576,6 +591,7 @@ typedef union _alpm_event_t { alpm_event_pacnew_created_t pacnew_created; alpm_event_pacsave_created_t pacsave_created; alpm_event_hook_t hook; + alpm_event_hook_run_t hook_run; } alpm_event_t; /** Event callback. */ diff --git a/lib/libalpm/hook.c b/lib/libalpm/hook.c index df41fce..acd571d 100644 --- a/lib/libalpm/hook.c +++ b/lib/libalpm/hook.c @@ -611,6 +611,7 @@ static int _alpm_hook_run_hook(alpm_handle_t *handle, struct _alpm_hook_t *hook) int _alpm_hook_run(alpm_handle_t *handle, alpm_hook_when_t when) { alpm_event_hook_t event = { .when = when }; + alpm_event_hook_run_t hook_event; alpm_list_t *i, *hooks = NULL, *hooks_triggered = NULL; const char *suffix = ".hook"; size_t suflen = strlen(suffix), triggered = 0; @@ -725,12 +726,23 @@ int _alpm_hook_run(alpm_handle_t *handle, alpm_hook_when_t when) event.type = ALPM_EVENT_HOOK_START; EVENT(handle, &event); - for(i = hooks_triggered; i; i = i->next) { + hook_event.position = 1; + hook_event.total = triggered; + + for(i = hooks_triggered; i; i = i->next, hook_event.position++) { struct _alpm_hook_t *hook = i->data; _alpm_log(handle, ALPM_LOG_DEBUG, "running hook %s\n", hook->name); + + hook_event.type = ALPM_EVENT_HOOK_RUN_START; + hook_event.desc = hook->name; + EVENT(handle, &hook_event); + if(_alpm_hook_run_hook(handle, hook) != 0 && hook->abort_on_fail) { ret = -1; } + + hook_event.type = ALPM_EVENT_HOOK_RUN_DONE; + EVENT(handle, &hook_event); } event.type = ALPM_EVENT_HOOK_DONE; diff --git a/src/pacman/callback.c b/src/pacman/callback.c index c33bd24..ae725d3 100644 --- a/src/pacman/callback.c +++ b/src/pacman/callback.c @@ -172,6 +172,18 @@ void cb_event(alpm_event_t *event) event->hook.when == ALPM_HOOK_PRE_TRANSACTION ? _("pre-transaction") : _("post-transaction")); break; + case ALPM_EVENT_HOOK_RUN_START: + { + alpm_event_hook_run_t *e = &event->hook_run; + int digits = 1; + size_t tmp = e->total; + while((tmp /= 10)) { + ++digits; + } + printf("(%*zu/%*zu) %s\n", digits, e->position, + digits, e->total, e->desc); + } + break; case ALPM_EVENT_CHECKDEPS_START: printf(_("checking dependencies...\n")); break; @@ -339,6 +351,7 @@ void cb_event(alpm_event_t *event) case ALPM_EVENT_RETRIEVE_DONE: case ALPM_EVENT_RETRIEVE_FAILED: case ALPM_EVENT_HOOK_DONE: + case ALPM_EVENT_HOOK_RUN_DONE: /* we can safely ignore those as well */ case ALPM_EVENT_PKGDOWNLOAD_START: case ALPM_EVENT_PKGDOWNLOAD_DONE: -- 2.6.4
On 12/14/15 at 03:51pm, Allan McRae wrote:
Introduces the ALPM_EVENT_HOOK_RUN_{START,DONE} events that are triggered at the start and end of running an individual hook.
Signed-off-by: Allan McRae <allan@archlinux.org> --- ... lib/libalpm/alpm.h | 18 +++++++++++++++++- lib/libalpm/hook.c | 14 +++++++++++++- src/pacman/callback.c | 13 +++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) ... diff --git a/src/pacman/callback.c b/src/pacman/callback.c index c33bd24..ae725d3 100644 --- a/src/pacman/callback.c +++ b/src/pacman/callback.c @@ -172,6 +172,18 @@ void cb_event(alpm_event_t *event) event->hook.when == ALPM_HOOK_PRE_TRANSACTION ? _("pre-transaction") : _("post-transaction")); break; + case ALPM_EVENT_HOOK_RUN_START: + { + alpm_event_hook_run_t *e = &event->hook_run; + int digits = 1; + size_t tmp = e->total; + while((tmp /= 10)) { + ++digits; + }
I would suggest extracting the above bit into a function since we do the exact same calculation elsewhere and cb_event is already massive.
+ printf("(%*zu/%*zu) %s\n", digits, e->position, + digits, e->total, e->desc); + } + break; case ALPM_EVENT_CHECKDEPS_START: printf(_("checking dependencies...\n")); break; @@ -339,6 +351,7 @@ void cb_event(alpm_event_t *event) case ALPM_EVENT_RETRIEVE_DONE: case ALPM_EVENT_RETRIEVE_FAILED: case ALPM_EVENT_HOOK_DONE: + case ALPM_EVENT_HOOK_RUN_DONE: /* we can safely ignore those as well */ case ALPM_EVENT_PKGDOWNLOAD_START: case ALPM_EVENT_PKGDOWNLOAD_DONE: -- 2.6.4
Also include the abort_on_fail flag so the frontend can let the user know which hook(s) are responsible. Signed-off-by: Olivier Brunel <jjk@jjacky.com> --- lib/libalpm/alpm.h | 6 +++++- lib/libalpm/hook.c | 7 +++++-- src/pacman/callback.c | 4 ++++ 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h index f6e6b86..52cbd51 100644 --- a/lib/libalpm/alpm.h +++ b/lib/libalpm/alpm.h @@ -465,7 +465,9 @@ typedef enum _alpm_event_type_t { /** A hook is starting */ ALPM_EVENT_HOOK_RUN_START, /** A hook has finnished runnning */ - ALPM_EVENT_HOOK_RUN_DONE + ALPM_EVENT_HOOK_RUN_DONE, + /** A hook has failed to run. */ + ALPM_EVENT_HOOK_RUN_FAILED } alpm_event_type_t; typedef struct _alpm_event_any_t { @@ -568,6 +570,8 @@ typedef struct _alpm_event_hook_run_t { alpm_event_type_t type; /** Text to be outputted */ const char *desc; + /** Whether the hook has the AbortOnFail flag set (pre-transaction only) */ + int abort_on_fail; /** position of hook being run */ size_t position; /** total hooks being run */ diff --git a/lib/libalpm/hook.c b/lib/libalpm/hook.c index acd571d..41dacbe 100644 --- a/lib/libalpm/hook.c +++ b/lib/libalpm/hook.c @@ -731,17 +731,20 @@ int _alpm_hook_run(alpm_handle_t *handle, alpm_hook_when_t when) for(i = hooks_triggered; i; i = i->next, hook_event.position++) { struct _alpm_hook_t *hook = i->data; + int r; _alpm_log(handle, ALPM_LOG_DEBUG, "running hook %s\n", hook->name); hook_event.type = ALPM_EVENT_HOOK_RUN_START; + hook_event.abort_on_fail = hook->abort_on_fail; hook_event.desc = hook->name; EVENT(handle, &hook_event); - if(_alpm_hook_run_hook(handle, hook) != 0 && hook->abort_on_fail) { + r = _alpm_hook_run_hook(handle, hook); + if(r != 0 && hook->abort_on_fail) { ret = -1; } - hook_event.type = ALPM_EVENT_HOOK_RUN_DONE; + hook_event.type = (r != 0) ? ALPM_EVENT_HOOK_RUN_FAILED : ALPM_EVENT_HOOK_RUN_DONE; EVENT(handle, &hook_event); } diff --git a/src/pacman/callback.c b/src/pacman/callback.c index ae725d3..02d9b64 100644 --- a/src/pacman/callback.c +++ b/src/pacman/callback.c @@ -184,6 +184,10 @@ void cb_event(alpm_event_t *event) digits, e->total, e->desc); } break; + case ALPM_EVENT_HOOK_RUN_FAILED: + if (event->hook_run.abort_on_fail) + printf(_("Hook failed; Abort transaction.\n")); + break; case ALPM_EVENT_CHECKDEPS_START: printf(_("checking dependencies...\n")); break; -- 2.6.4
On 12/14/15 at 05:55pm, Olivier Brunel wrote:
Also include the abort_on_fail flag so the frontend can let the user know which hook(s) are responsible.
Signed-off-by: Olivier Brunel <jjk@jjacky.com> ---
This seems like overkill. A failed AbortOnFail hook will already generate 3 error messages (assuming the hook itself prints one). We could just label AbortOnFail hooks as such when we print the info during HOOK_RUN_START. Alternatively, and this might be preferable behavior anyway, we could simply stop running PreTransaction hooks as soon as an AbortOnFail hook fails.
lib/libalpm/alpm.h | 6 +++++- lib/libalpm/hook.c | 7 +++++-- src/pacman/callback.c | 4 ++++ 3 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h index f6e6b86..52cbd51 100644 --- a/lib/libalpm/alpm.h +++ b/lib/libalpm/alpm.h @@ -465,7 +465,9 @@ typedef enum _alpm_event_type_t { /** A hook is starting */ ALPM_EVENT_HOOK_RUN_START, /** A hook has finnished runnning */ - ALPM_EVENT_HOOK_RUN_DONE + ALPM_EVENT_HOOK_RUN_DONE, + /** A hook has failed to run. */ + ALPM_EVENT_HOOK_RUN_FAILED } alpm_event_type_t;
typedef struct _alpm_event_any_t { @@ -568,6 +570,8 @@ typedef struct _alpm_event_hook_run_t { alpm_event_type_t type; /** Text to be outputted */ const char *desc; + /** Whether the hook has the AbortOnFail flag set (pre-transaction only) */
This is not strictly true. Setting AbortOnFail on a PostTransaction hook generates a warning, but leaves the flag set. In that case your callback will falsely claim that it aborted the transaction.
+ int abort_on_fail; /** position of hook being run */ size_t position; /** total hooks being run */ diff --git a/lib/libalpm/hook.c b/lib/libalpm/hook.c index acd571d..41dacbe 100644 --- a/lib/libalpm/hook.c +++ b/lib/libalpm/hook.c @@ -731,17 +731,20 @@ int _alpm_hook_run(alpm_handle_t *handle, alpm_hook_when_t when)
for(i = hooks_triggered; i; i = i->next, hook_event.position++) { struct _alpm_hook_t *hook = i->data; + int r; _alpm_log(handle, ALPM_LOG_DEBUG, "running hook %s\n", hook->name);
hook_event.type = ALPM_EVENT_HOOK_RUN_START; + hook_event.abort_on_fail = hook->abort_on_fail; hook_event.desc = hook->name; EVENT(handle, &hook_event);
- if(_alpm_hook_run_hook(handle, hook) != 0 && hook->abort_on_fail) { + r = _alpm_hook_run_hook(handle, hook); + if(r != 0 && hook->abort_on_fail) { ret = -1; }
- hook_event.type = ALPM_EVENT_HOOK_RUN_DONE; + hook_event.type = (r != 0) ? ALPM_EVENT_HOOK_RUN_FAILED : ALPM_EVENT_HOOK_RUN_DONE; EVENT(handle, &hook_event); }
diff --git a/src/pacman/callback.c b/src/pacman/callback.c index ae725d3..02d9b64 100644 --- a/src/pacman/callback.c +++ b/src/pacman/callback.c @@ -184,6 +184,10 @@ void cb_event(alpm_event_t *event) digits, e->total, e->desc); } break; + case ALPM_EVENT_HOOK_RUN_FAILED: + if (event->hook_run.abort_on_fail) + printf(_("Hook failed; Abort transaction.\n"));
Always use braces.
+ break; case ALPM_EVENT_CHECKDEPS_START: printf(_("checking dependencies...\n")); break; -- 2.6.4
On Mon, 14 Dec 2015 12:47:26 -0500 Andrew Gregory <andrew.gregory.8@gmail.com> wrote:
On 12/14/15 at 05:55pm, Olivier Brunel wrote:
Also include the abort_on_fail flag so the frontend can let the user know which hook(s) are responsible.
Signed-off-by: Olivier Brunel <jjk@jjacky.com> ---
This seems like overkill. A failed AbortOnFail hook will already generate 3 error messages (assuming the hook itself prints one). We could just label AbortOnFail hooks as such when we print the info during HOOK_RUN_START. Alternatively, and this might be preferable behavior anyway, we could simply stop running PreTransaction hooks as soon as an AbortOnFail hook fails.
But there's no guarantee the hook will actually print anything, so it is good for frontends to (be able to) do so. And this is the only way to tell which hook(s) are causing the transaction to be aborted, so I don't see this as overkill. Now I assumed there was a reason for remaining hooks to still be ran, but if the behavior is to be changed to stop processing hooks right away then it might not be needed indeed, since the faulty hook is always the last one...
lib/libalpm/alpm.h | 6 +++++- lib/libalpm/hook.c | 7 +++++-- src/pacman/callback.c | 4 ++++ 3 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h index f6e6b86..52cbd51 100644 --- a/lib/libalpm/alpm.h +++ b/lib/libalpm/alpm.h @@ -465,7 +465,9 @@ typedef enum _alpm_event_type_t { /** A hook is starting */ ALPM_EVENT_HOOK_RUN_START, /** A hook has finnished runnning */ - ALPM_EVENT_HOOK_RUN_DONE + ALPM_EVENT_HOOK_RUN_DONE, + /** A hook has failed to run. */ + ALPM_EVENT_HOOK_RUN_FAILED } alpm_event_type_t;
typedef struct _alpm_event_any_t { @@ -568,6 +570,8 @@ typedef struct _alpm_event_hook_run_t { alpm_event_type_t type; /** Text to be outputted */ const char *desc; + /** Whether the hook has the AbortOnFail flag set (pre-transaction only) */
This is not strictly true. Setting AbortOnFail on a PostTransaction hook generates a warning, but leaves the flag set. In that case your callback will falsely claim that it aborted the transaction.
Oh, I missed that. Easy enough to set the flag here only for pre-transaction hooks though. (Since it doesn't apply, why are abort_on_fail flags set for post-transaction hooks though?)
On 12/14/15 at 07:03pm, Olivier Brunel wrote:
On Mon, 14 Dec 2015 12:47:26 -0500 Andrew Gregory <andrew.gregory.8@gmail.com> wrote:
On 12/14/15 at 05:55pm, Olivier Brunel wrote:
Also include the abort_on_fail flag so the frontend can let the user know which hook(s) are responsible.
Signed-off-by: Olivier Brunel <jjk@jjacky.com> ---
This seems like overkill. A failed AbortOnFail hook will already generate 3 error messages (assuming the hook itself prints one). We could just label AbortOnFail hooks as such when we print the info during HOOK_RUN_START. Alternatively, and this might be preferable behavior anyway, we could simply stop running PreTransaction hooks as soon as an AbortOnFail hook fails.
But there's no guarantee the hook will actually print anything, so it is good for frontends to (be able to) do so. And this is the only way to tell which hook(s) are causing the transaction to be aborted, so I don't see this as overkill.
Even if the hook itself doesn't print anything, libalpm will always print a message if a scriptlet or hook doesn't return 0. I'm fine with allowing front-ends to mark failed hooks as being AbortOnFail, I just don't think justifies adding a whole new event type.
Now I assumed there was a reason for remaining hooks to still be ran, but if the behavior is to be changed to stop processing hooks right away then it might not be needed indeed, since the faulty hook is always the last one...
I don't think I had a specific reason for continuing to run hooks other than not having a reason to stop running them at the time. For certain hooks (e.g. a btrfs snapshot) I would think immediately stopping would be preferable though.
lib/libalpm/alpm.h | 6 +++++- lib/libalpm/hook.c | 7 +++++-- src/pacman/callback.c | 4 ++++ 3 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h index f6e6b86..52cbd51 100644 --- a/lib/libalpm/alpm.h +++ b/lib/libalpm/alpm.h @@ -465,7 +465,9 @@ typedef enum _alpm_event_type_t { /** A hook is starting */ ALPM_EVENT_HOOK_RUN_START, /** A hook has finnished runnning */ - ALPM_EVENT_HOOK_RUN_DONE + ALPM_EVENT_HOOK_RUN_DONE, + /** A hook has failed to run. */ + ALPM_EVENT_HOOK_RUN_FAILED } alpm_event_type_t;
typedef struct _alpm_event_any_t { @@ -568,6 +570,8 @@ typedef struct _alpm_event_hook_run_t { alpm_event_type_t type; /** Text to be outputted */ const char *desc; + /** Whether the hook has the AbortOnFail flag set (pre-transaction only) */
This is not strictly true. Setting AbortOnFail on a PostTransaction hook generates a warning, but leaves the flag set. In that case your callback will falsely claim that it aborted the transaction.
Oh, I missed that. Easy enough to set the flag here only for pre-transaction hooks though. (Since it doesn't apply, why are abort_on_fail flags set for post-transaction hooks though?)
At the time abort_on_fail is set we don't know if it's a pre or post hook. We would have to *unset* the flag in hook_validate, which I didn't do at the time because there was no reason to.
On Mon, 14 Dec 2015 13:20:05 -0500 Andrew Gregory <andrew.gregory.8@gmail.com> wrote:
On 12/14/15 at 07:03pm, Olivier Brunel wrote:
On Mon, 14 Dec 2015 12:47:26 -0500 Andrew Gregory <andrew.gregory.8@gmail.com> wrote:
On 12/14/15 at 05:55pm, Olivier Brunel wrote:
Also include the abort_on_fail flag so the frontend can let the user know which hook(s) are responsible.
Signed-off-by: Olivier Brunel <jjk@jjacky.com> ---
This seems like overkill. A failed AbortOnFail hook will already generate 3 error messages (assuming the hook itself prints one). We could just label AbortOnFail hooks as such when we print the info during HOOK_RUN_START. Alternatively, and this might be preferable behavior anyway, we could simply stop running PreTransaction hooks as soon as an AbortOnFail hook fails.
But there's no guarantee the hook will actually print anything, so it is good for frontends to (be able to) do so. And this is the only way to tell which hook(s) are causing the transaction to be aborted, so I don't see this as overkill.
Even if the hook itself doesn't print anything, libalpm will always print a message if a scriptlet or hook doesn't return 0. I'm fine with allowing front-ends to mark failed hooks as being AbortOnFail, I just don't think justifies adding a whole new event type.
Sure libalpm will print an error message (w/out the hook name), but in the case where multiple hooks are run, and multiple hooks can fail, there would be no way to know which one(s) are actually causing the aborted transaction and which ones are not. And without this new event, frontends have no way of knowing whether a hook run was successful or not. All they know is it ran (ALPM_EVENT_HOOK_RUN_DONE), without any further indication.
Now I assumed there was a reason for remaining hooks to still be ran, but if the behavior is to be changed to stop processing hooks right away then it might not be needed indeed, since the faulty hook is always the last one...
I don't think I had a specific reason for continuing to run hooks other than not having a reason to stop running them at the time. For certain hooks (e.g. a btrfs snapshot) I would think immediately stopping would be preferable though.
Alright, so let's drop this patch, and instead I'll send one that stops processing pre-transaction hooks as soon as one with abort_on_fail does fail. Sounds good? Speaking of which, looking into this I realized something that I think may be a bug/not expected behavior, though I'm not sure: in trans.c when running pre-transaction hooks, this is how it's done: if(_alpm_hook_run(handle, ALPM_HOOK_PRE_TRANSACTION) != 0) { RET_ERR(handle, ALPM_ERR_TRANS_HOOK_FAILED, -1); } Which (to me) seems to imply that it will abort if _alpm_hook_run() doesn't return 0, and that would be classified as a hook (w/ AbortOnFail) did fail (though the error message is more generic: "failed to run transaction hooks"). However, in _alpm_hook_run() there are quite a few more cases that could lead to returning -1, e.g. failure to open a directory, to parse a hook file, etc What's the intended behavior here? When failing to parse a hook file or any of those other possible cases, should (in the case of pre-transaction hooks) the transaction be aborted or not? Because if not, there should be a specific return code to trigger the abort, distinguishing from other "non-fatal" errors to be silently ignored; And if so, there is no point running any hooks at all then.
On 12/14/15 at 08:30pm, Olivier Brunel wrote:
On Mon, 14 Dec 2015 13:20:05 -0500 Andrew Gregory <andrew.gregory.8@gmail.com> wrote:
On 12/14/15 at 07:03pm, Olivier Brunel wrote: ...
Now I assumed there was a reason for remaining hooks to still be ran, but if the behavior is to be changed to stop processing hooks right away then it might not be needed indeed, since the faulty hook is always the last one...
I don't think I had a specific reason for continuing to run hooks other than not having a reason to stop running them at the time. For certain hooks (e.g. a btrfs snapshot) I would think immediately stopping would be preferable though.
Alright, so let's drop this patch, and instead I'll send one that stops processing pre-transaction hooks as soon as one with abort_on_fail does fail. Sounds good?
Speaking of which, looking into this I realized something that I think may be a bug/not expected behavior, though I'm not sure:
in trans.c when running pre-transaction hooks, this is how it's done:
if(_alpm_hook_run(handle, ALPM_HOOK_PRE_TRANSACTION) != 0) { RET_ERR(handle, ALPM_ERR_TRANS_HOOK_FAILED, -1); }
Which (to me) seems to imply that it will abort if _alpm_hook_run() doesn't return 0, and that would be classified as a hook (w/ AbortOnFail) did fail (though the error message is more generic: "failed to run transaction hooks"). However, in _alpm_hook_run() there are quite a few more cases that could lead to returning -1, e.g. failure to open a directory, to parse a hook file, etc
What's the intended behavior here? When failing to parse a hook file or any of those other possible cases, should (in the case of pre-transaction hooks) the transaction be aborted or not?
Because if not, there should be a specific return code to trigger the abort, distinguishing from other "non-fatal" errors to be silently ignored; And if so, there is no point running any hooks at all then.
Aborting on any error is intentional. Marking a hook as AbortOnFail is intended to guarantee that the hook runs prior to transactions. If we fail to open a directory or parse a hook we have no way of knowing if there were any AbortOnFail hooks that we failed to run, so we take the conservative route and abort just in case. apg
participants (3)
-
Allan McRae
-
Andrew Gregory
-
Olivier Brunel