From e270a436c1aa228175afbaad7a192b829ddf8aed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20L=C3=A4ubrich?= Date: Thu, 7 Mar 2024 09:06:20 +0100 Subject: [PATCH] Do not fail target resolution if a referenced repository fails Currently a (failing) referenced repository can fail the whole target resolution process. This now only warns if a referenced repository can not be loaded. (cherry picked from commit 1cf4c9bd4a2bdb800b097c578a8c2e30c04ca4b3) --- .../p2/resolver/EmptyArtifactRepository.java | 87 +++++++++++++++++++ .../resolver/URITargetDefinitionContent.java | 84 +++++++++++------- .../p2resolver/TargetDefinitionResolver.java | 2 +- 3 files changed, 142 insertions(+), 31 deletions(-) create mode 100644 tycho-core/src/main/java/org/eclipse/tycho/p2/resolver/EmptyArtifactRepository.java diff --git a/tycho-core/src/main/java/org/eclipse/tycho/p2/resolver/EmptyArtifactRepository.java b/tycho-core/src/main/java/org/eclipse/tycho/p2/resolver/EmptyArtifactRepository.java new file mode 100644 index 0000000000..c96ac62a58 --- /dev/null +++ b/tycho-core/src/main/java/org/eclipse/tycho/p2/resolver/EmptyArtifactRepository.java @@ -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 descriptorQueryable() { + return new ListQueryable<>(); + } + + @Override + public IQueryResult query(IQuery 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(); + } + +} diff --git a/tycho-core/src/main/java/org/eclipse/tycho/p2/resolver/URITargetDefinitionContent.java b/tycho-core/src/main/java/org/eclipse/tycho/p2/resolver/URITargetDefinitionContent.java index 726f33425c..ce36f8fe1f 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/p2/resolver/URITargetDefinitionContent.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/p2/resolver/URITargetDefinitionContent.java @@ -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; @@ -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 @@ -74,9 +78,15 @@ private synchronized void preload(IProgressMonitor monitor) { if (metadataRepository == null) { Map metadataRepositoriesMap = new LinkedHashMap<>(); Map 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 metadataRepositories = metadataRepositoriesMap.values(); if (metadataRepositories.size() == 1) { metadataRepository = metadataRepositories.iterator().next(); @@ -94,7 +104,7 @@ private synchronized void preload(IProgressMonitor monitor) { private static void loadMetadataRepositories(URI uri, String id, Map metadataRepositories, Map artifactRepositories, boolean includeReferenced, IProvisioningAgent agent, - IProgressMonitor monitor) { + IProgressMonitor monitor, MavenLogger logger) throws ProvisionException { URI key = uri.normalize(); if (metadataRepositories.containsKey(key)) { //already loaded... @@ -105,46 +115,60 @@ private static void loadMetadataRepositories(URI uri, String id, Map 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 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 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 diff --git a/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/TargetDefinitionResolver.java b/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/TargetDefinitionResolver.java index 9347563cc5..49df237316 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/TargetDefinitionResolver.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/TargetDefinitionResolver.java @@ -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 locationUnits = QueryUtil.compoundQueryable(locations); Collection rootUnits = installableUnitResolver