Skip to content

Commit

Permalink
Pass the profile properties so they can be considered in the resolve
Browse files Browse the repository at this point in the history
  • Loading branch information
laeubi committed Dec 10, 2023
1 parent 579e03b commit 352827a
Show file tree
Hide file tree
Showing 7 changed files with 56 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;

import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
Expand All @@ -27,6 +28,7 @@
import org.eclipse.equinox.internal.p2.metadata.InstallableUnit;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.metadata.IRequirement;
import org.eclipse.equinox.p2.metadata.expression.IMatchExpression;
import org.eclipse.equinox.p2.query.CollectionResult;
import org.eclipse.equinox.p2.query.IQueryResult;
import org.eclipse.equinox.p2.query.IQueryable;
Expand Down Expand Up @@ -73,15 +75,20 @@ public IQueryResult<IInstallableUnit> computeDependencies(Collection<IInstallabl
* {@link IInstallableUnit}s in a way that the result contains any unit that
* satisfies a requirement in for rootIus
*
* @param rootIus the root {@link InstallableUnit}s to take into account
* @param avaiableIUs the {@link IQueryable} of all units that could be used for
* fulfilling a requirement
* @param rootIus the root {@link InstallableUnit}s to take into
* account
* @param avaiableIUs the {@link IQueryable} of all units that could be
* used for fulfilling a requirement
* @param profileProperties the profile properties to consider during
* resolution, can be empty in which case a filter is
* always considered a match
* @return the result of the slicing
* @throws CoreException if there is any error
*/
public IQueryResult<IInstallableUnit> computeDirectDependencies(Collection<IInstallableUnit> rootIus,
IQueryable<IInstallableUnit> avaiableIUs) throws CoreException {
IQueryable<IInstallableUnit> avaiableIUs, Map<String, String> profileProperties) throws CoreException {
Collection<IInstallableUnit> result = new LinkedHashSet<>();
IInstallableUnit selectionContext = InstallableUnit.contextIU(profileProperties);
List<IRequirement> collect = rootIus.stream().flatMap(iu -> iu.getRequirements().stream()).filter(req -> {
for (IInstallableUnit unit : rootIus) {
if (unit.satisfies(req)) {
Expand All @@ -91,13 +98,20 @@ public IQueryResult<IInstallableUnit> computeDirectDependencies(Collection<IInst
}
return true;
}).toList();
boolean considerFilter = profileProperties.size() > 0;
for (IInstallableUnit iu : avaiableIUs.query(QueryUtil.ALL_UNITS, new NullProgressMonitor()).toSet()) {
for (IRequirement requirement : collect) {
// Negative requirements should not create a dependency.
// If there is a filter, we need more context, e.g, see
// org.eclipse.equinox.internal.p2.director.Slicer.isApplicable(IRequirement)
// Failing that, we need to assume the filter isn't applicable.
if (requirement.getMax() != 0 && requirement.getFilter() == null && iu.satisfies(requirement)) {
if (requirement.getMax() == 0) {
continue;
}
IMatchExpression<IInstallableUnit> filter = requirement.getFilter();
// If there is a filter, we need to evaluate
if (considerFilter && filter != null && !filter.isMatch(selectionContext)) {
// filter does not match...
continue;
}
if (iu.satisfies(requirement)) {
result.add(iu);
// TODO remove the requirement from the set so we only collect exactly one
// provider for a requirement?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

Expand Down Expand Up @@ -72,19 +73,23 @@ public class MavenProjectDependencyProcessor {
* Computes the {@link ProjectDependencyClosure} of the given collection of
* projects.
*
* @param projects the projects to include in the closure
* @param session the maven session for this request
* @param projects the projects to include in the closure
* @param session the maven session for this request
* @param profileProperties the profile properties to consider when evaluating
* filters, can be empty in which case a filter is
* always considered a match
* @return the computed {@link ProjectDependencyClosure}
* @throws CoreException if computation failed
*/
public ProjectDependencyClosure computeProjectDependencyClosure(Collection<MavenProject> projects,
MavenSession session) throws CoreException {
MavenSession session, Function<MavenProject, Map<String, String>> profilePropertiesSupplier)
throws CoreException {
Objects.requireNonNull(session);
Map<MavenProject, Collection<IInstallableUnit>> projectIUMap = generator.getInstallableUnits(projects, session);
Collection<IInstallableUnit> availableIUs = projectIUMap.values().stream().flatMap(Collection::stream)
.collect(Collectors.toSet());
Map<MavenProject, ProjectDependencies> projectDependenciesMap = computeProjectDependencies(projects,
new CollectionResult<>(availableIUs), projectIUMap);
new CollectionResult<>(availableIUs), projectIUMap, profilePropertiesSupplier);
Map<IInstallableUnit, MavenProject> iuProjectMap = new HashMap<>();
for (var entry : projectIUMap.entrySet()) {
MavenProject mavenProject = entry.getKey();
Expand Down Expand Up @@ -138,14 +143,15 @@ public Collection<IInstallableUnit> getProjectUnits(MavenProject mavenProject) {
* @throws CoreException if computation failed
*/
private Map<MavenProject, ProjectDependencies> computeProjectDependencies(Collection<MavenProject> projects,
IQueryable<IInstallableUnit> avaiableIUs, Map<MavenProject, Collection<IInstallableUnit>> projectIUMap)
IQueryable<IInstallableUnit> avaiableIUs, Map<MavenProject, Collection<IInstallableUnit>> projectIUMap,
Function<MavenProject, Map<String, String>> profilePropertiesSupplier)
throws CoreException {
List<CoreException> errors = new CopyOnWriteArrayList<>();
Map<MavenProject, ProjectDependencies> result = new ConcurrentHashMap<>();
projects.parallelStream().unordered().takeWhile(nil -> errors.isEmpty()).forEach(project -> {
try {
ProjectDependencies projectDependencies = computeProjectDependencies(projectIUMap.get(project),
avaiableIUs);
avaiableIUs, profilePropertiesSupplier.apply(project));
result.put(project, projectDependencies);
if (DUMP_DATA) {
File file = new File(project.getBasedir(), "project-dependencies.xml");
Expand Down Expand Up @@ -182,12 +188,12 @@ private Map<MavenProject, ProjectDependencies> computeProjectDependencies(Collec
* @throws CoreException if computation failed
*/
private ProjectDependencies computeProjectDependencies(Collection<IInstallableUnit> projectUnits,
IQueryable<IInstallableUnit> avaiableIUs) throws CoreException {
IQueryable<IInstallableUnit> avaiableIUs, Map<String, String> profileProperties) throws CoreException {
if (projectUnits.isEmpty()) {
return EMPTY_DEPENDENCIES;
}
Set<IInstallableUnit> resolved = new LinkedHashSet<>(
slicer.computeDirectDependencies(projectUnits, avaiableIUs).toSet());
slicer.computeDirectDependencies(projectUnits, avaiableIUs, profileProperties).toSet());
resolved.removeAll(projectUnits);
// now we need to filter all fragments that we are a host!
// for example SWT creates an explicit requirement to its fragments and we don't
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
package org.eclipse.tycho;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
Expand Down Expand Up @@ -88,7 +87,7 @@ public boolean isWindows() {
* Returns the target environment as map. The keys are "osgi.ws", "osgi.os", and "osgi.arch".
* This format is used by the p2 slicer to filter installable units by environments.
*
* @return a new instance of {@link HashMap} with the target environment set
* @return a new instance of {@link LinkedHashMap} with the target environment set
*/
public Map<String, String> toFilterProperties() {
//for nicer debug output, use an ordered map here
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,10 @@ public Result<ProjectDependencyGraph> build(MavenSession session) {
try {
ProjectDependencyClosure dependencyClosure;
try {
dependencyClosure = dependencyProcessor.computeProjectDependencyClosure(projects, session);
// here we don't use filters, the worst that can happen is that we get more
// projects to consider...
dependencyClosure = dependencyProcessor.computeProjectDependencyClosure(projects, session,
always -> Map.of());
} catch (CoreException e) {
log.error("Cannot resolve projects", e);
return Result.error(graph, toProblems(e.getStatus(), new ArrayList<>()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import org.eclipse.tycho.ExecutionEnvironmentConfiguration;
import org.eclipse.tycho.ReactorProject;
import org.eclipse.tycho.ResolvedArtifactKey;
import org.eclipse.tycho.TargetEnvironment;
import org.eclipse.tycho.TargetPlatform;
import org.eclipse.tycho.TargetPlatformService;
import org.eclipse.tycho.TychoConstants;
Expand Down Expand Up @@ -143,6 +144,18 @@ public void readExecutionEnvironmentConfiguration(ReactorProject project, Execut
}
}

public Map<String, String> getProfileProperties(MavenProject project) {
return getProfileProperties(project, TargetEnvironment.getRunningEnvironment());
}

public Map<String, String> getProfileProperties(MavenProject project, TargetEnvironment environment) {
TargetPlatformConfiguration configuration = getTargetPlatformConfiguration(project);
Map<String, String> properties = environment.toFilterProperties();
properties.put("org.eclipse.update.install.features", "true");
properties.putAll(configuration.getProfileProperties());
return properties;
}

public TargetPlatformConfiguration getTargetPlatformConfiguration(MavenProject project) {
ReactorProject reactorProject = DefaultReactorProject.adapt(project);
return reactorProject.computeContextValue(CTX_TARGET_PLATFORM_CONFIGURATION,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ public void afterProjectsRead(MavenSession session) throws MavenExecutionExcepti
if (lazyProjects.size() > 0) {
try {
ProjectDependencyClosure closure = dependencyProcessor.computeProjectDependencyClosure(projects,
session);
session, projectManager::getProfileProperties);
for (MavenProject project : lazyProjects) {
if (projectManager.getTychoProject(project).isEmpty()) {
//do not inject additional dependencies for non Tycho managed projects!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@ public class JustJCycleTest extends AbstractTychoIntegrationTest {
@Test
public void testCustomBundleParent() throws Exception {
Verifier verifier = getVerifier("justj-cycle");
verifier.setForkJvm(false);
verifier.setSystemProperty("user.home", System.getProperty("user.home"));
verifier.executeGoal("verify");
verifier.executeGoal("initialize");
verifier.verifyErrorFreeLog();
}
}

0 comments on commit 352827a

Please sign in to comment.