diff --git a/src/site/markdown/Category.md b/src/site/markdown/Category.md index 307a849b4c..c8517dc96e 100644 --- a/src/site/markdown/Category.md +++ b/src/site/markdown/Category.md @@ -32,8 +32,10 @@ The following is an example, demonstrating a complex category definition. + + @@ -58,7 +60,11 @@ The following is an example, demonstrating a complex category definition. - id ~= /javax.*/ + + id ~= /javax.*/ + -``` \ No newline at end of file +``` + +You can read more about P2 Query Syntax [here](https://wiki.eclipse.org/Equinox/p2/Query_Language_for_p2). diff --git a/tycho-core/src/main/java/org/eclipse/tycho/p2/tools/publisher/PublisherActionRunner.java b/tycho-core/src/main/java/org/eclipse/tycho/p2/tools/publisher/PublisherActionRunner.java index ed5c02b328..197ae94481 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/p2/tools/publisher/PublisherActionRunner.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/p2/tools/publisher/PublisherActionRunner.java @@ -96,10 +96,9 @@ private void setTargetEnvironments(PublisherInfo publisherInfo) { private void handlePublisherStatus(IStatus result) { if (result.matches(IStatus.INFO)) { - logger.info(StatusTool.collectProblems(result)); + logger.info(StatusTool.toLogMessage(result)); } else if (result.matches(IStatus.WARNING)) { - logger.warn(StatusTool.collectProblems(result)); - + logger.warn(StatusTool.toLogMessage(result)); } else if (!result.isOK()) { Throwable directlyIncludedException = result.getException(); throw directlyIncludedException instanceof RuntimeException runtimeEx // diff --git a/tycho-core/src/main/java/org/eclipse/tycho/p2tools/MirrorApplicationServiceImpl.java b/tycho-core/src/main/java/org/eclipse/tycho/p2tools/MirrorApplicationServiceImpl.java index 4709107cdb..76a629c9eb 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/p2tools/MirrorApplicationServiceImpl.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/p2tools/MirrorApplicationServiceImpl.java @@ -354,7 +354,7 @@ static class LogListener implements IArtifactMirrorLog { @Override public void log(IArtifactDescriptor descriptor, IStatus status) { if (!status.isOK()) { - logger.debug(MIRROR_TOOL_MESSAGE_PREFIX + StatusTool.collectProblems(status)); + logger.debug(MIRROR_TOOL_MESSAGE_PREFIX + StatusTool.toLogMessage(status)); hasLogged = true; } } @@ -362,7 +362,7 @@ public void log(IArtifactDescriptor descriptor, IStatus status) { @Override public void log(IStatus status) { if (!status.isOK()) { - logger.warn(MIRROR_TOOL_MESSAGE_PREFIX + StatusTool.collectProblems(status)); + logger.warn(MIRROR_TOOL_MESSAGE_PREFIX + StatusTool.toLogMessage(status)); hasLogged = true; } } 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 8406843f51..1cbfc30708 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; @@ -59,6 +58,9 @@ import org.eclipse.tycho.TargetPlatform; 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; @@ -94,6 +96,16 @@ protected IArtifactRepository initializeDestination(RepositoryDescriptor toInit, return result; } + @Override + public IArtifactRepository getCompositeArtifactRepository() { + IArtifactRepository repository = super.getCompositeArtifactRepository(); + if (targetPlatform != null) { + return new ListCompositeArtifactRepository(List.of(repository, targetPlatform.getArtifactRepository()), + agent); + } + return repository; + } + @Override protected Slicer createSlicer(SlicingOptions options) { List> filters = getContextFilters(); @@ -184,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 867c0fb77b..60ec25fa15 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 @@ -23,6 +23,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; @@ -76,7 +77,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 1862059973..4ac5c0421a 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; }