Skip to content

Commit

Permalink
Assemble repository for all environments in one pass
Browse files Browse the repository at this point in the history
  • Loading branch information
HannesWell committed Sep 27, 2023
1 parent 05c76bd commit fe7266b
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<String, String> 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<String, String> 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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
*
* Contributors:
* SAP SE - initial API and implementation
* Hannes Wellmann - Assemble repository for all environments in one pass
*******************************************************************************/
package org.eclipse.tycho.p2tools;

Expand All @@ -29,6 +30,8 @@
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;
import org.eclipse.equinox.p2.core.IProvisioningAgent;
import org.eclipse.equinox.p2.core.ProvisionException;
import org.eclipse.equinox.p2.internal.repository.tools.RepositoryDescriptor;
Expand Down Expand Up @@ -82,13 +85,16 @@ protected IArtifactRepository initializeDestination(RepositoryDescriptor toInit,

@Override
protected Slicer createSlicer(SlicingOptions options) {
Map<String, String> context = options.getFilter();
List<Map<String, String>> filters = getContextFilters();
List<IInstallableUnit> 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) {
boolean considerOnlyStrictDependency = options.considerStrictDependencyOnly();
return new PermissiveSlicer(repository, filters.get(0), includeOptionalDependencies,
options.isEverythingGreedy(), evalFilterTo, considerOnlyStrictDependency, onlyFilteredRequirements) {
@Override
protected boolean isApplicable(IInstallableUnit iu, IRequirement req) {
if ((includeRequiredBundles || includeRequiredFeatures) && QueryUtil.isGroup(iu)
Expand All @@ -103,15 +109,43 @@ 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);
return isApplicable(req);
}

@Override
protected boolean isApplicable(IRequirement req) {
throw new UnsupportedOperationException("should never be called!");
//Every filter in this method needs to continue except when the filter does not pass
if (!includeOptionalDependencies && req.getMin() == 0) {
return false;
}
if (considerOnlyStrictDependency && !RequiredCapability.isStrictVersionRequirement(req.getMatches())) {
return false;
}
//deal with filters
IMatchExpression<IInstallableUnit> filter = req.getFilter();
if (considerFilter) {
if (onlyFilteredRequirements && filter == null) {
return false;
}
return filter == null || matchesSelectionContext(filter);
}
return filter == null ? !onlyFilteredRequirements : evalFilterTo;
}

@Override
protected boolean isApplicable(IInstallableUnit iu) {
if (considerFilter) {
IMatchExpression<IInstallableUnit> filter = iu.getFilter();
return filter == null || matchesSelectionContext(filter);
}
return iu.getFilter() == null || evalFilterTo;
}

private boolean matchesSelectionContext(IMatchExpression<IInstallableUnit> filter) {
return selectionContexts.stream().anyMatch(filter::isMatch);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -43,7 +44,6 @@
import org.eclipse.equinox.p2.metadata.VersionRange;
import org.eclipse.equinox.p2.planner.IPlanner;
import org.eclipse.equinox.p2.planner.IProfileChangeRequest;
import org.eclipse.equinox.p2.query.CompoundQueryable;
import org.eclipse.equinox.p2.query.IQuery;
import org.eclipse.equinox.p2.query.IQueryResult;
import org.eclipse.equinox.p2.query.IQueryable;
Expand All @@ -52,13 +52,15 @@
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$
private static final String LOG_ROOT = "p2.mirror"; //$NON-NLS-1$
private static final String MIRROR_MODE = "metadataOrArtifacts"; //$NON-NLS-1$

protected SlicingOptions slicingOptions = new SlicingOptions();
protected List<TargetEnvironment> environments = new ArrayList<>();

private URI baseline;
private String comparatorID;
Expand Down Expand Up @@ -397,22 +399,35 @@ private IArtifactMirrorLog getLog(File location, String root) {
}

private IQueryable<IInstallableUnit> performResolution(IProgressMonitor monitor) throws ProvisionException {
List<Map<String, String>> 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<IInstallableUnit>[] 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<IQueryable<IInstallableUnit>> queryables = new ArrayList<>();
for (Map<String, String> 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 QueryUtil.compoundQueryable(queryables);
}

protected List<Map<String, String>> getContextFilters() {
return environments.isEmpty() ? List.of(slicingOptions.getFilter()) : environments.stream().map(environment -> {
Map<String, String> filter = new HashMap<>(slicingOptions.getFilter());
filter.putAll(environment.toFilterProperties());
return filter;
}).toList();
}

private IProfileRegistry getProfileRegistry() throws ProvisionException {
Expand Down Expand Up @@ -452,6 +467,10 @@ protected Slicer createSlicer(SlicingOptions options) {
return slicer;
}

public void setEnvironments(List<TargetEnvironment> environments) {
this.environments = environments;
}

public void setSlicingOptions(SlicingOptions options) {
slicingOptions = options;
}
Expand Down

0 comments on commit fe7266b

Please sign in to comment.