Skip to content

Commit

Permalink
Add preliminary work
Browse files Browse the repository at this point in the history
  • Loading branch information
laeubi committed Dec 10, 2023
1 parent d2188aa commit 7c24bc7
Show file tree
Hide file tree
Showing 7 changed files with 121 additions and 45 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*******************************************************************************
* Copyright (c) 2023 Christoph Läubrich and others.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Christoph Läubrich - initial API and implementation
*******************************************************************************/
package org.eclipse.tycho.p2maven;

import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.metadata.IRequirement;

public class DirectDependenciesResult {

private Map<IRequirement, List<IInstallableUnit>> unitMap;

DirectDependenciesResult(Map<IRequirement, List<IInstallableUnit>> unitMap) {
this.unitMap = unitMap;
}

/**
* @return a all units contained in the results
*/
public List<IInstallableUnit> units() {
return unitMap.values().stream().flatMap(Collection::stream).distinct().toList();
}

public Collection<IRequirement> requirements() {
return unitMap.keySet();
}

public Collection<IInstallableUnit> getUnits(IRequirement requirement) {
return unitMap.getOrDefault(requirement, List.of());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,9 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
Expand All @@ -31,8 +29,6 @@
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;
import org.eclipse.equinox.p2.query.QueryUtil;
Expand Down Expand Up @@ -87,51 +83,28 @@ public IQueryResult<IInstallableUnit> computeDependencies(Collection<IInstallabl
* @return the result of the slicing
* @throws CoreException if there is any error
*/
public IQueryResult<IInstallableUnit> computeDirectDependencies(Collection<IInstallableUnit> rootIus,
IQueryable<IInstallableUnit> avaiableIUs, Collection<IInstallableUnit> contextIUs) throws CoreException {
Collection<IInstallableUnit> result = new LinkedHashSet<>();
Map<Boolean, List<IRequirement>> collect = rootIus.stream().flatMap(iu -> iu.getRequirements().stream())
public DirectDependenciesResult computeDirectDependencies(Collection<IInstallableUnit> rootIus,
IQueryable<IInstallableUnit> avaiableIUs) throws CoreException {
List<IRequirement> collect = rootIus.stream().flatMap(iu -> iu.getRequirements().stream())
.filter(req -> {
for (IInstallableUnit unit : rootIus) {
if (unit.satisfies(req)) {
// self full filled requirement
return false;
}
}
return isMatch(req.getFilter(), contextIUs);
}).collect(Collectors.partitioningBy(req -> req.getMax() == 0));
List<IRequirement> negativeRequirements = collect.get(true);
List<IRequirement> requirements = new ArrayList<>(collect.get(false));

return true;
}).toList();
Map<IRequirement, List<IInstallableUnit>> unitMap = new LinkedHashMap<>();
for (IInstallableUnit iu : avaiableIUs.query(QueryUtil.ALL_UNITS, new NullProgressMonitor()).toSet()) {
for (Iterator<IRequirement> iterator = requirements.iterator(); iterator.hasNext();) {
IRequirement requirement = iterator.next();
for (IRequirement requirement : collect) {
if (iu.satisfies(requirement)) {
result.add(iu);
if (requirement.getMax() == 1) {
// only one provider allowed
iterator.remove();
}
break;
// need to add it to the book
unitMap.computeIfAbsent(requirement, nil -> new ArrayList<>()).add(iu);
}
}
// now check if the IU satisfies any negative one, then we need to remove it
// from the set...
for (IRequirement requirement : negativeRequirements) {
if (iu.satisfies(requirement)) {
result.remove(iu);
break;
}
}
}
return new CollectionResult<>(result);
}

private boolean isMatch(IMatchExpression<IInstallableUnit> filter, Collection<IInstallableUnit> contextIUs) {
if (filter == null || contextIUs.isEmpty()) {
return true;
}
return contextIUs.stream().anyMatch(contextIU -> filter.isMatch(contextIU));
return new DirectDependenciesResult(unitMap);
}

private final class TychoSlicer extends PermissiveSlicer {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.metadata.IProvidedCapability;
import org.eclipse.equinox.p2.metadata.IRequirement;
import org.eclipse.equinox.p2.metadata.expression.IMatchExpression;
import org.eclipse.equinox.p2.publisher.eclipse.BundlesAction;
import org.eclipse.equinox.p2.query.CollectionResult;
import org.eclipse.equinox.p2.query.IQueryable;
Expand All @@ -58,7 +59,7 @@
public class MavenProjectDependencyProcessor {

private static final ProjectDependencies EMPTY_DEPENDENCIES = new ProjectDependencies(Collections.emptyList(),
Collections.emptyList());
Collections.emptyList(), Collections.emptyList());

private static final boolean DUMP_DATA = Boolean.getBoolean("tycho.p2.dump")
|| Boolean.getBoolean("tycho.p2.dump.dependencies");
Expand Down Expand Up @@ -146,8 +147,7 @@ public Collection<IInstallableUnit> getProjectUnits(MavenProject mavenProject) {
*/
private Map<MavenProject, ProjectDependencies> computeProjectDependencies(Collection<MavenProject> projects,
IQueryable<IInstallableUnit> avaiableIUs, Map<MavenProject, Collection<IInstallableUnit>> projectIUMap,
Function<MavenProject, Collection<IInstallableUnit>> profilePropertiesSupplier)
throws CoreException {
Function<MavenProject, Collection<IInstallableUnit>> profilePropertiesSupplier) throws CoreException {
List<CoreException> errors = new CopyOnWriteArrayList<>();
Map<MavenProject, ProjectDependencies> result = new ConcurrentHashMap<>();
projects.parallelStream().unordered().takeWhile(nil -> errors.isEmpty()).forEach(project -> {
Expand Down Expand Up @@ -195,8 +195,20 @@ private ProjectDependencies computeProjectDependencies(Collection<IInstallableUn
if (projectUnits.isEmpty()) {
return EMPTY_DEPENDENCIES;
}
Set<IInstallableUnit> resolved = new LinkedHashSet<>(
slicer.computeDirectDependencies(projectUnits, avaiableIUs, profileProperties).toSet());
DirectDependenciesResult dependencies = slicer.computeDirectDependencies(projectUnits, avaiableIUs);
// first collect the maximum desired number
Set<IInstallableUnit> resolved = new LinkedHashSet<>();
Set<IInstallableUnit> unmatched = new LinkedHashSet<>();
Collection<IRequirement> requirements = dependencies.requirements();
for (IRequirement requirement : requirements) {
Collection<IInstallableUnit> units = dependencies.getUnits(requirement);
List<IInstallableUnit> limit = units.stream().limit(requirement.getMax()).toList();
resolved.addAll(limit);
if (isMatch(requirement, profileProperties)) {
unmatched.addAll(limit);
}
}
// remove everything that is our own units...
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 All @@ -209,7 +221,15 @@ private ProjectDependencies computeProjectDependencies(Collection<IInstallableUn
iterator.remove();
}
}
return new ProjectDependencies(resolved, projectFragments);
return new ProjectDependencies(resolved, projectFragments, unmatched);
}

private boolean isMatch(IRequirement requirement, Collection<IInstallableUnit> contextIUs) {
IMatchExpression<IInstallableUnit> filter = requirement.getFilter();
if (filter == null || contextIUs.isEmpty()) {
return true;
}
return contextIUs.stream().anyMatch(contextIU -> filter.isMatch(contextIU));
}

private static boolean hasAnyHost(IInstallableUnit unit, Iterable<IInstallableUnit> collection) {
Expand Down Expand Up @@ -251,10 +271,13 @@ public static final class ProjectDependencies {

private final Collection<IInstallableUnit> dependencies;
private final Collection<IInstallableUnit> fragments;
private final Collection<IInstallableUnit> unmatched;

private ProjectDependencies(Collection<IInstallableUnit> dependencies, Collection<IInstallableUnit> fragments) {
private ProjectDependencies(Collection<IInstallableUnit> dependencies, Collection<IInstallableUnit> fragments,
Collection<IInstallableUnit> unmatched) {
this.dependencies = dependencies;
this.fragments = fragments;
this.unmatched = unmatched;
}

public Collection<IInstallableUnit> getDependencies() {
Expand All @@ -265,6 +288,13 @@ public Collection<IInstallableUnit> getFragments() {
return fragments;
}

/**
* @return return all units that don'T match the current profile filters
*/
public Collection<IInstallableUnit> getUnmatched() {
return unmatched;
}

}

public static interface ProjectDependencyClosure {
Expand Down Expand Up @@ -305,6 +335,7 @@ default Collection<MavenProject> getDependencyProjects(MavenProject mavenProject
if (isFragment(mavenProject)) {
return list;
}
// TODO check if this is a negated/inactive dependecy...
return list.stream().flatMap(project -> {
ProjectDependencies dependecies = getProjectDependecies(project);
if (dependecies.getFragments().isEmpty()) {
Expand Down
8 changes: 8 additions & 0 deletions tycho-baseline-plugin/.settings/org.eclipse.jdt.core.prefs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
org.eclipse.jdt.core.compiler.compliance=17
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
org.eclipse.jdt.core.compiler.release=disabled
org.eclipse.jdt.core.compiler.source=17
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,10 @@ public void afterProjectsRead(MavenSession session) throws MavenExecutionExcepti
continue;
}
Collection<MavenProject> dependencyProjects = closure.getDependencyProjects(project);
System.out.println("=== " + project + " ===");
for (MavenProject mavenProject : projects) {
System.out.println(mavenProject);
}
MavenDependencyInjector.injectMavenProjectDependencies(project, dependencyProjects);
if (DUMP_DATA) {
try {
Expand Down
8 changes: 8 additions & 0 deletions tycho-p2/.settings/org.eclipse.jdt.core.prefs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
org.eclipse.jdt.core.compiler.compliance=17
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
org.eclipse.jdt.core.compiler.release=disabled
org.eclipse.jdt.core.compiler.source=17
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
org.eclipse.jdt.core.compiler.release=disabled
org.eclipse.jdt.core.compiler.source=1.8

0 comments on commit 7c24bc7

Please sign in to comment.