Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for mirroring the projects target platform #3306

Merged
merged 1 commit into from
Dec 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ This page describes the noteworthy improvements provided by each release of Ecli

### backports:

- new `mirror-target-platform` mojo
- new director mojo
- support for PDE Api Tools Annotations
- api tools fixes
Expand Down
2 changes: 2 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,8 @@
<configuration>
<source>${min.jdk.version}</source>
<target>${min.jdk.version}</target>
<!-- Workaround for https://issues.apache.org/jira/browse/MCOMPILER-567 -->
<useIncrementalCompilation>false</useIncrementalCompilation>
</configuration>
</plugin>
<plugin>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*******************************************************************************
* Copyright (c) 2023 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.target;

import java.io.File;
import java.util.List;

import org.apache.maven.plugin.AbstractMojo;
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.plugins.annotations.ResolutionScope;
import org.apache.maven.project.MavenProject;
import org.eclipse.equinox.p2.core.IProvisioningAgent;
import org.eclipse.equinox.p2.repository.artifact.IArtifactRepository;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository;
import org.eclipse.tycho.ReactorProject;
import org.eclipse.tycho.TargetPlatform;
import org.eclipse.tycho.TargetPlatformService;
import org.eclipse.tycho.core.osgitools.DefaultReactorProject;
import org.eclipse.tycho.p2.repository.ListCompositeMetadataRepository;
import org.eclipse.tycho.p2.repository.PublishingRepository;
import org.eclipse.tycho.p2.tools.FacadeException;
import org.eclipse.tycho.p2.tools.mirroring.facade.MirrorApplicationService;
import org.eclipse.tycho.p2maven.ListCompositeArtifactRepository;
import org.eclipse.tycho.repository.registry.facade.ReactorRepositoryManager;

