Skip to content

Commit

Permalink
Do not fail target resolution if a referenced repository fails
Browse files Browse the repository at this point in the history
Currently a (failing) referenced repository can fail the whole target
resolution process.

This now only warns if a referenced repository can not be loaded.
  • Loading branch information
laeubi committed Mar 7, 2024
1 parent e2b2ee5 commit abad795
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 31 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*******************************************************************************
* Copyright (c) 2024 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.p2.resolver;

import java.io.OutputStream;
import java.net.URI;
import java.util.List;
import java.util.Map;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.equinox.p2.core.IProvisioningAgent;
import org.eclipse.equinox.p2.core.ProvisionException;
import org.eclipse.equinox.p2.metadata.IArtifactKey;
import org.eclipse.equinox.p2.query.CollectionResult;
import org.eclipse.equinox.p2.query.IQuery;
import org.eclipse.equinox.p2.query.IQueryResult;
import org.eclipse.equinox.p2.query.IQueryable;
import org.eclipse.equinox.p2.repository.artifact.IArtifactDescriptor;
import org.eclipse.equinox.p2.repository.artifact.IArtifactRepositoryManager;
import org.eclipse.equinox.p2.repository.artifact.IArtifactRequest;
import org.eclipse.equinox.p2.repository.artifact.spi.AbstractArtifactRepository;
import org.eclipse.tycho.p2maven.ListQueryable;

