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

Reply via email to