Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

assemble-repository: Prevent sources from being included inadvertently #3635

Merged
merged 1 commit into from
Mar 18, 2024

Conversation

sratz
Copy link
Contributor

@sratz sratz commented Mar 12, 2024

In the presence of products, P2 adds a virtual tooling.source.default
IU which optionally depends on all sources.

If these sources are available in the target platform, this would cause
them to be picked up even if assemble-repository was configured with

  <includeAllDependencies>true<includeAllDependencies>

but with

  <includeAllSources>false</includeAllSources>.

This scenario has become much more likely with recent changes to P2 [1].

We do not want includeAllDependencies to imply includeAllSources, so
we actively prevent this from happening by ignoring the

  <required namespace='org.eclipse.equinox.p2.eclipse.type'
            name='source'
            range='0.0.0'
            optional='true'
            multiple='true'
            greedy='false'/>

requirements if includeAllSources is not specified.

Fixes #3522.

[1] eclipse-equinox/p2#446

Copy link

github-actions bot commented Mar 12, 2024

Test Results

  591 files  +3    591 suites  +3   4h 39m 20s ⏱️ + 2m 35s
  407 tests +2    400 ✅ +4   7 💤 ±0  0 ❌  - 1 
1 221 runs  +6  1 199 ✅ +9  22 💤 ±0  0 ❌  - 1 

Results for commit a028cbf. ± Comparison against base commit d6366ad.

♻️ This comment has been updated with latest results.

laeubi
laeubi previously requested changes Mar 14, 2024
Copy link
Member

@laeubi laeubi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It goes in the right direction but basically I would

  1. check here if this is a requirement for a source bundle
  2. Construct a context IU with org.eclipse.update.install.sources=true/false
  3. then check if they match in isApplicable(IInstallableUnit iu, IRequirement req)

that way the requirements will just be filtered out.

