Skip to content

Drop invalid package providers when adding a permutation#1086

Closed
laeubi wants to merge 1 commit into
eclipse-equinox:masterfrom
laeubi:drop_invalid_package_providers
Closed

Drop invalid package providers when adding a permutation#1086
laeubi wants to merge 1 commit into
eclipse-equinox:masterfrom
laeubi:drop_invalid_package_providers

Conversation

@laeubi
Copy link
Copy Markdown
Member

@laeubi laeubi commented Jul 15, 2025

Currently a certain set of use-constraint violations occur when checking the classpath consistency that can be described in the following way:

  • There is a package A provided by X and Y
  • There is a package B provided by Y that uses A
  • Consumer C imports package A + B
  • There are now two eligible providers for A and if the resolver chooses for A = X and B = Y
  • This results in a use-violation because A is reachable through two chains (C->X->Ax, C->B->Y->Ay)

This can be avoided by doing an initial scan of all providers that are singletons in the current permutation, have a use constraint on a package that is also provided by this provider, and has more than one candidate, then the only valid on is the provider of the singleton selection.

This currently adds a test-case that shows the situation and currently requires 7 permutations, where it should in the best case only require 1 (the initial one) because there is only one valid choice when these kind of exceptions occurs:

Chain 1:
  biz.aQute.repository [osgi.identity; type="osgi.bundle"; version:Version="7.1.0.202411251545"; osgi.identity="biz.aQute.repository"]
    import: (&(osgi.wiring.package=aQute.service.reporter)(&(version>=1.3.0)(!(version>=2.0.0))))
     |
    export: osgi.wiring.package: aQute.service.reporter
  aQute.libg [osgi.identity; type="osgi.bundle"; version:Version="7.1.0.202411251545"; osgi.identity="aQute.libg"]

Chain 2:
  biz.aQute.repository [osgi.identity; type="osgi.bundle"; version:Version="7.1.0.202411251545"; osgi.identity="biz.aQute.repository"]
    import: (&(osgi.wiring.package=aQute.bnd.build)(&(version>=4.6.0)(!(version>=5.0.0))))
     |
    export: osgi.wiring.package: aQute.bnd.build; uses:=aQute.service.reporter
    export: osgi.wiring.package=aQute.service.reporter
  biz.aQute.bndlib [osgi.identity; type="osgi.bundle"; version:Version="7.1.0.202411251545"; osgi.identity="biz.aQute.bndlib"])

Where the following choices exits:

    [?]Import-Package: aQute.service.reporter; version="[1.3.0,2.0.0)": 
        Export-Package: aQute.service.reporter; bundle-symbolic-name="aQute.libg"; bundle-version="7.1.0.202411251545"; version="1.3.0"
        Export-Package: aQute.service.reporter; bundle-symbolic-name="biz.aQute.bndlib"; bundle-version="7.1.0.202411251545"; version="1.3.0"

but the first one is invalid because of

    [!]Import-Package: aQute.bnd.service.repository; version="[1.7.0,2.0.0)": 
        Export-Package: aQute.bnd.service.repository; bundle-symbolic-name="biz.aQute.bndlib"; bundle-version="7.1.0.202411251545"; version="1.7.0"; uses:="aQute.bnd.service,aQute.bnd.util.dto,aQute.bnd.version,aQute.service.reporter,org.osgi.resource"

So aQute.bnd.service.repository uses aQute.service.reporter, both packages are provided by biz.aQute.bndlib so in the case of import only bndlib is a valid choice.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jul 15, 2025

Test Results

  807 files  ±0    807 suites  ±0   1h 14m 49s ⏱️ -14s
2 202 tests ±0  2 149 ✅  -  4   49 💤 ±0   4 ❌ + 4 
6 618 runs  ±0  6 457 ✅  - 12  149 💤 ±0  12 ❌ +12 

For more details on these failures, see this check.

Results for commit 6869c27. ± Comparison against base commit 626f822.

♻️ This comment has been updated with latest results.

@laeubi laeubi force-pushed the drop_invalid_package_providers branch from 428a351 to 34c0ef9 Compare July 16, 2025 04:24
@laeubi
Copy link
Copy Markdown
Member Author

laeubi commented Jul 16, 2025

This now works and the test passes with one less iteration but I have some trouble starting an Eclipse SDK with this change, need to investigate whats going on.

@laeubi laeubi force-pushed the drop_invalid_package_providers branch from 34c0ef9 to 05f0b4d Compare July 20, 2025 17:16
@laeubi
Copy link
Copy Markdown
Member Author

laeubi commented Jul 21, 2025

I have now found the issue. It is in org.apache.felix.resolver.Candidates.checkSubstitutes() where it permutates a substitution package and then remove all dependent providers of such package.

This can lead to a state where it removes (incorrectly) valid choices from the current permutation that then results in a failure. If I make sure dependents are not reduced if there is only one provider left, everything works like intended and the IDE starts up again. Also it works to just resolve all individual bundles again one by one. I now need to extract some kind of testcase here to show the issue...

@tjwatson I must confess I not yet fully understood the logic behind that method, but it feels it might better want to operate on a copy of the candidates here. Also it feels really strange here that permutations are computed (and modify the candidates) as a side-effect of the checkConsistency call, I would have expected that this is a preliminary step and it has to be much more simpler, e.g. we only have the choice of

  • accepting a substitution and discarding the export (that seems to be somehow the case handled here)
  • rejecting the substitution and discarding the import

So I always would expect two Candidates to be added as a possible permutation, where it removes the provider from the list anywhere while currently it is dropping all providers in front of it for it dependents. Also I would expect this to be the very first step when creating an inital permutation. So before I try to fix/rewrite the stuff maybe you can explain the background of the current approach.

Currently a certain set of use-constraint violations occur when checking
the classpath consistency that can be described in the following way:

- There is a package A provided by X and Y
- There is a package B provided by Y that uses A
- Consumer C imports package A + B
- There are now two eligible providers for A and if the resolver chooses
for A = X and B = Y
- This results in a use-violation because A is reachable through two
chains (C->X->Ax, C->B->Y->Ay)

This can be avoided by doing an initial scan of all providers that are
singletons in the current permutation, have a use constraint on a
package that is also provided by this provider, and has more than one
candidate, then the only valid on is the provider of the singleton
selection.
@laeubi laeubi force-pushed the drop_invalid_package_providers branch from 05f0b4d to 6869c27 Compare August 2, 2025 11:34
@laeubi
Copy link
Copy Markdown
Member Author

laeubi commented Sep 4, 2025

@laeubi laeubi closed this Sep 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant