Skip to content

Commit

Permalink
Improve message if artifact can not be downloaded from any repository
Browse files Browse the repository at this point in the history
There are rare cases where one gets a message that an artifact can not
be downloaded from any repository, this has two pitfalls:

1) You don't get an idea what repositories are actually contacted
2) Its hard to find out who actually requires this artifact

This now enhances an IArtifactRequest by a method to set a "context iu"
why this artifact is requested. If the information is given, it searches
through the available IUs and gives additional information why it is
required and what repositories are queried.
  • Loading branch information
laeubi committed Apr 24, 2024
1 parent e82bbdf commit 8bcba76
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 12 deletions.
2 changes: 1 addition & 1 deletion bundles/org.eclipse.equinox.p2.engine/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.equinox.p2.engine;singleton:=true
Bundle-Version: 2.10.100.qualifier
Bundle-Version: 2.10.200.qualifier
Bundle-Activator: org.eclipse.equinox.internal.p2.engine.EngineActivator
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,20 @@
*******************************************************************************/
package org.eclipse.equinox.internal.p2.engine;

import java.net.URI;
import java.util.*;
import java.util.stream.Collectors;
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.internal.p2.engine.phases.Collect;
import org.eclipse.equinox.internal.provisional.p2.core.eventbus.IProvisioningEventBus;
import org.eclipse.equinox.p2.core.IProvisioningAgent;
import org.eclipse.equinox.p2.engine.ProvisioningContext;
import org.eclipse.equinox.p2.metadata.*;
import org.eclipse.equinox.p2.metadata.expression.ExpressionUtil;
import org.eclipse.equinox.p2.query.*;
import org.eclipse.equinox.p2.repository.artifact.IArtifactRepository;
import org.eclipse.equinox.p2.repository.artifact.IArtifactRequest;
import org.eclipse.osgi.util.NLS;

public class DownloadManager {
private ProvisioningContext provContext = null;
Expand All @@ -49,9 +53,15 @@ public int compare(IArtifactRepository arg0, IArtifactRepository arg1) {
return 0;
}
};
private Set<IInstallableUnit> ius;

public DownloadManager(ProvisioningContext context, IProvisioningAgent agent) {
this(context, Set.of(), agent);
}

public DownloadManager(ProvisioningContext context, Set<IInstallableUnit> ius, IProvisioningAgent agent) {
provContext = context;
this.ius = ius;
this.agent = agent;
}

Expand Down Expand Up @@ -96,7 +106,7 @@ public IStatus start(IProgressMonitor monitor) {
if (repositories.length == 0)
return new Status(IStatus.ERROR, EngineActivator.ID, Messages.download_no_repository, new Exception(Collect.NO_ARTIFACT_REPOSITORIES_AVAILABLE));
fetch(repositories, subMonitor.newChild(500));
return overallStatus(monitor);
return overallStatus(monitor, repositories);
} finally {
subMonitor.done();
}
Expand Down Expand Up @@ -148,12 +158,7 @@ private IArtifactRequest[] getRequestsForRepository(IArtifactRepository reposito
return applicable.toArray(new IArtifactRequest[applicable.size()]);
}

// private void notifyFetched() {
// ProvisioningEventBus bus = (ProvisioningEventBus) ServiceHelper.getService(DownloadActivator.context, ProvisioningEventBus.class);
// bus.publishEvent();
// }

private IStatus overallStatus(IProgressMonitor monitor) {
private IStatus overallStatus(IProgressMonitor monitor, IArtifactRepository[] repositories) {
if (monitor != null && monitor.isCanceled())
return Status.CANCEL_STATUS;

Expand All @@ -163,9 +168,51 @@ private IStatus overallStatus(IProgressMonitor monitor) {
MultiStatus result = new MultiStatus(EngineActivator.ID, IStatus.OK, null, null);
for (IArtifactRequest request : requestsToProcess) {
IStatus failed = request.getResult();
if (failed != null && !failed.isOK())
if (failed != null && !failed.isOK()) {
IArtifactKey key = request.getArtifactKey();
IInstallableUnit unit = getUnit(key);
if (unit != null) {
String dependencyPath = computeDependency(unit);
result.add(Status.error(NLS.bind(Messages.DownloadManager_cant_find_artifact,
new Object[] { request.getArtifactKey().toString(), dependencyPath,
Arrays.stream(repositories).map(repo -> repo.getLocation()).filter(Objects::nonNull)
.map(URI::toString).collect(Collectors.joining(System.lineSeparator(),
System.lineSeparator(), "")) }))); //$NON-NLS-1$
continue;
}
result.add(failed);
}
}
return result;
}

private IInstallableUnit getUnit(IArtifactKey artifactKey) {
if (ius != null) {
for (IInstallableUnit unit : ius) {
if (unit.getArtifacts().contains(artifactKey)) {
return unit;
}
}
}
return null;
}

private String computeDependency(IInstallableUnit unit) {
List<String> requiredBy = new ArrayList<>();
requiredBy.add(toIdAndVersion(unit));
if (ius != null) {
for (IInstallableUnit other : ius) {
List<IRequirement> requirement = other.getRequirements().stream().filter(req -> unit.satisfies(req))
.toList();
if (!requirement.isEmpty()) {
requiredBy.add(toIdAndVersion(other));
}
}
}
return requiredBy.stream().collect(Collectors.joining(", ")); //$NON-NLS-1$
}

private static String toIdAndVersion(IInstallableUnit unit) {
return String.format("%s[%s]", unit.getId(), unit.getVersion()); //$NON-NLS-1$
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ public class Messages extends NLS {
public static String committing;
public static String download_artifact;
public static String download_no_repository;

public static String DownloadManager_cant_find_artifact;
public static String Engine_Operation_Canceled_By_User;

public static String EngineActivator_0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ CertificateChecker_SignedContentError=Error with signed content.
CertificateChecker_SignedContentIOError=Error reading signed content.
CertificateChecker_UnsignedNotAllowed=Installing unsigned artifacts is not permitted: {0}
CertificateChecker_UnsignedRejected=Unsigned content is rejected. Installation cannot proceed.
DownloadManager_cant_find_artifact=Can't download artifact {0} required by {1} from any of the following repositories: {2}

Phase_Collect_Error=An error occurred while collecting items to be installed
Phase_Configure_Error=An error occurred while configuring the installed items
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,9 @@ protected IStatus completePhase(IProgressMonitor monitor, IProfile profile, Map<
agent = (IProvisioningAgent) parameters.get(PARM_AGENT);
}

@SuppressWarnings("unchecked")
Set<IInstallableUnit> ius = (Set<IInstallableUnit>) parameters.get(PARM_IUS);
if (Boolean.parseBoolean(context.getProperty(ProvisioningContext.CHECK_AUTHORITIES))) {
@SuppressWarnings("unchecked")
Set<IInstallableUnit> ius = (Set<IInstallableUnit>) parameters.get(PARM_IUS);
IStatus authorityStatus = new AuthorityChecker(agent, context, ius, artifactRequests.stream()
.flatMap(Arrays::stream).map(IArtifactRequest::getArtifactKey).collect(Collectors.toList()),
profile).start(monitor);
Expand All @@ -111,7 +111,7 @@ protected IStatus completePhase(IProgressMonitor monitor, IProfile profile, Map<
}

List<IArtifactRequest> totalArtifactRequests = new ArrayList<>(artifactRequests.size());
DownloadManager dm = new DownloadManager(context, agent);
DownloadManager dm = new DownloadManager(context, ius, agent);
for (IArtifactRequest[] requests : artifactRequests) {
for (IArtifactRequest request : requests) {
dm.add(request);
Expand Down

0 comments on commit 8bcba76

Please sign in to comment.