diff --git a/tycho-build/pom.xml b/tycho-build/pom.xml index 21c2970660..91d95af367 100644 --- a/tycho-build/pom.xml +++ b/tycho-build/pom.xml @@ -30,6 +30,84 @@ tycho-pomless ${project.version} + + org.eclipse.tycho + org.eclipse.tycho.core.shared + ${project.version} + + + org.eclipse.tycho + org.eclipse.tycho.p2.maven.repository + 2.7.0-SNAPSHOT + + + + org.eclipse.platform + org.eclipse.equinox.p2.core + 2.6.100 + + + + org.eclipse.platform + org.eclipse.osgi + 3.17.100 + + + + org.eclipse.platform + org.eclipse.equinox.p2.publisher + 1.6.200 + + + + org.eclipse.platform + org.eclipse.equinox.p2.director + 2.5.100 + + + + org.eclipse.platform + org.eclipse.equinox.p2.engine + 2.7.200 + + + + + org.eclipse.platform + org.eclipse.equinox.p2.metadata + 2.6.100 + + + org.eclipse.platform + org.eclipse.equinox.p2.repository + 2.5.300 + + + + org.eclipse.platform + org.eclipse.osgi.compatibility.state + 1.2.500 + + + + + org.eclipse.platform + org.eclipse.equinox.p2.publisher.eclipse + 1.4.1 + + + + + org.eclipse.sisu + org.eclipse.sisu.plexus + provided + org.apache.maven maven-model @@ -46,5 +124,24 @@ maven-core provided + + + org.eclipse.tycho + org.eclipse.tycho.p2.resolver.impl + ${project.version} + + + org.eclipse.tycho + org.eclipse.tycho.p2.maven.repository + ${project.version} + + + + org.eclipse.platform + org.eclipse.equinox.p2.metadata.repository + 1.4.0 + + + \ No newline at end of file diff --git a/tycho-build/src/main/java/org/eclipse/tycho/build/MavenLoggerAdapter.java b/tycho-build/src/main/java/org/eclipse/tycho/build/MavenLoggerAdapter.java new file mode 100644 index 0000000000..7ddcff0318 --- /dev/null +++ b/tycho-build/src/main/java/org/eclipse/tycho/build/MavenLoggerAdapter.java @@ -0,0 +1,83 @@ +/******************************************************************************* + * Copyright (c) 2011, 2022 SAP AG and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * SAP AG - initial API and implementation + * Christoph Läubrich - #225 MavenLogger is missing error method that accepts an exception + *******************************************************************************/ +package org.eclipse.tycho.build; + +import org.codehaus.plexus.logging.Logger; +import org.eclipse.tycho.core.shared.MavenLogger; + +public class MavenLoggerAdapter implements MavenLogger { + + private final Logger logger; + private final boolean extendedDebug; + + public MavenLoggerAdapter(Logger logger, boolean extendedDebug) { + this.logger = logger; + this.extendedDebug = extendedDebug; + } + + @Override + public void debug(String message) { + if (logger.isDebugEnabled()) { + logger.debug(message); + } else if (isExtendedDebugEnabled()) { + logger.info(message); + } + } + + @Override + public void debug(String message, Throwable cause) { + if (logger.isDebugEnabled()) { + logger.debug(message, cause); + } else if (isExtendedDebugEnabled()) { + logger.info(message, cause); + } + } + + @Override + public void info(String message) { + logger.info(message); + } + + @Override + public void warn(String message) { + warn(message, null); + } + + @Override + public void warn(String message, Throwable cause) { + logger.warn(message, cause); + } + + @Override + public void error(String message, Throwable cause) { + logger.error(message, cause); + } + + @Override + public void error(String message) { + logger.error(message); + } + + @Override + public boolean isDebugEnabled() { + return logger.isDebugEnabled() || isExtendedDebugEnabled(); + } + + @Override + public boolean isExtendedDebugEnabled() { + return extendedDebug; + } + + private boolean isEmpty(String message) { + return message == null || message.isEmpty(); + } +} diff --git a/tycho-build/src/main/java/org/eclipse/tycho/build/PlexusBundleContext.java b/tycho-build/src/main/java/org/eclipse/tycho/build/PlexusBundleContext.java new file mode 100644 index 0000000000..ceb3596c34 --- /dev/null +++ b/tycho-build/src/main/java/org/eclipse/tycho/build/PlexusBundleContext.java @@ -0,0 +1,181 @@ +/******************************************************************************* + * Copyright (c) 2022 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.build; + +import java.io.File; +import java.io.InputStream; +import java.util.Collection; +import java.util.Dictionary; + +import org.codehaus.plexus.component.annotations.Component; +import org.eclipse.osgi.internal.framework.FilterImpl; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.BundleException; +import org.osgi.framework.BundleListener; +import org.osgi.framework.Filter; +import org.osgi.framework.FrameworkListener; +import org.osgi.framework.InvalidSyntaxException; +import org.osgi.framework.ServiceFactory; +import org.osgi.framework.ServiceListener; +import org.osgi.framework.ServiceObjects; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.ServiceRegistration; + +//FIXME this should not be necessary at all see https://bugs.eclipse.org/bugs/show_bug.cgi?id=578387 +@Component(role = BundleContext.class, hint = "plexus") +public class PlexusBundleContext implements BundleContext { + + @Override + public String getProperty(String key) { + return System.getProperty(key); + } + + @Override + public Bundle getBundle() { + throw new IllegalStateException("this is not OSGi!"); + } + + @Override + public Bundle installBundle(String location, InputStream input) throws BundleException { + throw new BundleException("this context does not support installations"); + } + + @Override + public Bundle installBundle(String location) throws BundleException { + throw new BundleException("this context does not support installations"); + } + + @Override + public Bundle getBundle(long id) { + return getBundle(); + } + + @Override + public Bundle[] getBundles() { + return new Bundle[0]; + } + + @Override + public void addServiceListener(ServiceListener listener, String filter) throws InvalidSyntaxException { + + } + + @Override + public void addServiceListener(ServiceListener listener) { + + } + + @Override + public void removeServiceListener(ServiceListener listener) { + + } + + @Override + public void addBundleListener(BundleListener listener) { + + } + + @Override + public void removeBundleListener(BundleListener listener) { + + } + + @Override + public void addFrameworkListener(FrameworkListener listener) { + + } + + @Override + public void removeFrameworkListener(FrameworkListener listener) { + + } + + @Override + public ServiceRegistration registerService(String[] clazzes, Object service, Dictionary properties) { + throw new IllegalStateException("this is not OSGi!"); + } + + @Override + public ServiceRegistration registerService(String clazz, Object service, Dictionary properties) { + throw new IllegalStateException("this is not OSGi!"); + } + + @Override + public ServiceRegistration registerService(Class clazz, S service, Dictionary properties) { + throw new IllegalStateException("this is not OSGi!"); + } + + @Override + public ServiceRegistration registerService(Class clazz, ServiceFactory factory, + Dictionary properties) { + throw new IllegalStateException("this is not OSGi!"); + } + + @Override + public ServiceReference[] getServiceReferences(String clazz, String filter) throws InvalidSyntaxException { + throw new IllegalStateException("this is not OSGi!"); + } + + @Override + public ServiceReference[] getAllServiceReferences(String clazz, String filter) throws InvalidSyntaxException { + throw new IllegalStateException("this is not OSGi!"); + } + + @Override + public ServiceReference getServiceReference(String clazz) { + throw new IllegalStateException("this is not OSGi!"); + } + + @Override + public ServiceReference getServiceReference(Class clazz) { + throw new IllegalStateException("this is not OSGi!"); + } + + @Override + public Collection> getServiceReferences(Class clazz, String filter) + throws InvalidSyntaxException { + throw new IllegalStateException("this is not OSGi!"); + } + + @Override + public S getService(ServiceReference reference) { + throw new IllegalStateException("this is not OSGi!"); + } + + @Override + public boolean ungetService(ServiceReference reference) { + return true; + } + + @Override + public ServiceObjects getServiceObjects(ServiceReference reference) { + throw new IllegalStateException("this is not OSGi!"); + } + + @Override + public File getDataFile(String filename) { + return null; + } + + @Override + public Filter createFilter(String filter) throws InvalidSyntaxException { + return FilterImpl.newInstance(filter); + } + + @Override + public Bundle getBundle(String location) { + return getBundle(); + } + +} diff --git a/tycho-build/src/main/java/org/eclipse/tycho/build/TychoGraphBuilder.java b/tycho-build/src/main/java/org/eclipse/tycho/build/TychoGraphBuilder.java new file mode 100644 index 0000000000..02c41a54ea --- /dev/null +++ b/tycho-build/src/main/java/org/eclipse/tycho/build/TychoGraphBuilder.java @@ -0,0 +1,366 @@ +/******************************************************************************* + * Copyright (c) 2021 Christoph Läubrich and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Christoph Läubrich - initial API and implementation based on + * org.eclipse.tycho.p2.util.resolution.AbstractSlicerResolutionStrategy + * org.eclipse.tycho.p2.util.resolution.ProjectorResolutionStrategy + *******************************************************************************/ +package org.eclipse.tycho.build; + +import java.io.File; +import java.io.IOException; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Objects; +import java.util.Optional; +import java.util.Queue; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.Future; +import java.util.function.BooleanSupplier; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.apache.maven.execution.MavenExecutionRequest; +import org.apache.maven.execution.MavenSession; +import org.apache.maven.execution.ProjectDependencyGraph; +import org.apache.maven.graph.DefaultGraphBuilder; +import org.apache.maven.graph.DefaultProjectDependencyGraph; +import org.apache.maven.graph.GraphBuilder; +import org.apache.maven.model.building.DefaultModelProblem; +import org.apache.maven.model.building.ModelProblem; +import org.apache.maven.model.building.ModelProblem.Severity; +import org.apache.maven.model.building.Result; +import org.apache.maven.project.DuplicateProjectException; +import org.apache.maven.project.MavenProject; +import org.codehaus.plexus.component.annotations.Component; +import org.codehaus.plexus.component.annotations.Requirement; +import org.codehaus.plexus.logging.Logger; +import org.codehaus.plexus.util.dag.CycleDetectedException; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.equinox.internal.p2.director.DirectorActivator; +import org.eclipse.equinox.internal.p2.publisher.eclipse.FeatureParser; +import org.eclipse.equinox.p2.metadata.IArtifactKey; +import org.eclipse.equinox.p2.metadata.IInstallableUnit; +import org.eclipse.equinox.p2.publisher.IPublisherInfo; +import org.eclipse.equinox.p2.publisher.PublisherInfo; +import org.eclipse.equinox.p2.publisher.PublisherResult; +import org.eclipse.equinox.p2.publisher.eclipse.BundlesAction; +import org.eclipse.equinox.p2.publisher.eclipse.Feature; +import org.eclipse.equinox.p2.publisher.eclipse.FeaturesAction; +import org.eclipse.equinox.p2.query.QueryUtil; +import org.eclipse.osgi.service.resolver.BundleDescription; +import org.eclipse.tycho.core.shared.MavenLogger; +import org.eclipse.tycho.p2.target.ee.NoExecutionEnvironmentResolutionHints; +import org.eclipse.tycho.p2.util.resolution.ProjectorResolutionStrategy; +import org.eclipse.tycho.p2.util.resolution.ResolutionDataImpl; +import org.eclipse.tycho.p2.util.resolution.ResolverException; +import org.osgi.framework.BundleContext; +import org.osgi.framework.BundleException; + +@Component(role = GraphBuilder.class, hint = GraphBuilder.HINT) +public class TychoGraphBuilder extends DefaultGraphBuilder { + + public static final String TYPE_ECLIPSE_PLUGIN = "eclipse-plugin"; + public static final String TYPE_ECLIPSE_TEST_PLUGIN = "eclipse-test-plugin"; + public static final String TYPE_ECLIPSE_FEATURE = "eclipse-feature"; + public static final String TYPE_ECLIPSE_REPOSITORY = "eclipse-repository"; + public static final String TYPE_ECLIPSE_TARGET_DEFINITION = "eclipse-target-definition"; + + @Requirement + private Logger log; + + @Requirement(hint = "plexus") + private BundleContext bundleContext; + + @Override + public Result build(MavenSession session) { + MavenExecutionRequest request = session.getRequest(); + ProjectDependencyGraph dependencyGraph = session.getProjectDependencyGraph(); + Result graphResult = super.build(session); + if (dependencyGraph != null || graphResult.hasErrors()) { + // on second pass nothing to do for tycho, or already error ... + return graphResult; + } + session.getUserProperties().put("tycho.mode", "extension"); + MavenLogger loggerAdapter = new MavenLoggerAdapter(log, + Boolean.valueOf(session.getUserProperties().getProperty("tycho.debug.resolver"))); + String makeBehavior = request.getMakeBehavior(); + if (loggerAdapter.isExtendedDebugEnabled()) { + loggerAdapter.debug("TychoGraphBuilder:"); + loggerAdapter.debug(" - SelectedProjects: " + request.getSelectedProjects()); + loggerAdapter.debug(" - ExcludedProjects: " + request.getExcludedProjects()); + loggerAdapter.debug(" - MakeBehavior: " + makeBehavior); + } + boolean makeUpstream = MavenExecutionRequest.REACTOR_MAKE_UPSTREAM.equals(makeBehavior) + || MavenExecutionRequest.REACTOR_MAKE_BOTH.equals(makeBehavior); + boolean makeDownstream = MavenExecutionRequest.REACTOR_MAKE_DOWNSTREAM.equals(makeBehavior) + || MavenExecutionRequest.REACTOR_MAKE_BOTH.equals(makeBehavior); + if (!makeDownstream && !makeUpstream) { + // just like default... + return graphResult; + } + if (DirectorActivator.context == null) { + DirectorActivator.context = bundleContext; + } + ProjectDependencyGraph graph = graphResult.get(); + List projects = graph.getAllProjects(); + List problems = new CopyOnWriteArrayList<>(); + int degreeOfConcurrency = request.getDegreeOfConcurrency(); + boolean failFast = MavenExecutionRequest.REACTOR_FAIL_FAST.equals(request.getReactorFailureBehavior()); + Optional executor; + if (degreeOfConcurrency > 1) { + executor = Optional.of(new ForkJoinPool(degreeOfConcurrency)); + } else { + executor = Optional.empty(); + } + BooleanSupplier hasFailures = () -> failFast && !problems.isEmpty(); + Set selectedProjects = ConcurrentHashMap.newKeySet(); + try { + Map> projectIUMap = new ConcurrentHashMap<>(); + try { + var projectUnits = computeProjectUnits(problems); + runStream(projects.stream(), p -> projectIUMap.put(p, projectUnits.apply(p)), hasFailures, executor); + } catch (ExecutionException e) { + log.error("Can't read projects", e); + return Result.error(graph); + } + Map> projectDependenciesMap = new ConcurrentHashMap>(); + try { + Collection availableIUs = projectIUMap.values().stream().flatMap(Collection::stream) + .collect(Collectors.toSet()); + var projectDependencies = computeProjectDependencies(availableIUs, problems, loggerAdapter); + runStream(projectIUMap.entrySet().stream(), + entry -> projectDependenciesMap.put(entry.getKey(), projectDependencies.apply(entry)), + hasFailures, executor); + } catch (ExecutionException e) { + log.error("Can't resolve projects", e); + return Result.error(graph); + } + if (hasFailures.getAsBoolean()) { + if (loggerAdapter.isExtendedDebugEnabled()) { + for (ModelProblem modelProblem : problems) { + loggerAdapter.error(modelProblem.getMessage(), modelProblem.getException()); + } + } + return Result.error(graph, problems); + } + Map iuProjectMap = new HashMap(); + for (var entry : projectIUMap.entrySet()) { + MavenProject mavenProject = entry.getKey(); + for (IInstallableUnit iu : entry.getValue()) { + iuProjectMap.put(iu, mavenProject); + } + } + if (loggerAdapter.isExtendedDebugEnabled()) { + for (Entry> entry : projectDependenciesMap.entrySet()) { + MavenProject project = entry.getKey(); + Collection depends = entry.getValue(); + if (depends.isEmpty()) { + continue; + } + loggerAdapter.debug("[[ project " + project.getName() + " depends on: ]]"); + for (IInstallableUnit dependency : depends) { + MavenProject mavenProject = iuProjectMap.get(dependency); + if (mavenProject == null) { + loggerAdapter.debug(" IU: " + dependency); + } else { + loggerAdapter.debug(" IU: " + dependency + " [of project " + mavenProject.getName() + "]"); + } + } + } + } + Queue queue = new ConcurrentLinkedQueue<>(graph.getSortedProjects().stream() + .map(p -> new ProjectRequest(p, makeDownstream, makeUpstream, null)).collect(Collectors.toList())); + loggerAdapter.debug("Computing additional " + makeBehavior + + " dependencies based on initial project set of " + queue.stream().map(r -> r.mavenProject) + .map(MavenProject::getName).collect(Collectors.joining(", "))); + while (!queue.isEmpty()) { + ProjectRequest projectRequest = queue.poll(); + if (selectedProjects.add(projectRequest.mavenProject)) { + if (projectRequest.requestDownstream) { + Collection depends = projectDependenciesMap + .getOrDefault(projectRequest.mavenProject, Collections.emptyList()); + depends.stream()// + .map(iuProjectMap::get)// + .filter(Objects::nonNull)// + .distinct()// + .peek(project -> loggerAdapter.debug(" + add downstream project '" + project.getName() + + "' of project '" + projectRequest.mavenProject.getName() + "'..."))// + .forEach( + project -> queue.add(new ProjectRequest(project, true, false, projectRequest))); + } + if (projectRequest.requestUpstream) { + projectDependenciesMap.entrySet().stream()// + .filter(entry -> { + return entry.getValue().stream()// + .map(iuProjectMap::get)// + .filter(Objects::nonNull)// + .anyMatch(projectRequest::matches); + })// + .map(Entry::getKey)// + .distinct()// + .peek(project -> loggerAdapter.debug(" + add upstream project '" + project.getName() + + "' of project '" + projectRequest.mavenProject.getName() + "'..."))// + .forEach( + project -> queue.add(new ProjectRequest(project, true, false, projectRequest))); + } + } + } + // add target projects always, they don't really add to the build times but are + // needed if referenced inside projects we might be more selective and choose + // target projects depending on project configuration + for (MavenProject mavenProject : projects) { + if (TYPE_ECLIPSE_TARGET_DEFINITION.equals(mavenProject.getPackaging())) { + selectedProjects.add(mavenProject); + } + + } + } finally { + executor.ifPresent(ExecutorService::shutdownNow); + } + + try { + return Result.success(new DefaultProjectDependencyGraph(projects, selectedProjects)); + } catch (DuplicateProjectException | CycleDetectedException e) { + log.error("Can't compute project dependency graph", e); + return Result.error(graph); + } + } + + private Function> computeProjectUnits(List problems) { + return project -> { + PublisherInfo publisherInfo = new PublisherInfo(); + publisherInfo.setArtifactOptions(IPublisherInfo.A_INDEX); + if (TYPE_ECLIPSE_PLUGIN.equals(project.getPackaging()) + || TYPE_ECLIPSE_TEST_PLUGIN.equals(project.getPackaging())) { + try { + BundleDescription bundleDescription = BundlesAction.createBundleDescription(project.getBasedir()); + IArtifactKey descriptor = BundlesAction.createBundleArtifactKey(bundleDescription.getSymbolicName(), + bundleDescription.getVersion().toString()); + IInstallableUnit iu = BundlesAction.createBundleIU(bundleDescription, descriptor, publisherInfo); + return Collections.singletonList(iu); + } catch (IOException | BundleException e) { + problems.add(new DefaultModelProblem( + "can't read " + project.getPackaging() + " project @ " + project.getBasedir(), + Severity.ERROR, null, null, 0, 0, e)); + } + } else if (TYPE_ECLIPSE_FEATURE.equals(project.getPackaging())) { + FeatureParser parser = new FeatureParser(); + File basedir = project.getBasedir(); + Feature feature = parser.parse(basedir); + Map featureMap = new HashMap<>(); + FeaturesAction action = new FeaturesAction(new Feature[] { feature }) { + @Override + protected void publishFeatureArtifacts(Feature feature, IInstallableUnit featureIU, + IPublisherInfo publisherInfo) { + // so not call super as we don't wan't to copy anything --> Bug in P2 with + // IPublisherInfo.A_INDEX option + // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=578380 + } + + @Override + protected IInstallableUnit generateFeatureJarIU(Feature feature, IPublisherInfo publisherInfo) { + IInstallableUnit iu = super.generateFeatureJarIU(feature, publisherInfo); + featureMap.put(iu, feature); + return iu; + } + }; + PublisherResult results = new PublisherResult(); + action.perform(publisherInfo, results, null); + Set result = results.query(QueryUtil.ALL_UNITS, null).toSet(); + return result; + + } + return Collections.emptyList(); + }; + } + + private Function>, Collection> computeProjectDependencies( + Collection availableIUs, List problems, MavenLogger logger) { + return entry -> { + Collection projectUnits = entry.getValue(); + if (!projectUnits.isEmpty()) { + MavenProject project = entry.getKey(); + logger.debug("Resolve dependencies for project " + project.getName() + "..."); + try { + ProjectorResolutionStrategy resolutionStrategy = new ProjectorResolutionStrategy(logger); + ResolutionDataImpl data = new ResolutionDataImpl(NoExecutionEnvironmentResolutionHints.INSTANCE); + data.setFailOnMissing(false); + data.setAvailableIUs(Collections.unmodifiableCollection(availableIUs)); + data.setRootIUs(Collections.unmodifiableCollection(projectUnits)); + data.setSlicerPredicate(always -> true); + resolutionStrategy.setData(data); + Collection resolve = resolutionStrategy.resolve(new HashMap(), + new NullProgressMonitor()); + resolve.removeAll(projectUnits); + return resolve; + } catch (ResolverException e) { + problems.add(new DefaultModelProblem( + "can't resolve " + project.getPackaging() + " project @ " + project.getBasedir(), + Severity.ERROR, null, null, 0, 0, e)); + } + } + return Collections.emptyList(); + }; + } + + private static void runStream(Stream stream, Consumer consumer, BooleanSupplier hasFailures, + Optional service) throws ExecutionException { + if (hasFailures.getAsBoolean()) { + // short-cut + return; + } + Predicate takeWhile = nil -> !hasFailures.getAsBoolean(); + if (service.isEmpty()) { + stream.unordered().takeWhile(takeWhile).forEach(consumer); + } else { + Future future = service.get().submit(() -> { + stream.unordered().parallel().takeWhile(takeWhile).forEach(consumer); + }); + try { + future.get(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + } + + private static final class ProjectRequest { + + final MavenProject mavenProject; + final ProjectRequest parent; + final boolean requestDownstream; + final boolean requestUpstream; + + ProjectRequest(MavenProject mavenProject, boolean requestDownstream, boolean requestUpstream, + ProjectRequest parent) { + this.requestDownstream = requestDownstream; + this.requestUpstream = requestUpstream; + this.parent = parent; + this.mavenProject = mavenProject; + } + + boolean matches(MavenProject mavenproject) { + return this.mavenProject == mavenproject; + } + } + +} diff --git a/tycho-bundles/org.eclipse.tycho.p2.resolver.impl/src/main/java/org/eclipse/tycho/p2/util/resolution/ProjectorResolutionStrategy.java b/tycho-bundles/org.eclipse.tycho.p2.resolver.impl/src/main/java/org/eclipse/tycho/p2/util/resolution/ProjectorResolutionStrategy.java index a57d521dcc..43778c048c 100644 --- a/tycho-bundles/org.eclipse.tycho.p2.resolver.impl/src/main/java/org/eclipse/tycho/p2/util/resolution/ProjectorResolutionStrategy.java +++ b/tycho-bundles/org.eclipse.tycho.p2.resolver.impl/src/main/java/org/eclipse/tycho/p2/util/resolution/ProjectorResolutionStrategy.java @@ -46,7 +46,7 @@ public class ProjectorResolutionStrategy extends AbstractSlicerResolutionStrateg * incomplete solution */ private static final int MAX_ITERATIONS = Integer - .getInteger("tycho.internal.ProjectorResolutionStrategy.maxIterations", 100); + .getInteger("tycho.internal.ProjectorResolutionStrategy.maxIterations", 1000); public ProjectorResolutionStrategy(MavenLogger logger) { super(logger);