From 6b9cefeb69fa261e2dab74f4ab3cf68a3cb060ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20L=C3=A4ubrich?= Date: Fri, 19 Jan 2024 18:04:15 +0100 Subject: [PATCH] Only selects the highest matching requirement if multiple match --- .../tycho/p2tools/TychoMirrorApplication.java | 43 +++++++++++++------ .../copiedfromp2/MirrorApplication.java | 12 +++--- .../copiedfromp2/PermissiveSlicer.java | 1 - .../tycho/p2tools/copiedfromp2/Slicer.java | 18 ++++---- ...efLocationP2RepositoryIntegrationTest.java | 4 +- .../test/AbstractTychoIntegrationTest.java | 5 ++- 6 files changed, 51 insertions(+), 32 deletions(-) diff --git a/tycho-core/src/main/java/org/eclipse/tycho/p2tools/TychoMirrorApplication.java b/tycho-core/src/main/java/org/eclipse/tycho/p2tools/TychoMirrorApplication.java index 1587aa1119..910f9242cc 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/p2tools/TychoMirrorApplication.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/p2tools/TychoMirrorApplication.java @@ -22,6 +22,7 @@ import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collection; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -32,8 +33,6 @@ import java.util.stream.Stream; import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.equinox.internal.p2.director.PermissiveSlicer; -import org.eclipse.equinox.internal.p2.director.Slicer; import org.eclipse.equinox.internal.p2.metadata.IRequiredCapability; import org.eclipse.equinox.internal.p2.metadata.InstallableUnit; import org.eclipse.equinox.internal.p2.metadata.RequiredCapability; @@ -57,10 +56,11 @@ import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository; import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager; import org.eclipse.tycho.TargetPlatform; -import org.eclipse.tycho.p2.repository.ListCompositeMetadataRepository; import org.eclipse.tycho.p2.tools.DestinationRepositoryDescriptor; import org.eclipse.tycho.p2.tools.RepositoryReference; import org.eclipse.tycho.p2maven.ListCompositeArtifactRepository; +import org.eclipse.tycho.p2tools.copiedfromp2.PermissiveSlicer; +import org.eclipse.tycho.p2tools.copiedfromp2.Slicer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -106,16 +106,6 @@ public IArtifactRepository getCompositeArtifactRepository() { return repository; } - @Override - public IMetadataRepository getCompositeMetadataRepository() { - IMetadataRepository repository = super.getCompositeMetadataRepository(); - if (targetPlatform != null) { - return new ListCompositeMetadataRepository(List.of(repository, targetPlatform.getMetadataRepository()), - agent); - } - return repository; - } - @Override protected Slicer createSlicer(SlicingOptions options) { List> filters = getContextFilters(); @@ -206,6 +196,33 @@ public IQueryable slice(Collection ius, IPro } return slice; } + + @Override + protected Stream selectIUsForRequirement(IQueryable queryable, + IRequirement req) { + Stream stream = super.selectIUsForRequirement(queryable, req); + if (targetPlatform == null) { + return stream; + } + List list = stream.toList(); + if (list.isEmpty() && req.getMin() > 0) { + // It is possible that an IU is not visible to the slicer (e.g. dynamic category produced by a categorx.xml) + // In such case we additionally try to query the full target platform here. + return selectHighestIUsForRequirement(targetPlatform.getMetadataRepository(), req); + } + return list.stream(); + } + + protected Stream selectHighestIUsForRequirement(IQueryable queryable, + IRequirement req) { + //first group by ID + Map> groupById = queryable + .query(QueryUtil.createMatchQuery(req.getMatches()), null).stream().filter(this::isApplicable) + .collect(Collectors.groupingBy(IInstallableUnit::getId)); + //now select the max of items in each group with the same id + return groupById.values().stream().flatMap(list -> list.stream() + .sorted(Comparator.comparing(IInstallableUnit::getVersion).reversed()).limit(req.getMax())); + } }; } diff --git a/tycho-core/src/main/java/org/eclipse/tycho/p2tools/copiedfromp2/MirrorApplication.java b/tycho-core/src/main/java/org/eclipse/tycho/p2tools/copiedfromp2/MirrorApplication.java index 8b866fbbf5..c3218ca581 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/p2tools/copiedfromp2/MirrorApplication.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/p2tools/copiedfromp2/MirrorApplication.java @@ -22,8 +22,6 @@ import org.eclipse.equinox.app.IApplication; import org.eclipse.equinox.app.IApplicationContext; import org.eclipse.equinox.internal.p2.core.helpers.LogHelper; -import org.eclipse.equinox.internal.p2.director.PermissiveSlicer; -import org.eclipse.equinox.internal.p2.director.Slicer; import org.eclipse.equinox.internal.p2.repository.Transport; import org.eclipse.equinox.internal.p2.repository.helpers.RepositoryHelper; import org.eclipse.equinox.p2.core.IProvisioningAgent; @@ -280,7 +278,7 @@ protected Mirroring getMirroring(Collection ius, IProgressMoni * Collect all artifacts from the IUs that should be mirrored * * @param ius - * the IUs that are selected for mirroring + * the IUs that are selected for mirroring * @return a (modifiable) list of {@link IArtifactKey}s that must be mirrored */ protected List collectArtifactKeys(Collection ius, IProgressMonitor monitor) @@ -315,7 +313,7 @@ private void mirrorMetadata(Collection units, IProgressMonitor * Collect all IUS from the slice that should be mirrored * * @param slice - * the slice for mirroring + * the slice for mirroring * @return a (modifiable) set of {@link IInstallableUnit}s that must be mirrored * @throws ProvisionException */ @@ -327,9 +325,9 @@ protected Set collectUnits(IQueryable slice, } /* - * Ensure all mandatory parameters have been set. Throw an exception if there are any missing. We - * don't require the user to specify the artifact repository here, we will default to the ones - * already registered in the manager. (callers are free to add more if they wish) + * Ensure all mandatory parameters have been set. Throw an exception if there are any missing. + * We don't require the user to specify the artifact repository here, we will default to the + * ones already registered in the manager. (callers are free to add more if they wish) */ private void validate() throws ProvisionException { if (sourceRepositories.isEmpty()) diff --git a/tycho-core/src/main/java/org/eclipse/tycho/p2tools/copiedfromp2/PermissiveSlicer.java b/tycho-core/src/main/java/org/eclipse/tycho/p2tools/copiedfromp2/PermissiveSlicer.java index efd12d0ead..bb9983c113 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/p2tools/copiedfromp2/PermissiveSlicer.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/p2tools/copiedfromp2/PermissiveSlicer.java @@ -15,7 +15,6 @@ import java.util.Map; -import org.eclipse.equinox.internal.p2.director.Slicer; import org.eclipse.equinox.internal.p2.metadata.RequiredCapability; import org.eclipse.equinox.p2.metadata.IInstallableUnit; import org.eclipse.equinox.p2.metadata.IRequirement; diff --git a/tycho-core/src/main/java/org/eclipse/tycho/p2tools/copiedfromp2/Slicer.java b/tycho-core/src/main/java/org/eclipse/tycho/p2tools/copiedfromp2/Slicer.java index db43457c8a..817dbc9f0e 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/p2tools/copiedfromp2/Slicer.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/p2tools/copiedfromp2/Slicer.java @@ -24,6 +24,7 @@ import java.util.Map; import java.util.Queue; import java.util.Set; +import java.util.stream.Stream; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; @@ -44,7 +45,6 @@ import org.eclipse.equinox.p2.metadata.IRequirementChange; import org.eclipse.equinox.p2.metadata.Version; import org.eclipse.equinox.p2.metadata.expression.IMatchExpression; -import org.eclipse.equinox.p2.query.IQueryResult; import org.eclipse.equinox.p2.query.IQueryable; import org.eclipse.equinox.p2.query.QueryUtil; import org.eclipse.osgi.util.NLS; @@ -210,19 +210,14 @@ private void expandRequirement(IInstallableUnit iu, IRequirement req) { if (req.getMax() == 0) { return; } - IQueryResult matches = possibilites.query(QueryUtil.createMatchQuery(req.getMatches()), null); - int validMatches = 0; - for (IInstallableUnit match : matches) { - if (!isApplicable(match)) { - continue; - } - validMatches++; + List selected = selectIUsForRequirement(possibilites, req).toList(); + for (IInstallableUnit match : selected) { Map iuSlice = slice.get(match.getId()); if ((iuSlice == null || !iuSlice.containsKey(match.getVersion())) && considered.add(match)) { toProcess.add(match); } } - if (validMatches == 0) { + if (selected.isEmpty()) { if (req.getMin() == 0) { if (DEBUG) { System.out.println("No IU found to satisfy optional dependency of " + iu + " on req " + req); //$NON-NLS-1$//$NON-NLS-2$ @@ -233,6 +228,11 @@ private void expandRequirement(IInstallableUnit iu, IRequirement req) { } } + protected Stream selectIUsForRequirement(IQueryable queryable, + IRequirement req) { + return queryable.query(QueryUtil.createMatchQuery(req.getMatches()), null).stream().filter(this::isApplicable); + } + Set getNonGreedyIUs() { return nonGreedyIUs; } diff --git a/tycho-its/src/test/java/org/eclipse/tycho/test/p2Repository/RepoRefLocationP2RepositoryIntegrationTest.java b/tycho-its/src/test/java/org/eclipse/tycho/test/p2Repository/RepoRefLocationP2RepositoryIntegrationTest.java index ec13224e39..851537d77a 100644 --- a/tycho-its/src/test/java/org/eclipse/tycho/test/p2Repository/RepoRefLocationP2RepositoryIntegrationTest.java +++ b/tycho-its/src/test/java/org/eclipse/tycho/test/p2Repository/RepoRefLocationP2RepositoryIntegrationTest.java @@ -24,6 +24,7 @@ import java.io.File; import java.util.List; import java.util.function.Consumer; +import java.util.stream.Collectors; import org.apache.maven.it.VerificationException; import org.apache.maven.it.Verifier; @@ -77,7 +78,8 @@ public void testAdditionOfOnlyProvidingRepos() throws Exception { "/p2Repository.repositoryRef.filter.providing", c -> { }); - assertEquals(4, allRepositoryReferences.size()); + assertEquals(allRepositoryReferences.stream().map(rr -> rr.uri()).collect(Collectors.joining(", ")), 4, + allRepositoryReferences.size()); assertThat(allRepositoryReferences, containsInAnyOrder( // new RepositoryReference("https://download.eclipse.org/eclipse/updates/4.29", TYPE_ARTIFACT, ENABLED), new RepositoryReference("https://download.eclipse.org/eclipse/updates/4.29", TYPE_METADATA, ENABLED), diff --git a/tycho-testing-harness/src/main/java/org/eclipse/tycho/test/AbstractTychoIntegrationTest.java b/tycho-testing-harness/src/main/java/org/eclipse/tycho/test/AbstractTychoIntegrationTest.java index 31ba59f72a..3e71c90c0c 100644 --- a/tycho-testing-harness/src/main/java/org/eclipse/tycho/test/AbstractTychoIntegrationTest.java +++ b/tycho-testing-harness/src/main/java/org/eclipse/tycho/test/AbstractTychoIntegrationTest.java @@ -214,7 +214,10 @@ protected File[] assertFileExists(File baseDir, String pattern) { DirectoryScanner ds = scan(baseDir, pattern); File[] includedFiles = Arrays.stream(ds.getIncludedFiles()).map(file -> new File(baseDir, file)) .toArray(File[]::new); - assertEquals(baseDir.getAbsolutePath() + "/" + pattern, 1, includedFiles.length); + assertEquals( + baseDir.getAbsolutePath() + "/" + pattern + System.lineSeparator() + Arrays.stream(includedFiles) + .map(f -> f.getName()).collect(Collectors.joining(System.lineSeparator())), + 1, includedFiles.length); assertTrue(baseDir.getAbsolutePath() + "/" + pattern, includedFiles[0].canRead()); return includedFiles; }