On 10/20/2012 03:52 AM, Gregory M. Turner wrote:
> If I indeed understand the facts correctly, I'm still a bit
> uncomfortable with your advice to just use "helper || die" in eclass
> code. It seems to me that if I follow this recipe, >=EAPI4 kinda works
> OK, but EAPI[0-3] doesn't.
>
> Specifically, an EAPI[0-3] ebuild author will not have any means at his
> or her disposal to handle errors that occur in eclass utility functions.
> The error-handling semantics of eclass utility functions would be like
> EAPI4, except without nonfatal around to provide relief from auto-die.
>
> EAPI[0-3] conventions encourage the habit of writing ebuild code like
> normal bash script code, which is to say, that authors expect to be able
> to write code like
>
> invoke_fn || ... # handle error, probably by die()ing but maybe not
>
> But eclasses that auto-die violate this expectation and create a
> situation where ebuild authors must be mindful of whether a particular
> function is a helper-function or an eclass utility function to correctly
> anticipate whether auto-death will occur.
>
> This seems to be by design and may not be so horrible as I make it sound
> -- for example, it would be pretty weird to expect eclass code written
> before EAPI4 to suddenly start working differently in EAPI[0-3].
>
> But should we really write new eclass code to behave this way as well?
Yeah, I think we should. If the eclass function is doing something that
might result in an undesirable die, then it can try to avoid the die by
first doing a sanity check. For example, it can check that a given file
path exists before passing it to the helper, and skip calling the helper
if the file path doesn't exist.
> Worse, eclasses authored in the pre-EAPI4 era ubiquitously assume that
> die() never returns, and do things like:
>
> efoo() {
> [[ ${EBUILD_PHASE} != "prepare" ]] &&
> die "efoo can only be used during src_prepare"
> .
> .
> # stuff that isn't safe if ${EBUILD_PHASE} != "prepare"
> .
> .
> }
>
> Since, in EAPI4, no means is provided to specify that a particular
> invocation of die() is unconditionally terminal, (except directly
> manipulating PORTAGE_NONFATAL, which doesn't seem to be encouraged), the
> only non-encapsulation-breaking non-EAPI-specific solution would be to
> re-code every presumed-terminal use of die() to look something like:
>
> failure_prone_action
> ret=$?
> if [[ ${ret} != 0 ]] ; then
> die "Error message"
> return ${ret}
> fi
>
> I can imagine no reasonable way to avoid this without using aliases...
> or perhaps some construct like:
>
> do_or_die() {
> diemsg="$1"
> shift
> "$@" || { ret=$?; die "${diemsg}"; return ${ret}; }
> }
>
> efoo() {
> do_or_die "error message 1" \
> failure_prone_action1 arg1 arg2 arg3 && \
> safe_action1 arg1 && \
> safe_action2 arg1 arg2 && \
> do_or_die "error message 2" \
> failure_prone_action2 arg1 arg2 && \
> .
> .
>
> Hopefully I'm missing something here...?
I never really liked the nonfatal helper. If you don't want a helper to
die, then I'd suggest to use sanity checks before calling the helper,
and avoid calling the helper if it seems like it will trigger an
unwanted die.
--
Thanks,
Zac