Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
Bug 489458 - [Future EAPI] Replace || with something less ambiguous
Summary: [Future EAPI] Replace || with something less ambiguous
Status: CONFIRMED
Alias: None
Product: Gentoo Hosted Projects
Classification: Unclassified
Component: PMS/EAPI (show other bugs)
Hardware: All Linux
: Normal normal (vote)
Assignee: PMS/EAPI
URL:
Whiteboard: feasible-for-next-eapi
Keywords:
Depends on:
Blocks: future-eapi
  Show dependency tree
 
Reported: 2013-10-26 12:13 UTC by Ciaran McCreesh
Modified: 2016-06-23 19:14 UTC (History)
3 users (show)

See Also:
Package list:
Runtime testing required: ---


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Ciaran McCreesh 2013-10-26 12:13:12 UTC
There are at least two issues with || ( ) dependencies in *DEPEND. Firstly, developers commonly think it just means "or", and forget the "prefer leftmost" issue. Secondly, it's ambiguous in the same way that specs matching multiple slots are ambiguous: the package mangler doesn't know whether it's safe to swap || deps at runtime.

We could improve the situation by replacing || in *DEPEND with a choice of <<* for "prefer the leftmost, and you can switch it at runtime" and <<= for "prefer the leftmost, and lock it when it's installed".

An added bonus of this notation is that it's horribly ugly, just like || dependencies.
Comment 1 Ulrich Müller gentoo-dev 2013-10-26 12:51:30 UTC
Maybe we should start with documenting "prefer leftmost" in PMS.

Not sure what changing || to << would buy us. That || is evaluated from left to right (and processing stops after the first match) is quite common elsewhere, e.g. in bash or C. Also << would look strange in LICENSE or REQUIRED_USE.

How about just allowing an optional * or = after the || operator?
Comment 2 Ciaran McCreesh 2013-10-26 12:58:53 UTC
Well, || ( <a-2 >a-3 ) comes up pretty regularly...
Comment 3 Ulrich Müller gentoo-dev 2013-10-26 13:07:32 UTC
Heh, things could be much worse.

<any-of prefer="leftmost" runtime="will-break-if-replaced">
  <package match-type="greater-than">a-3</package>
  <package match-type="less-than">a-2</package>
</any-of>
Comment 4 Ciaran McCreesh 2013-10-26 13:11:23 UTC
No Zynot jokes!
Comment 5 Ulrich Müller gentoo-dev 2013-12-09 10:30:38 UTC
This issue just came up again in bug 493652. So, how about this syntax:
   ||* ( )
   ||= ( )

Questions:
- Should we allow || ( ) in addition, and (if yes) what should it default to?
- How should ||* ( cat/foo:= cat/bar:= ) be interpreted (mgorny brought this
  up on IRC)? What about nested ||= and ||* of different type?
Comment 6 Ulrich Müller gentoo-dev 2014-01-14 08:23:38 UTC
Another question:
- ||* and ||= are meaningless for build-time dependencies. Should they be just
  synonyms for || there? Or should we disallow these operators in DEPEND?
  In the latter case, DEPEND="${RDEPEND}" would not be possible any more.
Comment 7 Ulrich Müller gentoo-dev 2014-02-20 11:01:01 UTC
(In reply to Ulrich Müller from comment #5)
> Questions:
> - Should we allow || ( ) in addition, and (if yes) what should it default to?
> - How should ||* ( cat/foo:= cat/bar:= ) be interpreted (mgorny brought this
>   up on IRC)? What about nested ||= and ||* of different type?

Any ideas? If this shall make it into the next EAPI, these questions need to be answered.
Comment 8 Ciaran McCreesh 2014-02-20 15:28:12 UTC
Nested || should be banned everywhere, at least...
Comment 9 Sebastian Luther (few) 2014-02-20 17:35:59 UTC
(In reply to Ulrich Müller from comment #5)
> This issue just came up again in bug 493652. So, how about this syntax:
>    ||* ( )
>    ||= ( )
> 
> Questions:
> - Should we allow || ( ) in addition, and (if yes) what should it default to?

Not allowing it would at least force people to make a decision (unlike in the slot operator case).

> - How should ||* ( cat/foo:= cat/bar:= ) be interpreted (mgorny brought this
>   up on IRC)?

This problem already exists and is orthogonal to the matters discussed here.

> What about nested ||= and ||* of different type?

How exactly behave nested ||s of the same type when written to the vdb? It's clear for ||* - just leave it as is. But what about this:
"||= ( ||= ( A B ) ||= ( C D ) )"
If D is installed but A, B, C aren't then I'd assume this gets rewritten to "D".
But what if A and D are installed? Does it get rewritten to "A D" or does the PM choose either "A" or "D"?

(In reply to Ulrich Müller from comment #6)
> Another question:
> - ||* and ||= are meaningless for build-time dependencies. Should they be
> just
>   synonyms for || there? Or should we disallow these operators in DEPEND?
>   In the latter case, DEPEND="${RDEPEND}" would not be possible any more.

Slot operators are allowed in DEPEND too. I think it would be too annoying to not allow them for the reason you gave.
Comment 10 Michał Górny archtester Gentoo Infrastructure gentoo-dev Security 2014-04-18 21:50:54 UTC
One more question:

  || ( A B C )

does the 'prefer leftmost' rule apply to the behavior of package itself? That is, if multiple dependencies are installed, is the package required to use the left-most of them? This is important for the package manager to properly handle upgrades.

Right now, || sounds pretty much like undefined behavior to me. That is, package manager seeing all of ( A, B, C ) installed would have to upgrade all of them, in case the package used another one than package manager expected.

Using a new operator could clarify that as well.
Comment 11 Ciaran McCreesh 2014-04-18 21:55:36 UTC
Right now, anything using || has to work with any of its choices (even if some of the choices are broken, due to missing deps, so long as at least one of its choices is correct), and this has to be switchable at runtime.
Comment 12 Michał Górny archtester Gentoo Infrastructure gentoo-dev Security 2014-07-31 08:23:36 UTC
Let me ask a different question: would there be use for ||= ( A B ) without := on A & B?

Otherwise, we could achieve a similar effect via extrapolating the current rules for := and || ().

Plain:

  || ( A B )

would mean runtime-switchable, while:

  || ( A:= B:= )

would require rebuild via subslots.

This is already true if A & B are mutually exclusive. Since PMS says that 'the package will break unless a matching package with slot and sub-slot equal to the slot and sub-slot of the best installed version at the time the package was installed is available', removing the relevant package will need to trigger a rebuild.

Not sure how to properly handle non-mutually exclusive variants. Not sure if we need any.
Comment 13 Ulrich Müller gentoo-dev 2014-08-04 06:21:12 UTC
(In reply to Michał Górny from comment #12)
> Let me ask a different question: would there be use for ||= ( A B ) without
> := on A & B?

Why not? There could be a case similar to mit-krb5 and heimdal where providers have different APIs, but runtime ABI switching within one provider could still be possible.

> Otherwise, we could achieve a similar effect via extrapolating the current
> rules for := and || ().
> 
> Plain:
> 
>   || ( A B )
> 
> would mean runtime-switchable,

How would you distinguish between ||= ( A B ) and ||* ( A B ) without separate operators?

> while:
> 
>   || ( A:= B:= )
> 
> would require rebuild via subslots.

I believe that ||= ( A:= B:= ) expresses the intention much more clearly.

And ||* ( A:= B:= ) should be banned. Otherwise, you could switch the provider from A:1 to B and then from B to A:2 which would render the := meaningless.
Comment 14 Michał Górny archtester Gentoo Infrastructure gentoo-dev Security 2014-08-05 08:43:04 UTC
So let's keep this simple.

For PMS:

- we add ||= () with 'prefer leftmost' and build-time switching.

For policy/common sense:

1. || () still works like usual, that is run-time switching. Preferences do not really matter here since package can use any of the installed deps anyway.

1a. Corner case: || ( A[foo] B ) -- what if A[-foo] and B is installed? Some packages may actually try to use A and fail due to unsatisfied USE. But it's no new issue and I doubt it's worth special handling. Extra '!A[-foo]' could be used to solve it.

2. Alike :=, ||= can be used in DEPEND (works as '||' there).

2a. ||= in RDEPEND makes sense only if there's corresponding || or ||= in DEPEND -- the package needs to select provider build-time. I'd dare say requiring people to write RDEP='||= ( A B )' DEP='|| ( A B )' is... bad :).

2b. ||= (and :=) in PDEPEND doesn't make sense -- we use that when we can't install something build-time.

3. := atoms make sense only in ||=. We likely want to ban them in || in the EAPIs with ||=. In earlier EAPIs, those combinations will be left undefined.

4. I don't think we need to set any special rules for nesting. 'It should work', I'd dare say, but since it's hard to implement the real use will follow implementation:

4a.

  || (
    || ( A B )
    C
  )

  Direct nesting doesn't really make sense :).

4b.

  ||= (
    (
      libX11
      ||= ( ffmpeg:= libav:= )
    )
    (
      emul-linux-x86-medialibs
    )
  )

  This one may actually be meaningful. Not sure how hard to implement it would be.

5. I don't think we need a specific ||*. || is already well-defined in PMS, and :* already proved being rarely used.
Comment 15 Michał Górny archtester Gentoo Infrastructure gentoo-dev Security 2014-09-06 08:50:25 UTC
The more I think about it, the less I like the idea of ||= with packages that do not mutually block one another.

For example:

  ||= ( A B )

means that you can't properly switch to B without unmerging A first, and therefore breaking the package.
Comment 16 Ulrich Müller gentoo-dev 2014-09-06 09:04:03 UTC
(In reply to Michał Górny from comment #15)
> The more I think about it, the less I like the idea of ||= with packages
> that do not mutually block one another.
> 
> For example:
> 
>   ||= ( A B )
> 
> means that you can't properly switch to B without unmerging A first, and
> therefore breaking the package.

How is this different from := in SLOT dependencies?
Comment 17 Michał Górny archtester Gentoo Infrastructure gentoo-dev Security 2014-09-06 09:09:21 UTC
Well, I think we simply don't support downgrades :). In case of ||=, it'd rather more inconvenient not to support switching to a 'less preferred' provider.
Comment 18 Michał Górny archtester Gentoo Infrastructure gentoo-dev Security 2016-06-23 18:56:05 UTC
(In reply to Michał Górny from comment #15)
> The more I think about it, the less I like the idea of ||= with packages
> that do not mutually block one another.
> 
> For example:
> 
>   ||= ( A B )
> 
> means that you can't properly switch to B without unmerging A first, and
> therefore breaking the package.

Let me clarify that since it seems that I wasn't clear on what the problem is.

The problem is that if you install both A and B, and then want to switch to B, you'd have to do:

  emerge -C A

but so far the --unmerge/--depclean actions in emerge did not build anything, just remove packages. This means that either we would have to strongly change behavior, or the rebuild won't happen until next regular emerge call.
Comment 19 Ulrich Müller gentoo-dev 2016-06-23 19:14:54 UTC
(In reply to Michał Górny from comment #18)

Conceptionally that doesn't seem to be so much different from a slot operator dependency.

For example, the package depends on foo:= and there is foo:2 installed when it is emerged. What happens if the user does "emerge foo:1" followed by "emerge -C foo:2"? Does portage rebuild the reverse dependency with the second command?