From 332cef29fbcdd66df100458e6719547487b8c301 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20L=C3=A4ubrich?= Date: Tue, 19 Dec 2023 09:30:10 +0100 Subject: [PATCH] Add support for mirroring the projects target platform This adds support for converting the projects computed target platform into a deployable p2 repository. This can be used to create a mirror of a target-file, or to have a repository that can be used to install one specific bundle or feature with all its dependencies. --- .../facade/MirrorApplicationService.java | 18 ++++++ .../PreliminaryTargetPlatformImpl.java | 7 ++- .../p2resolver/TargetPlatformFactoryImpl.java | 2 +- .../p2tools/MirrorApplicationServiceImpl.java | 62 +++++++++++++++++++ 4 files changed, 86 insertions(+), 3 deletions(-) diff --git a/tycho-core/src/main/java/org/eclipse/tycho/p2/tools/mirroring/facade/MirrorApplicationService.java b/tycho-core/src/main/java/org/eclipse/tycho/p2/tools/mirroring/facade/MirrorApplicationService.java index 2362e74a4b..2cd396d248 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/p2/tools/mirroring/facade/MirrorApplicationService.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/p2/tools/mirroring/facade/MirrorApplicationService.java @@ -17,6 +17,8 @@ import java.util.Collection; import java.util.Map; +import org.eclipse.equinox.p2.repository.artifact.IArtifactRepository; +import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository; import org.eclipse.tycho.BuildDirectory; import org.eclipse.tycho.DependencySeed; import org.eclipse.tycho.p2.tools.BuildContext; @@ -107,6 +109,22 @@ void mirrorStandalone(RepositoryReferences sources, DestinationRepositoryDescrip Collection seedUnits, MirrorOptions mirrorOptions, BuildDirectory tempDirectory) throws FacadeException; + /** + * Mirrors the given sources to the destination, if the destination exits it will be delete + * beforehand. + * + * @param sourceArtifactRepository + * the source artifact repository + * @param sourceMetadataRepository + * the source metadata repository + * @param repositoryDestination + * the destination + * @param repositoryName + * the name of the new repository + */ + void mirrorDirect(IArtifactRepository sourceArtifactRepository, IMetadataRepository sourceMetadataRepository, + File repositoryDestination, String repositoryName) throws FacadeException; + /** * Modifies the artifact repository to add mapping rules to download Maven released artifacts * from one of the specified maven repositories (when it's found). diff --git a/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/PreliminaryTargetPlatformImpl.java b/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/PreliminaryTargetPlatformImpl.java index 089b5f6627..258121013d 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/PreliminaryTargetPlatformImpl.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/PreliminaryTargetPlatformImpl.java @@ -22,6 +22,7 @@ import java.util.Map; import java.util.Set; +import org.eclipse.equinox.p2.core.IProvisioningAgent; import org.eclipse.equinox.p2.metadata.IInstallableUnit; import org.eclipse.equinox.p2.query.QueryUtil; import org.eclipse.equinox.p2.repository.artifact.IArtifactRepository; @@ -61,7 +62,8 @@ public PreliminaryTargetPlatformImpl(Map externalIUs, ExecutionEnvironmentResolutionHints executionEnvironment, TargetPlatformFilterEvaluator filter, LocalMetadataRepository localMetadataRepository, IRawArtifactFileProvider externalArtifacts, LocalArtifactRepository localArtifactRepository, - boolean includeLocalRepo, MavenLogger logger, Set shadowed) { + boolean includeLocalRepo, MavenLogger logger, Set shadowed, + IProvisioningAgent remoteAgent) { super(collectAllInstallableUnits(reactorProjectIUs, externalIUs, executionEnvironment), executionEnvironment, externalArtifacts, localArtifactRepository, reactorProjectIUs, new HashMap<>(), shadowed); this.externalIUs = externalIUs; @@ -69,7 +71,8 @@ public PreliminaryTargetPlatformImpl(Map collectAllInstallableUnits( diff --git a/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/TargetPlatformFactoryImpl.java b/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/TargetPlatformFactoryImpl.java index 960c32992d..6f069e6b6a 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/TargetPlatformFactoryImpl.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/TargetPlatformFactoryImpl.java @@ -294,7 +294,7 @@ public P2TargetPlatform createTargetPlatform(TargetPlatformConfigurationStub tpC externalArtifactFileProvider, // localArtifactRepository, // includeLocalMavenRepo, // - logger, shadowed); + logger, shadowed, remoteAgent); eeResolutionHandler.readFullSpecification(targetPlatform.getInstallableUnits()); return targetPlatform; diff --git a/tycho-core/src/main/java/org/eclipse/tycho/p2tools/MirrorApplicationServiceImpl.java b/tycho-core/src/main/java/org/eclipse/tycho/p2tools/MirrorApplicationServiceImpl.java index 68ea32319b..79b9c726bd 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/p2tools/MirrorApplicationServiceImpl.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/p2tools/MirrorApplicationServiceImpl.java @@ -21,21 +21,33 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.TreeSet; +import org.apache.commons.io.FileUtils; import org.codehaus.plexus.component.annotations.Component; import org.codehaus.plexus.component.annotations.Requirement; import org.codehaus.plexus.logging.Logger; +import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.MultiStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.equinox.internal.p2.artifact.repository.simple.SimpleArtifactRepository; import org.eclipse.equinox.internal.p2.artifact.repository.simple.SimpleArtifactRepositoryFactory; +import org.eclipse.equinox.internal.p2.metadata.repository.SimpleMetadataRepositoryFactory; +import org.eclipse.equinox.internal.p2.repository.Transport; import org.eclipse.equinox.p2.core.IProvisioningAgent; import org.eclipse.equinox.p2.core.ProvisionException; import org.eclipse.equinox.p2.internal.repository.mirroring.IArtifactMirrorLog; +import org.eclipse.equinox.p2.internal.repository.mirroring.Mirroring; +import org.eclipse.equinox.p2.internal.repository.tools.Activator; +import org.eclipse.equinox.p2.internal.repository.tools.Messages; import org.eclipse.equinox.p2.internal.repository.tools.RecreateRepositoryApplication; import org.eclipse.equinox.p2.internal.repository.tools.RepositoryDescriptor; import org.eclipse.equinox.p2.internal.repository.tools.SlicingOptions; @@ -44,9 +56,11 @@ import org.eclipse.equinox.p2.metadata.IInstallableUnit; import org.eclipse.equinox.p2.metadata.Version; import org.eclipse.equinox.p2.query.IQuery; +import org.eclipse.equinox.p2.query.IQueryResult; import org.eclipse.equinox.p2.query.QueryUtil; import org.eclipse.equinox.p2.repository.IRepositoryManager; import org.eclipse.equinox.p2.repository.artifact.IArtifactDescriptor; +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.tycho.ArtifactType; @@ -436,4 +450,52 @@ public void addMavenMappingRules(File repository, URI[] mavenRepositories) throw true, false, false); xzCompress(desc); } + + @Override + public void mirrorDirect(IArtifactRepository sourceArtifactRepository, IMetadataRepository sourceMetadataRepository, + File repositoryDestination, String repositoryName) throws FacadeException { + if (repositoryDestination.exists()) { + FileUtils.deleteQuietly(repositoryDestination); + } + //See https://github.com/eclipse-equinox/p2/pull/418 + Objects.requireNonNull(sourceArtifactRepository.getProvisioningAgent(), + "Source repository needs to have an agent"); + SimpleMetadataRepositoryFactory metadataRepositoryFactory = new SimpleMetadataRepositoryFactory(); + metadataRepositoryFactory.setAgent(agent); + SimpleArtifactRepositoryFactory artifactRepositoryFactory = new SimpleArtifactRepositoryFactory(); + artifactRepositoryFactory.setAgent(agent); + IArtifactRepository destinationArtifactRepository = artifactRepositoryFactory + .create(repositoryDestination.toURI(), repositoryName, null, Map.of()); + IMetadataRepository destinationMetadataRepository = metadataRepositoryFactory + .create(repositoryDestination.toURI(), repositoryName, null, Map.of()); + MultiStatus multiStatus = new MultiStatus(Activator.ID, IStatus.OK, Messages.message_mirroringStatus, null); + Set toMirror = new TreeSet<>(Comparator.comparing(IArtifactKey::getId).thenComparing( + Comparator.comparing(IArtifactKey::getVersion).thenComparing(IArtifactKey::getClassifier))); + multiStatus.add(destinationMetadataRepository.executeBatch(monitor -> { + IQueryResult result = sourceMetadataRepository.query(QueryUtil.ALL_UNITS, monitor); + Set units = result.toUnmodifiableSet(); + destinationMetadataRepository.addInstallableUnits(units); + for (IInstallableUnit unit : units) { + toMirror.addAll(unit.getArtifacts()); + } + }, null)); + multiStatus.add(destinationArtifactRepository.executeBatch(monitor -> { + Mirroring mirroring = new Mirroring(sourceArtifactRepository, destinationArtifactRepository, true); + mirroring.setCompare(false); + mirroring.setValidate(false); + mirroring.setTransport(agent.getService(Transport.class)); + IArtifactKey[] keys = toMirror.toArray(IArtifactKey[]::new); + mirroring.setArtifactKeys(keys); + multiStatus.addAll(mirroring.run(false, false)); + }, null)); + if (!multiStatus.isOK()) { + String logMessage = StatusTool.toLogMessage(multiStatus); + if (multiStatus.getSeverity() == IStatus.INFO) { + logger.info(logMessage, StatusTool.findException(multiStatus)); + } else if (multiStatus.getSeverity() == IStatus.WARNING) { + logger.warn(logMessage, StatusTool.findException(multiStatus)); + } + throw new FacadeException(logMessage, new CoreException(multiStatus)); + } + } }