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 cc249ffaf9..f54ca5fae2 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 @@ -51,7 +51,6 @@ import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository; import org.eclipse.tycho.ArtifactType; import org.eclipse.tycho.BuildDirectory; -import org.eclipse.tycho.TargetEnvironment; import org.eclipse.tycho.core.resolver.shared.DependencySeed; import org.eclipse.tycho.core.shared.StatusTool; import org.eclipse.tycho.p2.repository.GAV; @@ -164,28 +163,24 @@ public void mirrorReactor(RepositoryReferences sources, DestinationRepositoryDes mirrorApp.setIncludeRequiredFeatures(includeRequiredFeatures); mirrorApp.setIncludePacked(false); // no way, Tycho do no longer support packed artifacts anyways mirrorApp.setFilterProvided(filterProvided); - // TODO the p2 mirror tool should support mirroring multiple environments at once - for (TargetEnvironment environment : context.getEnvironments()) { - SlicingOptions options = new SlicingOptions(); - options.considerStrictDependencyOnly(!includeAllDependencies); - Map filter = options.getFilter(); - addFilterForFeatureJARs(filter); - if (filterProperties != null) { - filter.putAll(filterProperties); - } - filter.putAll(environment.toFilterProperties()); - mirrorApp.setSlicingOptions(options); - - try { - LogListener logListener = new LogListener(logger); - mirrorApp.setLog(logListener); - - IStatus returnStatus = mirrorApp.run(null); - checkStatus(returnStatus, false); - logListener.showHelpForLoggedMessages(); - } catch (ProvisionException e) { - throw new FacadeException(MIRROR_FAILURE_MESSAGE + ": " + StatusTool.collectProblems(e.getStatus()), e); - } + mirrorApp.setEnvironments(context.getEnvironments()); + SlicingOptions options = new SlicingOptions(); + options.considerStrictDependencyOnly(!includeAllDependencies); + Map filter = options.getFilter(); + addFilterForFeatureJARs(filter); + if (filterProperties != null) { + filter.putAll(filterProperties); + } + mirrorApp.setSlicingOptions(options); + try { + LogListener logListener = new LogListener(logger); + mirrorApp.setLog(logListener); + + IStatus returnStatus = mirrorApp.run(null); + checkStatus(returnStatus, false); + logListener.showHelpForLoggedMessages(); + } catch (ProvisionException e) { + throw new FacadeException(MIRROR_FAILURE_MESSAGE + ": " + StatusTool.collectProblems(e.getStatus()), e); } recreateArtifactRepository(destination); } 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 78e8d2a996..d59bf812bc 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 @@ -29,6 +29,7 @@ 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.p2.core.IProvisioningAgent; import org.eclipse.equinox.p2.core.ProvisionException; import org.eclipse.equinox.p2.internal.repository.tools.RepositoryDescriptor; @@ -82,13 +83,16 @@ protected IArtifactRepository initializeDestination(RepositoryDescriptor toInit, @Override protected Slicer createSlicer(SlicingOptions options) { - Map context = options.getFilter(); + List> filters = getContextFilters(); + List selectionContexts = filters.stream().map(InstallableUnit::contextIU).toList(); boolean includeOptionalDependencies = options.includeOptionalDependencies(); boolean onlyFilteredRequirements = options.followOnlyFilteredRequirements(); - boolean considerFilter = context != null && context.size() > 1; + boolean considerFilter = filters.stream().anyMatch(f -> f.size() > 1); + boolean evalFilterTo = options.forceFilterTo(); IMetadataRepository repository = getCompositeMetadataRepository(); - return new PermissiveSlicer(repository, context, includeOptionalDependencies, options.isEverythingGreedy(), - options.forceFilterTo(), options.considerStrictDependencyOnly(), onlyFilteredRequirements) { + return new PermissiveSlicer(repository, filters.get(0), includeOptionalDependencies, + options.isEverythingGreedy(), evalFilterTo, options.considerStrictDependencyOnly(), + onlyFilteredRequirements) { @Override protected boolean isApplicable(IInstallableUnit iu, IRequirement req) { if ((includeRequiredBundles || includeRequiredFeatures) && QueryUtil.isGroup(iu) @@ -103,17 +107,30 @@ protected boolean isApplicable(IInstallableUnit iu, IRequirement req) { if (onlyFilteredRequirements && filter == null) { return false; } - return !considerFilter || filter == null || filter.isMatch(selectionContext); + return !considerFilter || filter == null || matchesSelectionContext(filter); } } return super.isApplicable(req); } + @Override + protected boolean isApplicable(IInstallableUnit iu) { + if (considerFilter) { + IMatchExpression filter = iu.getFilter(); + return filter == null || matchesSelectionContext(filter); + } + return iu.getFilter() == null || evalFilterTo; + } + @Override protected boolean isApplicable(IRequirement req) { throw new UnsupportedOperationException("should never be called!"); } + private boolean matchesSelectionContext(IMatchExpression filter) { + return selectionContexts.stream().anyMatch(filter::isMatch); + } + @Override public IQueryable slice(IInstallableUnit[] ius, IProgressMonitor monitor) { IQueryable slice = super.slice(ius, monitor); 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 25a7e45579..706a2d788a 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 @@ -5,6 +5,7 @@ import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -52,6 +53,7 @@ import org.eclipse.equinox.p2.repository.artifact.IArtifactRepository; import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository; import org.eclipse.osgi.util.NLS; +import org.eclipse.tycho.TargetEnvironment; public class MirrorApplication extends AbstractApplication implements IApplication, IExecutableExtension { private static final String DEFAULT_COMPARATOR = ArtifactChecksumComparator.COMPARATOR_ID + ".sha-256"; //$NON-NLS-1$ @@ -59,6 +61,7 @@ public class MirrorApplication extends AbstractApplication implements IApplicati private static final String MIRROR_MODE = "metadataOrArtifacts"; //$NON-NLS-1$ protected SlicingOptions slicingOptions = new SlicingOptions(); + protected List environments = new ArrayList<>(); private URI baseline; private String comparatorID; @@ -396,23 +399,39 @@ private IArtifactMirrorLog getLog(File location, String root) { return new FileMirrorLog(absolutePath, 0, root); } + @SuppressWarnings("unchecked") + private static final IQueryable[] EMPTY = new IQueryable[0]; + private IQueryable performResolution(IProgressMonitor monitor) throws ProvisionException { + List> filters = getContextFilters(); IProfileRegistry registry = getProfileRegistry(); String profileId = "MirrorApplication-" + System.currentTimeMillis(); //$NON-NLS-1$ - IProfile profile = registry.addProfile(profileId, slicingOptions.getFilter()); - IPlanner planner = agent.getService(IPlanner.class); - if (planner == null) - throw new IllegalStateException(); - IProfileChangeRequest pcr = planner.createChangeRequest(profile); - pcr.addAll(sourceIUs); - IProvisioningPlan plan = planner.getProvisioningPlan(pcr, null, monitor); - registry.removeProfile(profileId); - @SuppressWarnings("unchecked") - IQueryable[] arr = new IQueryable[plan.getInstallerPlan() == null ? 1 : 2]; - arr[0] = plan.getAdditions(); - if (plan.getInstallerPlan() != null) - arr[1] = plan.getInstallerPlan().getAdditions(); - return new CompoundQueryable<>(arr); + List> queryables = new ArrayList<>(); + for (Map filter : filters) { + IProfile profile = registry.addProfile(profileId, filter); + IPlanner planner = agent.getService(IPlanner.class); + if (planner == null) { + throw new IllegalStateException(); + } + IProfileChangeRequest pcr = planner.createChangeRequest(profile); + pcr.addAll(sourceIUs); + IProvisioningPlan plan = planner.getProvisioningPlan(pcr, null, monitor); + registry.removeProfile(profileId); + queryables.add(plan.getAdditions()); + IProvisioningPlan installerPlan = plan.getInstallerPlan(); + if (installerPlan != null) { + queryables.add(installerPlan.getAdditions()); + } + } + return new CompoundQueryable<>(queryables.toArray(EMPTY)); + } + + protected List> getContextFilters() { + return environments.isEmpty() ? List.of(slicingOptions.getFilter()) : environments.stream().map(environment -> { + Map filter = new HashMap<>(slicingOptions.getFilter()); + filter.putAll(environment.toFilterProperties()); + return filter; + }).toList(); } private IProfileRegistry getProfileRegistry() throws ProvisionException { @@ -452,6 +471,10 @@ protected Slicer createSlicer(SlicingOptions options) { return slicer; } + public void setEnvironments(List environments) { + this.environments = environments; + } + public void setSlicingOptions(SlicingOptions options) { slicingOptions = options; }