@@ -118,6 +119,10 @@ protected Slicer createSlicer(SlicingOptions options) throws ProvisionException
boolean considerOnlyStrictDependency = options.considerStrictDependencyOnly();
return new PermissiveSlicer(repository, filters.get(0), includeOptionalDependencies,
options.isEverythingGreedy(), evalFilterTo, considerOnlyStrictDependency, onlyFilteredRequirements) {

private static final String TOOLING_SOURCE_IU_ID = PublisherHelper.createDefaultConfigUnitId("source",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure this is the correct approach also the test failuresindicate that.


private static final String TOOLING_SOURCE_IU_ID = PublisherHelper.createDefaultConfigUnitId("source",
"tooling");

@Override
protected boolean isApplicable(IInstallableUnit iu, IRequirement req) {
if ((includeRequiredBundles || includeRequiredFeatures) && QueryUtil.isGroup(iu)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is actually the place where you want to filter things, this test if a requirement for a IU is applicable and you don't want the new requirement to be considered.

@sratz
Copy link
Contributor Author

sratz commented Mar 15, 2024

1. check here if this is a requirement for a source bundle
2. Construct a context IU with org.eclipse.update.install.sources=true/false

I'm not sure I understand this part.
Where is 'here'?
What's a 'context IU'?
Also, as the problem is not the org.eclipse.update.install.sources, but the fact that a published product contains a tooling.source.default IU which optionally depends on all sources.

3. then check if they match in isApplicable(IInstallableUnit iu, IRequirement req)

I think this is the important aspect. We don't want to filter
tooling.source.default itself in isApplicable(IInstallableUnit iu)
but only filter
tooling.source.default's dependencies in isApplicable(IInstallableUnit iuIRequirement req).

I have moved the condition to isApplicable(IInstallableUnit iuIRequirement req), let's see what the test suite says.

@laeubi
Copy link
Member

laeubi commented Mar 15, 2024

I must confess I'm not sure tooling.source.default is really the problem. This has not changed recently but what has changed is that each bundle now has the org.eclipse.update.install.sources requirement.

@sratz
Copy link
Contributor Author

sratz commented Mar 15, 2024

I must confess I'm not sure tooling.source.default is really the problem. This has not changed recently but what has changed is that each bundle now has the org.eclipse.update.install.sources requirement.

It has not changed, but before org.eclipse.update.install.sources was introduced those sources weren't part of the target platform.

Now they are, and the effect of tooling.source.default now pulls them in.

@sratz
Copy link
Contributor Author

sratz commented Mar 15, 2024

An alternative to the current proposal of looking at tooling.source.default could be to provide a filtered view on the project's target platform with org.eclipse.update.install.source=true IUs excluded. Then, using that filtered target platform to initiate the mirroring. But I am not sure I know how to do that.

@laeubi
Copy link
Member

laeubi commented Mar 18, 2024

As said this are not IUs but Requirements ... You can create a so called "context IU" from a map of properties with InstallableUnit.contextIU(context) in your case maybe InstallableUnit.contextIU(Map.of(org.eclipse.update.install.source, true)), if you have that you can use

IMatchExpression<IInstallableUnit> filter = req.getFilter();
booelan matches =  filter != null && filter.isMatch(contextIU);

for example to check if a requirement is matching that context IU and if yes return false from is applicable if includeAllSources is false.

@sratz
Copy link
Contributor Author

sratz commented Mar 18, 2024

As said this are not IUs but Requirements ... You can create a so called "context IU" from a map of properties with InstallableUnit.contextIU(context) in your case maybe InstallableUnit.contextIU(Map.of(org.eclipse.update.install.source, true)), if you have that you can use

IMatchExpression<IInstallableUnit> filter = req.getFilter();
booelan matches =  filter != null && filter.isMatch(contextIU);

for example to check if a requirement is matching that context IU and if yes return false from is applicable if includeAllSources is false.

I tried this:

            private static final IInstallableUnit SOURCEC_CONTEXT = InstallableUnit
                    .contextIU(Map.of("org.eclipse.update.install.source", "true"));

            @Override
            protected boolean isApplicable(IInstallableUnit iu, IRequirement req) {
                if (!includeAllSource) {
                    IMatchExpression<IInstallableUnit> filter = req.getFilter();
                    if (filter != null) {
                        if (filter.isMatch(SOURCEC_CONTEXT)) {
                            // When dealing with a repository that contains published products, these products
                            // always include a dependency to 'tooling.source.default', which picks up all sources.
                            // And since https://github.com/eclipse-equinox/p2/pull/446 the target platform contains
                            // all the sources. They would be picked up unless we prevent this here.
                            // See https://github.com/eclipse-tycho/tycho/issues/3522
                            return false;
                        }
                    }
                }

but it does not work.

As outlined in the issue, the problematic IU is tooling.source.default which has an IRequirement on all source providers:

		// Create a required capability on source providers
		IRequirement[] reqs = new IRequirement[] {MetadataFactory.createRequirement(NAMESPACE_ECLIPSE_TYPE, TYPE_ECLIPSE_SOURCE, VersionRange.emptyRange, null, true, true, false)};
		cu.setHost(reqs);
		Map<String, String> touchpointData = new HashMap<>();

https://github.com/eclipse-equinox/p2/blob/e0ce87e039a001c4aafcbb2dba6ca33455933097/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/spi/p2/publisher/PublisherHelper.java#L169-L189

This requirement does not have any filter so the code above will not be able to filter anything here based on the context IU.

@laeubi
Copy link
Member

laeubi commented Mar 18, 2024

@merks yna you give a hint about the tooling.source.default IU?

@merks
Copy link
Contributor

merks commented Mar 18, 2024

One thing that might generally be helpful here is that this is an optional non-greedy requirement:

<unit id='tooling.source.default' version='1.0.0' singleton='false'>
  <hostRequirements size='1'>
    <required namespace='org.eclipse.equinox.p2.eclipse.type' name='source' range='0.0.0' optional='true' multiple='true' greedy='false'/>
  </hostRequirements>
  <properties size='1'>
    <property name='org.eclipse.equinox.p2.type.fragment' value='true'/>
  </properties>
  <provides size='2'>
    <provided namespace='org.eclipse.equinox.p2.iu' name='tooling.source.default' version='1.0.0'/>
    <provided namespace='org.eclipse.equinox.p2.flavor' name='tooling' version='1.0.0'/>
  </provides>
  <requires size='1'>
    <required namespace='org.eclipse.equinox.p2.eclipse.type' name='source' range='0.0.0' optional='true' multiple='true' greedy='false'/>
  </requires>
...
</unit>

As far as I understand it, at installation time, an optional non-greedy requirement will not be installed even when it's available, i.e., there must be some other non-optional requirements (in which case the required things must be available), or optional greedy requirement (in which case it's installed when available and quietly ignored when not).

Of course the context here is mirroring and not installing. I think in the filtering context here that generally it should be possible to ignore all optional non-greedy requirements. I'm not sure if that should involve yet another configuration option...

@laeubi
Copy link
Member

laeubi commented Mar 18, 2024

As far as I know "inlcudeAllRequirements" makes everything greedy....

@sratz
Copy link
Contributor Author

sratz commented Mar 18, 2024

Yes, we have includeAllDependencies and includeAllSources.

I think the intuitive expectation is that includeAllDependencies does not also imply includeAllSources.

And previously this expectation was (usually) met, because the sources typically weren't visible via the target platform in these kind of product-containing repository definitions.

So the current proposal of this PR basically ensures that this expectation is met deterministically.

@sratz
Copy link
Contributor Author

sratz commented Mar 18, 2024

Instead of looking at the IU's name tooling.source.default, we could also just look at the IRequirement and do this:

                if (!includeAllSource && req.getMin() == 0 && !req.isGreedy()
                        && req instanceof IRequiredCapability capability
                        && PublisherHelper.NAMESPACE_ECLIPSE_TYPE.equals(capability.getNamespace())
                        && PublisherHelper.TYPE_ECLIPSE_SOURCE.equals(capability.getName())) {
                    return false;
                }

WDYT?

@merks
Copy link
Contributor

merks commented Mar 18, 2024

That's exactly what I was trying just now:

image

I was just making sure the tests still pass but was having problems with the 4.31 repository not loading for some unknown reason.

@merks
Copy link
Contributor

merks commented Mar 18, 2024

@sratz I suggest you make the change (yes, the test still passes) since I'm a bit incompetent at updating someone else's PR.

@sratz
Copy link
Contributor Author

sratz commented Mar 18, 2024

I was just making sure the tests still pass but was having problems with the 4.31 repository not loading for some unknown reason.

had the same, clearing~.m2/cache helped.

@merks
Copy link
Contributor

merks commented Mar 18, 2024

@sratz

FYI, this test fails for me locally as well:

image

So I'm looking at that...

In the presence of products, P2 adds a virtual 'tooling.source.default'
IU which optionally depends on all sources.

If these sources are available in the target platform, this would cause
them to be picked up even if assemble-repository was configured with

  <includeAllDependencies>true<includeAllDependencies>

but with

  <includeAllSources>false</includeAllSources>.

This scenario has become much more likely with recent changes to P2 [1].

We do not want includeAllDependencies to imply includeAllSources, so
we actively prevent this from happening by ignoring the

  <required namespace='org.eclipse.equinox.p2.eclipse.type'
            name='source'
            range='0.0.0'
            optional='true'
            multiple='true'
            greedy='false'/>

requirements if 'includeAllSources' is not specified.

Fixes eclipse-tycho#3522.

[1] eclipse-equinox/p2#446
@merks
Copy link
Contributor

merks commented Mar 18, 2024

@sratz

The test failure is unrelated and is already fixed in master:

assertEquals(4, result.getArtifacts().size());
assertEquals(4, result.getNonReactorUnits().size()); // + a.jre

The problem is that the test uses a moving target repository so the actual content can and apparently does change:

private static final String LATEST_PLATFORM = "https://download.eclipse.org/eclipse/updates/latest/";

Please ensure that you rebase your change on master.

@laeubi laeubi dismissed their stale review March 18, 2024 12:06

outdated

@laeubi laeubi added the backport-to-tycho-4.0.x Can be added to a PR to trigger an automatic backport of the change label Mar 18, 2024
Copy link
Member

@laeubi laeubi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good and is backed by test so I think its ready to go.

@laeubi laeubi merged commit 51e39d6 into eclipse-tycho:main Mar 18, 2024
12 checks passed
@eclipse-tycho-bot
Copy link

💚 All backports created successfully

Status Branch Result
tycho-4.0.x

Note: Successful backport PRs will be merged automatically after passing CI.

Questions ?

Please refer to the Backport tool documentation and see the Github Action logs for details

@merks
Copy link
Contributor

merks commented Mar 18, 2024

And a back port too. That's great! Thanks!!

@laeubi
Copy link
Member

laeubi commented Mar 18, 2024

@sratz many thanks for the fix, as you already have contributed to Tycho for a while I'd like to ask if you want to become a committer I just would need your email address of the eclipse account and can prepare the vote then!

@sratz
Copy link
Contributor Author

sratz commented Mar 20, 2024

@sratz many thanks for the fix, as you already have contributed to Tycho for a while I'd like to ask if you want to become a committer I just would need your email address of the eclipse account and can prepare the vote then!

Thanks for the offer! I pinged you via email.

@sratz sratz deleted the product-sources branch March 20, 2024 09:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport-to-tycho-4.0.x Can be added to a PR to trigger an automatic backport of the change
Projects
None yet
Development

Successfully merging this pull request may close these issues.

product / repository contains source jars by default
4 participants