diff --git a/tycho-core/src/main/java/org/eclipse/tycho/core/maven/TychoProjectExecutionListener.java b/tycho-core/src/main/java/org/eclipse/tycho/core/maven/TychoProjectExecutionListener.java index 0edc592880..bc0b33fbd2 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/core/maven/TychoProjectExecutionListener.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/core/maven/TychoProjectExecutionListener.java @@ -39,12 +39,14 @@ import org.eclipse.tycho.ArtifactDescriptor; import org.eclipse.tycho.ArtifactKey; import org.eclipse.tycho.DependencyArtifacts; +import org.eclipse.tycho.DependencyResolutionException; import org.eclipse.tycho.ReactorProject; import org.eclipse.tycho.core.TargetPlatformConfiguration; import org.eclipse.tycho.core.TychoProject; import org.eclipse.tycho.core.TychoProjectManager; import org.eclipse.tycho.core.osgitools.DefaultArtifactDescriptor; import org.eclipse.tycho.core.osgitools.DefaultReactorProject; +import org.eclipse.tycho.p2.resolver.ResolverException; import org.eclipse.tycho.p2maven.DependencyChain; import org.eclipse.tycho.p2maven.InstallableUnitGenerator; import org.eclipse.tycho.resolver.TychoResolver; @@ -105,7 +107,22 @@ public void beforeProjectLifecycleExecution(ProjectExecutionEvent event) throws try { legacySupport.setSession(mavenSession); //FIXME should return tycho project! - resolver.resolveProject(mavenSession, mavenProject); + try { + resolver.resolveProject(mavenSession, mavenProject); + } catch (DependencyResolutionException e) { + ResolverException resolverException = findResolverException(e); + if (resolverException == null) { + throw new LifecycleExecutionException( + "Cannot resolve dependencies of project " + mavenProject.getId(), null, mavenProject, e); + } else { + throw new LifecycleExecutionException( + "Cannot resolve dependencies of project " + mavenProject.getId() + System.lineSeparator() + + " with context " + resolverException.getSelectionContext() + + System.lineSeparator() + resolverException.explanations() + .map(exp -> " " + exp.toString()).collect(Collectors.joining("\n")), + null, mavenProject); + } + } TychoProject tychoProject = projectManager.getTychoProject(mavenProject).orElse(null); if (tychoProject != null) { try { @@ -131,6 +148,21 @@ public void beforeProjectLifecycleExecution(ProjectExecutionEvent event) throws } } + private ResolverException findResolverException(Throwable t) { + if (t != null) { + if (t instanceof ResolverException re) { + return re; + } + for (Throwable sup : t.getSuppressed()) { + if (sup instanceof ResolverException re) { + return re; + } + } + return findResolverException(t.getCause()); + } + return null; + } + private Set checkBuildState(TychoProject tychoProject, MavenProject project) throws CoreException { ReactorProject reactorProject = DefaultReactorProject.adapt(project); DependencyArtifacts artifacts = tychoProject.getDependencyArtifacts(reactorProject); diff --git a/tycho-core/src/main/java/org/eclipse/tycho/p2/resolver/ResolverException.java b/tycho-core/src/main/java/org/eclipse/tycho/p2/resolver/ResolverException.java index 195d42d137..a15e76f24d 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/p2/resolver/ResolverException.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/p2/resolver/ResolverException.java @@ -13,7 +13,12 @@ *******************************************************************************/ package org.eclipse.tycho.p2.resolver; +import java.util.Collection; +import java.util.stream.Collectors; +import java.util.stream.Stream; + import org.eclipse.core.runtime.IStatus; +import org.eclipse.equinox.internal.p2.director.Explanation; import org.eclipse.tycho.core.shared.StatusTool; /** @@ -25,6 +30,7 @@ public class ResolverException extends Exception { private static final long serialVersionUID = 1L; private final String details; private final String selectionContext; + private Collection explanation; public ResolverException(String msg, Throwable cause) { super(msg, cause); @@ -32,6 +38,11 @@ public ResolverException(String msg, Throwable cause) { details = "N/A"; } + public ResolverException(Collection explanation, String selectionContext, Throwable cause) { + this(explanation.stream().map(Object::toString).collect(Collectors.joining("\n")), selectionContext, cause); + this.explanation = explanation; + } + public ResolverException(String details, String selectionContext, Throwable cause) { super("See log for details", cause); this.details = details; @@ -52,4 +63,8 @@ public String getSelectionContext() { return selectionContext; } + public Stream explanations() { + return explanation.stream(); + } + } diff --git a/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/ProjectorResolutionStrategy.java b/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/ProjectorResolutionStrategy.java index b0a512759b..6adf97db66 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/ProjectorResolutionStrategy.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/ProjectorResolutionStrategy.java @@ -91,8 +91,7 @@ public Collection resolve(Map properties, IPro // log all transitive requirements which cannot be satisfied; this doesn't print the dependency chain from the seed to the units with missing requirements, so this is less useful than the "explanation" logger.debug(StatusTool.toLogMessage(s)); explainProblems(explanation, MavenLogger::error); - throw new ResolverException(explanation.stream().map(Object::toString).collect(Collectors.joining("\n")), - selectionContext.toString(), StatusTool.findException(s)); + throw new ResolverException(explanation, selectionContext.toString(), StatusTool.findException(s)); } if (s.getSeverity() == IStatus.WARNING) { logger.warn(StatusTool.toLogMessage(s));