1 |
On 10/20/2012 03:52 AM, Gregory M. Turner wrote: |
2 |
> If I indeed understand the facts correctly, I'm still a bit |
3 |
> uncomfortable with your advice to just use "helper || die" in eclass |
4 |
> code. It seems to me that if I follow this recipe, >=EAPI4 kinda works |
5 |
> OK, but EAPI[0-3] doesn't. |
6 |
> |
7 |
> Specifically, an EAPI[0-3] ebuild author will not have any means at his |
8 |
> or her disposal to handle errors that occur in eclass utility functions. |
9 |
> The error-handling semantics of eclass utility functions would be like |
10 |
> EAPI4, except without nonfatal around to provide relief from auto-die. |
11 |
> |
12 |
> EAPI[0-3] conventions encourage the habit of writing ebuild code like |
13 |
> normal bash script code, which is to say, that authors expect to be able |
14 |
> to write code like |
15 |
> |
16 |
> invoke_fn || ... # handle error, probably by die()ing but maybe not |
17 |
> |
18 |
> But eclasses that auto-die violate this expectation and create a |
19 |
> situation where ebuild authors must be mindful of whether a particular |
20 |
> function is a helper-function or an eclass utility function to correctly |
21 |
> anticipate whether auto-death will occur. |
22 |
> |
23 |
> This seems to be by design and may not be so horrible as I make it sound |
24 |
> -- for example, it would be pretty weird to expect eclass code written |
25 |
> before EAPI4 to suddenly start working differently in EAPI[0-3]. |
26 |
> |
27 |
> But should we really write new eclass code to behave this way as well? |
28 |
|
29 |
Yeah, I think we should. If the eclass function is doing something that |
30 |
might result in an undesirable die, then it can try to avoid the die by |
31 |
first doing a sanity check. For example, it can check that a given file |
32 |
path exists before passing it to the helper, and skip calling the helper |
33 |
if the file path doesn't exist. |
34 |
|
35 |
> Worse, eclasses authored in the pre-EAPI4 era ubiquitously assume that |
36 |
> die() never returns, and do things like: |
37 |
> |
38 |
> efoo() { |
39 |
> [[ ${EBUILD_PHASE} != "prepare" ]] && |
40 |
> die "efoo can only be used during src_prepare" |
41 |
> . |
42 |
> . |
43 |
> # stuff that isn't safe if ${EBUILD_PHASE} != "prepare" |
44 |
> . |
45 |
> . |
46 |
> } |
47 |
> |
48 |
> Since, in EAPI4, no means is provided to specify that a particular |
49 |
> invocation of die() is unconditionally terminal, (except directly |
50 |
> manipulating PORTAGE_NONFATAL, which doesn't seem to be encouraged), the |
51 |
> only non-encapsulation-breaking non-EAPI-specific solution would be to |
52 |
> re-code every presumed-terminal use of die() to look something like: |
53 |
> |
54 |
> failure_prone_action |
55 |
> ret=$? |
56 |
> if [[ ${ret} != 0 ]] ; then |
57 |
> die "Error message" |
58 |
> return ${ret} |
59 |
> fi |
60 |
> |
61 |
> I can imagine no reasonable way to avoid this without using aliases... |
62 |
> or perhaps some construct like: |
63 |
> |
64 |
> do_or_die() { |
65 |
> diemsg="$1" |
66 |
> shift |
67 |
> "$@" || { ret=$?; die "${diemsg}"; return ${ret}; } |
68 |
> } |
69 |
> |
70 |
> efoo() { |
71 |
> do_or_die "error message 1" \ |
72 |
> failure_prone_action1 arg1 arg2 arg3 && \ |
73 |
> safe_action1 arg1 && \ |
74 |
> safe_action2 arg1 arg2 && \ |
75 |
> do_or_die "error message 2" \ |
76 |
> failure_prone_action2 arg1 arg2 && \ |
77 |
> . |
78 |
> . |
79 |
> |
80 |
> Hopefully I'm missing something here...? |
81 |
|
82 |
I never really liked the nonfatal helper. If you don't want a helper to |
83 |
die, then I'd suggest to use sanity checks before calling the helper, |
84 |
and avoid calling the helper if it seems like it will trigger an |
85 |
unwanted die. |
86 |
-- |
87 |
Thanks, |
88 |
Zac |