public class EmptyArtifactRepository extends AbstractArtifactRepository {

protected EmptyArtifactRepository(IProvisioningAgent agent, URI location) {
super(agent, "Empty", IArtifactRepositoryManager.TYPE_SIMPLE_REPOSITORY, null, location, null, null, Map.of());
}

@Override
public IStatus getRawArtifact(IArtifactDescriptor descriptor, OutputStream destination, IProgressMonitor monitor) {
return Status.CANCEL_STATUS;
}

@Override
public IQueryable<IArtifactDescriptor> descriptorQueryable() {
return new ListQueryable<>();
}

@Override
public IQueryResult<IArtifactKey> query(IQuery<IArtifactKey> query, IProgressMonitor monitor) {
return new CollectionResult<>(List.of());
}

@Override
public boolean contains(IArtifactDescriptor descriptor) {
return false;
}

@Override
public boolean contains(IArtifactKey key) {
return false;
}

@Override
public IStatus getArtifact(IArtifactDescriptor descriptor, OutputStream destination, IProgressMonitor monitor) {
return Status.CANCEL_STATUS;
}

@Override
public IArtifactDescriptor[] getArtifactDescriptors(IArtifactKey key) {
return new IArtifactDescriptor[0];
}

@Override
public IStatus getArtifacts(IArtifactRequest[] requests, IProgressMonitor monitor) {
return Status.CANCEL_STATUS;
}

@Override
public OutputStream getOutputStream(IArtifactDescriptor descriptor) throws ProvisionException {
return OutputStream.nullOutputStream();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@
import org.eclipse.equinox.p2.repository.IRepository;
import org.eclipse.equinox.p2.repository.IRepositoryReference;
import org.eclipse.equinox.p2.repository.artifact.IArtifactRepository;
import org.eclipse.equinox.p2.repository.artifact.IArtifactRepositoryManager;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager;
import org.eclipse.tycho.IRepositoryIdManager;
import org.eclipse.tycho.core.resolver.shared.ReferencedRepositoryMode;
import org.eclipse.tycho.core.shared.MavenLogger;
import org.eclipse.tycho.p2.repository.LazyArtifactRepository;
import org.eclipse.tycho.p2.repository.ListCompositeMetadataRepository;
import org.eclipse.tycho.p2.repository.RepositoryArtifactProvider;
Expand All @@ -47,13 +49,15 @@ public class URITargetDefinitionContent implements TargetDefinitionContent {
private String id;
private IMetadataRepository metadataRepository;
private ReferencedRepositoryMode referencedRepositoryMode;
private MavenLogger logger;

public URITargetDefinitionContent(IProvisioningAgent agent, URI location, String id,
ReferencedRepositoryMode referencedRepositoryMode) {
ReferencedRepositoryMode referencedRepositoryMode, MavenLogger logger) {
this.agent = agent;
this.location = location;
this.id = id;
this.referencedRepositoryMode = referencedRepositoryMode;
this.logger = logger;
}

@Override
Expand All @@ -74,9 +78,15 @@ private synchronized void preload(IProgressMonitor monitor) {
if (metadataRepository == null) {
Map<URI, IMetadataRepository> metadataRepositoriesMap = new LinkedHashMap<>();
Map<URI, IArtifactRepository> artifactRepositoriesMap = new LinkedHashMap<>();
loadMetadataRepositories(location, id, metadataRepositoriesMap, artifactRepositoriesMap,
referencedRepositoryMode == ReferencedRepositoryMode.include, agent, monitor);
loadArtifactRepositories(location, artifactRepositoriesMap, agent);
URI uri = location;
try {
loadMetadataRepositories(uri, id, metadataRepositoriesMap, artifactRepositoriesMap,
referencedRepositoryMode == ReferencedRepositoryMode.include, agent, monitor, logger);
loadArtifactRepositories(uri, artifactRepositoriesMap, agent, false, logger);
} catch (ProvisionException e) {
throw new TargetDefinitionResolutionException(
"Failed to load p2 metadata repository from location " + uri, e);
}
Collection<IMetadataRepository> metadataRepositories = metadataRepositoriesMap.values();
if (metadataRepositories.size() == 1) {
metadataRepository = metadataRepositories.iterator().next();
Expand All @@ -94,7 +104,7 @@ private synchronized void preload(IProgressMonitor monitor) {

private static void loadMetadataRepositories(URI uri, String id, Map<URI, IMetadataRepository> metadataRepositories,
Map<URI, IArtifactRepository> artifactRepositories, boolean includeReferenced, IProvisioningAgent agent,
IProgressMonitor monitor) {
IProgressMonitor monitor, MavenLogger logger) throws ProvisionException {
URI key = uri.normalize();
if (metadataRepositories.containsKey(key)) {
//already loaded...
Expand All @@ -105,46 +115,60 @@ private static void loadMetadataRepositories(URI uri, String id, Map<URI, IMetad
if (metadataManager == null) {
throw new TargetDefinitionResolutionException("IMetadataRepositoryManager is null in IProvisioningAgent");
}
try {
IRepositoryIdManager repositoryIdManager = agent.getService(IRepositoryIdManager.class);
if (repositoryIdManager != null) {
repositoryIdManager.addMapping(id, uri);
}
IMetadataRepository repository = metadataManager.loadRepository(uri, subMonitor.split(50));
metadataRepositories.put(key, repository);
if (includeReferenced) {
Collection<IRepositoryReference> references = repository.getReferences();
subMonitor.setWorkRemaining(references.size());
for (IRepositoryReference reference : references) {
if ((reference.getOptions() | IRepository.ENABLED) != 0) {
if (reference.getType() == IRepository.TYPE_METADATA) {
loadMetadataRepositories(reference.getLocation(), reference.getNickname(),
metadataRepositories, artifactRepositories, includeReferenced, agent,
subMonitor.split(1));
} else if (reference.getType() == IRepository.TYPE_ARTIFACT) {
loadArtifactRepositories(reference.getLocation(), artifactRepositories, agent);
subMonitor.worked(1);
IRepositoryIdManager repositoryIdManager = agent.getService(IRepositoryIdManager.class);
if (repositoryIdManager != null) {
repositoryIdManager.addMapping(id, uri);
}
IMetadataRepository repository = metadataManager.loadRepository(uri, subMonitor.split(50));
metadataRepositories.put(key, repository);
if (includeReferenced) {
Collection<IRepositoryReference> references = repository.getReferences();
subMonitor.setWorkRemaining(references.size());
for (IRepositoryReference reference : references) {
if ((reference.getOptions() | IRepository.ENABLED) != 0) {
URI location = reference.getLocation();
if (reference.getType() == IRepository.TYPE_METADATA) {
try {
loadMetadataRepositories(location, reference.getNickname(), metadataRepositories,
artifactRepositories, includeReferenced, agent, subMonitor.split(1), logger);
} catch (ProvisionException e) {
logger.warn("Skip referenced repository: " + location + ": " + e);
}
} else if (reference.getType() == IRepository.TYPE_ARTIFACT) {
loadArtifactRepositories(location, artifactRepositories, agent, true, logger);
subMonitor.worked(1);
}
}
}
} catch (ProvisionException e) {
throw new TargetDefinitionResolutionException("Failed to load p2 metadata repository from location " + uri,
e);
}

}

private static void loadArtifactRepositories(URI uri, Map<URI, IArtifactRepository> artifactRepositories,
IProvisioningAgent agent) {
IProvisioningAgent agent, boolean referenced, MavenLogger logger) {
URI key = uri.normalize();
if (artifactRepositories.containsKey(key)) {
//already loaded...
return;
}
//artifact repositories are resolved lazy here as loading them might not be always necessary (e.g only dependency resolution required) and could be expensive (net I/O)
artifactRepositories.put(key,
new LazyArtifactRepository(agent, uri, RepositoryArtifactProvider::loadRepository));
LazyArtifactRepository repository;
if (referenced) {
repository = new LazyArtifactRepository(agent, uri, (u, a) -> {
IArtifactRepositoryManager repositoryManager = agent.getService(IArtifactRepositoryManager.class);
if (repositoryManager != null) {
try {
return repositoryManager.loadRepository(u, null);
} catch (ProvisionException e) {
logger.warn("Skip referenced repository: " + u + ": " + e);
}
}
return new EmptyArtifactRepository(a, u);
});
} else {
repository = new LazyArtifactRepository(agent, uri, RepositoryArtifactProvider::loadRepository);
}
artifactRepositories.put(key, repository);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ public TargetDefinitionContent resolveContentWithExceptions(TargetDefinition def
String key = location.normalize().toASCIIString();
locations.add(
uriRepositories.computeIfAbsent(key, s -> new URITargetDefinitionContent(provisioningAgent,
location, repository.getId(), referencedRepositoryMode)));
location, repository.getId(), referencedRepositoryMode, logger)));
}
IQueryable<IInstallableUnit> locationUnits = QueryUtil.compoundQueryable(locations);
Collection<IInstallableUnit> rootUnits = installableUnitResolver
Expand Down

0 comments on commit abad795

Please sign in to comment.