From 6ab013817228ad3d234aaa009120d1678cbb0336 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20L=C3=A4ubrich?= Date: Mon, 11 Dec 2023 20:27:09 +0100 Subject: [PATCH] Add support for the director mojo to include the project dependencies Currently one needs to supply all repositories externally but in some cases it is useful to allow specify some items as maven dependencies or even use the current project artifact to be installed. For this purpose there is a new parameter 'includeProjectRepository' that generates a repository from the project artifact, attached artifacts and dependency artifacts and automatically pass it to the director (cherry picked from commit 8db1d78c48f0333ec8259e87cf31cca8f8bcf07a) --- .../tycho/p2/resolver/BundlePublisher.java | 47 ++++++++++++ .../plugins/p2/director/DirectorMojo.java | 75 +++++++++++++++++-- 2 files changed, 117 insertions(+), 5 deletions(-) diff --git a/tycho-core/src/main/java/org/eclipse/tycho/p2/resolver/BundlePublisher.java b/tycho-core/src/main/java/org/eclipse/tycho/p2/resolver/BundlePublisher.java index 3b034242c2..5880bddbde 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/p2/resolver/BundlePublisher.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/p2/resolver/BundlePublisher.java @@ -19,15 +19,24 @@ import java.util.Map.Entry; import java.util.Optional; +import org.apache.commons.io.FileUtils; +import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.equinox.internal.p2.artifact.repository.simple.SimpleArtifactDescriptor; +import org.eclipse.equinox.internal.p2.artifact.repository.simple.SimpleArtifactRepositoryFactory; +import org.eclipse.equinox.internal.p2.metadata.repository.SimpleMetadataRepositoryFactory; +import org.eclipse.equinox.p2.core.ProvisionException; import org.eclipse.equinox.p2.metadata.IArtifactKey; import org.eclipse.equinox.p2.metadata.IInstallableUnit; +import org.eclipse.equinox.p2.publisher.IPublisherAction; import org.eclipse.equinox.p2.publisher.IPublisherAdvice; import org.eclipse.equinox.p2.publisher.IPublisherInfo; +import org.eclipse.equinox.p2.publisher.Publisher; import org.eclipse.equinox.p2.publisher.PublisherInfo; import org.eclipse.equinox.p2.publisher.actions.IPropertyAdvice; import org.eclipse.equinox.p2.publisher.eclipse.BundlesAction; import org.eclipse.equinox.p2.repository.artifact.IArtifactDescriptor; +import org.eclipse.equinox.p2.repository.artifact.IArtifactRepository; +import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository; import org.eclipse.osgi.service.resolver.BundleDescription; import org.eclipse.tycho.core.resolver.target.FileArtifactRepository; import org.osgi.framework.BundleException; @@ -81,4 +90,42 @@ public static IInstallableUnit publishBundle(BundleDescription bundleDescription return iu; } + /** + * Creates a new bundle repository at the given location, if the location already exits it is + * deleted before performing the operation. + * + * @param repositoryLocation + * the location where the repository should be stored + * @param name + * the name of the repository + * @param files + * the files to consider as bundles to be installed in the new repository + * @param monitor + * the monitor to use for the operation + * @throws ProvisionException + * if creation of the repository failed + */ + public static void createBundleRepository(File repositoryLocation, String name, File[] files, + IProgressMonitor monitor) throws ProvisionException { + if (repositoryLocation.exists()) { + FileUtils.deleteQuietly(repositoryLocation); + } + SimpleMetadataRepositoryFactory metadataRepositoryFactory = new SimpleMetadataRepositoryFactory(); + SimpleArtifactRepositoryFactory artifactRepositoryFactory = new SimpleArtifactRepositoryFactory(); + IArtifactRepository artifactRepository = artifactRepositoryFactory.create(repositoryLocation.toURI(), name, + null, Map.of()); + IMetadataRepository metadataRepository = metadataRepositoryFactory.create(repositoryLocation.toURI(), name, + null, Map.of()); + metadataRepository.executeBatch(m1 -> { + artifactRepository.executeBatch(m2 -> { + PublisherInfo publisherInfo = new PublisherInfo(); + publisherInfo.setArtifactOptions(IPublisherInfo.A_INDEX | IPublisherInfo.A_PUBLISH); + publisherInfo.setArtifactRepository(artifactRepository); + publisherInfo.setMetadataRepository(metadataRepository); + Publisher publisher = new Publisher(publisherInfo); + publisher.publish(new IPublisherAction[] { new BundlesAction(files) }, m2); + }, m1); + }, monitor); + } + } diff --git a/tycho-p2-director-plugin/src/main/java/org/eclipse/tycho/plugins/p2/director/DirectorMojo.java b/tycho-p2-director-plugin/src/main/java/org/eclipse/tycho/plugins/p2/director/DirectorMojo.java index 5b0657ffee..ccc5e9d9b2 100644 --- a/tycho-p2-director-plugin/src/main/java/org/eclipse/tycho/plugins/p2/director/DirectorMojo.java +++ b/tycho-p2-director-plugin/src/main/java/org/eclipse/tycho/plugins/p2/director/DirectorMojo.java @@ -16,23 +16,29 @@ import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.Objects; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.apache.maven.artifact.Artifact; +import org.apache.maven.execution.MavenSession; import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.LegacySupport; +import org.apache.maven.plugin.MojoExecution; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Component; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.project.MavenProject; import org.eclipse.equinox.app.IApplication; import org.eclipse.equinox.p2.core.IProvisioningAgent; import org.eclipse.equinox.p2.core.IProvisioningAgentProvider; -import org.eclipse.osgi.service.environment.EnvironmentInfo; -import org.eclipse.tycho.TargetEnvironment; +import org.eclipse.equinox.p2.core.ProvisionException; import org.eclipse.tycho.p2.CommandLineArguments; +import org.eclipse.tycho.p2.resolver.BundlePublisher; import org.eclipse.tycho.p2tools.TychoDirectorApplication; /** @@ -69,7 +75,7 @@ * * */ -@Mojo(name = "director", defaultPhase = LifecyclePhase.NONE, threadSafe = true, requiresProject = true) +@Mojo(name = "director", defaultPhase = LifecyclePhase.NONE, threadSafe = true, requiresProject = false) public class DirectorMojo extends AbstractMojo { @Component @@ -78,6 +84,12 @@ public class DirectorMojo extends AbstractMojo { @Component private IProvisioningAgentProvider agentProvider; + @Component + private LegacySupport legacySupport; + + @Component + private MojoExecution execution; + /** * The folder in which the targeted product is located. */ @@ -326,13 +338,20 @@ public class DirectorMojo extends AbstractMojo { @Parameter(property = "trustedCertificates") private String trustedCertificates; + /** + * If specified, the current project and its artifacts are included as part of the repository + * that is used to install units + */ + @Parameter() + private boolean includeProjectRepository; + @Override public void execute() throws MojoExecutionException, MojoFailureException { CommandLineArguments args = new CommandLineArguments(); args.addNonNull("-destination", destination); args.addNonNull("-metadatarepository", metadatarepositories); args.addNonNull("-artifactrepository", artifactrepositories); - args.addNonNull("-repository", repositories); + args.addNonNull("-repository", getRepositories()); args.addNotEmpty("-installIU", getUnitParameterList(installIUs, install), ","); args.addNotEmpty("-uninstallIU", getUnitParameterList(uninstallIUs, uninstall), ","); args.addNonNull("-revert", revert); @@ -375,6 +394,52 @@ public void execute() throws MojoExecutionException, MojoFailureException { } } + private String getRepositories() { + File projectRepository = getProjectRepository(); + if (projectRepository != null) { + if (repositories == null) { + return projectRepository.getAbsoluteFile().toURI().toASCIIString(); + } + List list = new ArrayList(); + for (String repo : repositories.split(",")) { + list.add(repo.trim()); + } + list.add(projectRepository.getAbsoluteFile().toURI().toASCIIString()); + return list.stream().collect(Collectors.joining(",")); + } + return repositories; + } + + private File getProjectRepository() { + if (includeProjectRepository) { + MavenSession session = legacySupport.getSession(); + if (session != null) { + MavenProject currentProject = session.getCurrentProject(); + if (currentProject != null) { + + File[] files = Stream + .concat(Stream.of(currentProject.getArtifact()), + Stream.concat(currentProject.getAttachedArtifacts().stream(), + currentProject.getArtifacts().stream())) + .filter(Objects::nonNull).distinct().map(Artifact::getFile).filter(Objects::nonNull) + .filter(File::isFile).toArray(File[]::new); + if (files.length > 0) { + try { + File projectRepository = new File(currentProject.getBuild().getDirectory(), + execution.getExecutionId() + "-repo"); + BundlePublisher.createBundleRepository(projectRepository, execution.getExecutionId(), files, + null); + return projectRepository; + } catch (ProvisionException e) { + getLog().warn("Can't create the project repository!", e); + } + } + } + } + } + return null; + } + private Map getPropertyMap(String csvPropertiesMap, Map properties) { LinkedHashMap map = new LinkedHashMap(); if (csvPropertiesMap != null) {