/**
* Supports mirroring the computed target platform of the current project, this behaves similar to
* what PDE offers with its export deployable feature / plug-in and assembles an update site that
* contains everything this particular project depends on.
*/
@Mojo(name = "mirror-target-platform", threadSafe = true, requiresDependencyResolution = ResolutionScope.COMPILE, defaultPhase = LifecyclePhase.PREPARE_PACKAGE)
public class MirrorTargetPlatformMojo extends AbstractMojo {

@Parameter(property = "project", readonly = true)
private MavenProject project;

@Parameter(defaultValue = "${project.build.directory}/target-platform-repository")
private File destination;

@Parameter(defaultValue = "${project.id}")
private String name;

@Component
private TargetPlatformService platformService;

@Component
private MirrorApplicationService mirrorService;

@Component
private ReactorRepositoryManager repositoryManager;

@Component
private IProvisioningAgent agent;

@Override
public void execute() throws MojoExecutionException, MojoFailureException {
ReactorProject reactorProject = DefaultReactorProject.adapt(project);
TargetPlatform targetPlatform = platformService.getTargetPlatform(reactorProject).orElse(null);
if (targetPlatform == null) {
getLog().info("Project has no target platform, skip execution.");
return;
}
IArtifactRepository sourceArtifactRepository = targetPlatform.getArtifactRepository();
IMetadataRepository sourceMetadataRepository = targetPlatform.getMetadataRepository();
PublishingRepository publishingRepository = repositoryManager.getPublishingRepository(reactorProject);
getLog().info("Mirroring target platform, this can take a while ...");
try {
IArtifactRepository artifactRepository = new ListCompositeArtifactRepository(
List.of(sourceArtifactRepository, publishingRepository.getArtifactRepository()), agent);
IMetadataRepository metadataRepository = new ListCompositeMetadataRepository(
List.of(sourceMetadataRepository, publishingRepository.getMetadataRepository()), agent);
mirrorService.mirrorDirect(artifactRepository, metadataRepository, destination, name);
} catch (FacadeException e) {
throw new MojoFailureException(e.getMessage(), e.getCause());
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -107,6 +109,22 @@ void mirrorStandalone(RepositoryReferences sources, DestinationRepositoryDescrip
Collection<IUDescription> 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).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ public InstallableUnitResolver(List<TargetEnvironment> environments,
this.logger = logger;
}

public void addLocation(InstallableUnitLocation iuLocationDefinition, IQueryable<IInstallableUnit> localUnits) {
public Collection<IInstallableUnit> addLocation(InstallableUnitLocation iuLocationDefinition,
IQueryable<IInstallableUnit> localUnits) {
//update (and validate) desired global state
setIncludeMode(iuLocationDefinition.getIncludeMode());
setIncludeAllEnvironments(iuLocationDefinition.includeAllEnvironments());
Expand All @@ -85,7 +86,9 @@ public void addLocation(InstallableUnitLocation iuLocationDefinition, IQueryable
default -> iuLocationDefinition.includeSource();
});
//resolve root units and add them
rootUnits.add(new RootUnits(getRootIUs(iuLocationDefinition.getUnits(), localUnits), localUnits));
Collection<IInstallableUnit> rootIUs = getRootIUs(iuLocationDefinition.getUnits(), localUnits);
rootUnits.add(new RootUnits(rootIUs, localUnits));
return rootIUs;
}

private void setIncludeMode(IncludeMode newValue) throws TargetDefinitionResolutionException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -61,15 +62,17 @@ public PreliminaryTargetPlatformImpl(Map<IInstallableUnit, ReactorProjectIdentit
Collection<IInstallableUnit> externalIUs, ExecutionEnvironmentResolutionHints executionEnvironment,
TargetPlatformFilterEvaluator filter, LocalMetadataRepository localMetadataRepository,
IRawArtifactFileProvider externalArtifacts, LocalArtifactRepository localArtifactRepository,
boolean includeLocalRepo, MavenLogger logger, Set<IInstallableUnit> shadowed) {
boolean includeLocalRepo, MavenLogger logger, Set<IInstallableUnit> shadowed,
IProvisioningAgent remoteAgent) {
super(collectAllInstallableUnits(reactorProjectIUs, externalIUs, executionEnvironment), executionEnvironment,
externalArtifacts, localArtifactRepository, reactorProjectIUs, new HashMap<>(), shadowed);
this.externalIUs = externalIUs;
this.filter = filter;
this.localMetadataRepository = localMetadataRepository;
this.includeLocalRepo = includeLocalRepo;
this.logger = logger;
this.artifactRepository = new ProviderOnlyArtifactRepository(artifacts, null, URI.create("preliminary:/"));
this.artifactRepository = new ProviderOnlyArtifactRepository(artifacts, remoteAgent,
URI.create("preliminary:/"));
}

public static LinkedHashSet<IInstallableUnit> collectAllInstallableUnits(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,21 @@
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.equinox.internal.p2.updatesite.SiteCategory;
import org.eclipse.equinox.internal.p2.updatesite.SiteXMLAction;
import org.eclipse.equinox.p2.core.IProvisioningAgent;
import org.eclipse.equinox.p2.metadata.IArtifactKey;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.query.CollectionResult;
import org.eclipse.equinox.p2.query.Collector;
import org.eclipse.equinox.p2.query.IQuery;
import org.eclipse.equinox.p2.query.IQueryResult;
Expand Down Expand Up @@ -77,6 +84,8 @@
*/
public final class TargetDefinitionResolver {

private static final SiteXMLAction CATEGORY_FACTORY = new SiteXMLAction((URI) null, (String) null);

private final MavenLogger logger;

private final List<TargetEnvironment> environments;
Expand Down Expand Up @@ -148,7 +157,11 @@ public TargetDefinitionContent resolveContentWithExceptions(TargetDefinition def
location, repository.getId(), referencedRepositoryMode)));
}
IQueryable<IInstallableUnit> locationUnits = QueryUtil.compoundQueryable(locations);
installableUnitResolver.addLocation((InstallableUnitLocation) locationDefinition, locationUnits);
Collection<IInstallableUnit> rootUnits = installableUnitResolver
.addLocation((InstallableUnitLocation) locationDefinition, locationUnits);
unitResultSet.accept(
createCategory(installableUnitLocation.getRepositories().stream().map(r -> r.getLocation())
.collect(Collectors.joining(", ")), new CollectionResult<>(rootUnits)));
} else if (locationDefinition instanceof PathLocation pathLocation) {
String resolvePath = resolvePath(pathLocation.getPath(), definition);
File fileLocation;
Expand All @@ -161,32 +174,38 @@ public TargetDefinitionContent resolveContentWithExceptions(TargetDefinition def
FileTargetDefinitionContent fileRepositoryRolver = fileRepositories.computeIfAbsent(
fileLocation.getAbsolutePath(),
key -> new FileTargetDefinitionContent(provisioningAgent, fileLocation));
IQueryResult<IInstallableUnit> result;
if (pathLocation instanceof DirectoryLocation || pathLocation instanceof ProfileLocation) {
unitResultSet.addAll(
fileRepositoryRolver.query(QueryUtil.ALL_UNITS, new LoggingProgressMonitor(logger)));
result = fileRepositoryRolver.query(QueryUtil.ALL_UNITS, new LoggingProgressMonitor(logger));
} else if (pathLocation instanceof FeaturesLocation featuresLocation) {
IArtifactKey key = org.eclipse.equinox.p2.publisher.eclipse.FeaturesAction
.createFeatureArtifactKey(featuresLocation.getId(), featuresLocation.getVersion());
unitResultSet.addAll(fileRepositoryRolver.query(QueryUtil.createIUQuery(key),
new LoggingProgressMonitor(logger)));
result = fileRepositoryRolver.query(QueryUtil.createIUQuery(key),
new LoggingProgressMonitor(logger));
} else {
continue;
}
unitResultSet.addAll(result);
unitResultSet.accept(createCategory(resolvePath, result));
} else {
logger.warn("Target location path '" + fileLocation.getAbsolutePath()
+ "' does not exist, target resolution might be incomplete.");
}
} else if (locationDefinition instanceof MavenGAVLocation location) {
} else if (locationDefinition instanceof MavenGAVLocation mavenLocation) {
TargetDefinitionContent targetDefinitionContent = mavenDependenciesResolver
.resolveTargetDefinitionContent(location, includeSourceMode);
.resolveTargetDefinitionContent(mavenLocation, includeSourceMode);
mavenLocations.add(targetDefinitionContent);
IQueryResult<IInstallableUnit> result = targetDefinitionContent.query(QueryUtil.ALL_UNITS,
new LoggingProgressMonitor(logger));
unitResultSet.addAll(result);
Set<IInstallableUnit> locationUnits = result.toUnmodifiableSet();
if (logger.isDebugEnabled()) {
logger.debug("The following artifacts were resolved from location " + location);
for (IInstallableUnit iu : result.toUnmodifiableSet()) {
logger.debug("The following artifacts were resolved from location " + mavenLocation);
for (IInstallableUnit iu : locationUnits) {
logger.debug("\t" + iu);
}
}
unitResultSet.accept(createCategory(mavenLocation.getLabel(), result));
} else if (locationDefinition instanceof TargetReferenceLocation referenceLocation) {
logger.info("Resolving " + referenceLocation.getUri());
String resolvePath = resolvePath(referenceLocation.getUri(), definition);
Expand Down Expand Up @@ -219,6 +238,7 @@ public TargetDefinitionContent resolveContentWithExceptions(TargetDefinition def
IQueryResult<IInstallableUnit> result = content.query(QueryUtil.ALL_UNITS,
new LoggingProgressMonitor(logger));
unitResultSet.addAll(result);
unitResultSet.accept(createCategory(uri, result));
} else {
logger.warn("Target location type '" + locationDefinition.getTypeDescription() + "' is not supported");
}
Expand Down Expand Up @@ -294,6 +314,14 @@ public IArtifactRepository getArtifactRepository() {
};
}

private static IInstallableUnit createCategory(String label, IQueryResult<IInstallableUnit> result) {
SiteCategory category = new SiteCategory();
category.setLabel(label);
category.setName("generated.target.category." + UUID.randomUUID());
return CATEGORY_FACTORY.createCategoryIU(category,
result.stream().filter(iu -> !iu.getId().endsWith(".feature.jar")).collect(Collectors.toSet()));
}

/**
* Converts a "raw" URI string into one that can be used to parse it as an {@link URI}. The
* conversion is especially for converting file URIs constructed using maven properties that
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ public P2TargetPlatform createTargetPlatform(TargetPlatformConfigurationStub tpC
externalArtifactFileProvider, //
localArtifactRepository, //
includeLocalMavenRepo, //
logger, shadowed);
logger, shadowed, remoteAgent);
eeResolutionHandler.readFullSpecification(targetPlatform.getInstallableUnits());

return targetPlatform;
Expand Down
Loading
Loading