Skip to content

Commit

Permalink
Add a category for mirrored feature / bundle project and filter IUs
Browse files Browse the repository at this point in the history
Currently when mirroring the target platform of a bundle/feature it
mirrors everything that is reachable. Also it creates an update-site
that has not categories.

This now filters the IUs based on the project units, adds a category for
it and allows to even filter categories completely if desired.

This also contains the migration of previous used deployableFeature in
test to using this new way of creating an update-site, as part of this
the deployableFeature option is also deprecated.
  • Loading branch information
laeubi committed Jan 7, 2024
1 parent d72a866 commit cfc764f
Show file tree
Hide file tree
Showing 10 changed files with 190 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@
package org.eclipse.tycho.target;

import java.io.File;
import java.net.URI;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
Expand All @@ -24,9 +28,18 @@
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.project.MavenProject;
import org.eclipse.core.runtime.CoreException;
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.IInstallableUnit;
import org.eclipse.equinox.p2.query.CollectionResult;
import org.eclipse.equinox.p2.query.IQueryResult;
import org.eclipse.equinox.p2.query.IQueryable;
import org.eclipse.equinox.p2.query.QueryUtil;
import org.eclipse.equinox.p2.repository.artifact.IArtifactRepository;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository;
import org.eclipse.tycho.PackagingType;
import org.eclipse.tycho.ReactorProject;
import org.eclipse.tycho.TargetPlatform;
import org.eclipse.tycho.TargetPlatformService;
Expand All @@ -35,6 +48,7 @@
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.InstallableUnitSlicer;
import org.eclipse.tycho.p2maven.ListCompositeArtifactRepository;
import org.eclipse.tycho.repository.registry.facade.ReactorRepositoryManager;

Expand All @@ -43,9 +57,11 @@
* 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)
@Mojo(name = "mirror-target-platform", threadSafe = true, requiresDependencyResolution = ResolutionScope.COMPILE, defaultPhase = LifecyclePhase.PACKAGE)
public class MirrorTargetPlatformMojo extends AbstractMojo {

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

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

Expand All @@ -55,6 +71,9 @@ public class MirrorTargetPlatformMojo extends AbstractMojo {
@Parameter(defaultValue = "${project.id}")
private String name;

@Parameter(defaultValue = "true")
private boolean includeCategories = true;

@Component
private TargetPlatformService platformService;

Expand All @@ -67,6 +86,9 @@ public class MirrorTargetPlatformMojo extends AbstractMojo {
@Component
private IProvisioningAgent agent;

@Component
private InstallableUnitSlicer installableUnitSlicer;

@Override
public void execute() throws MojoExecutionException, MojoFailureException {
ReactorProject reactorProject = DefaultReactorProject.adapt(project);
Expand All @@ -78,16 +100,54 @@ public void execute() throws MojoExecutionException, MojoFailureException {
IArtifactRepository sourceArtifactRepository = targetPlatform.getArtifactRepository();
IMetadataRepository sourceMetadataRepository = targetPlatform.getMetadataRepository();
PublishingRepository publishingRepository = repositoryManager.getPublishingRepository(reactorProject);
getLog().info("Mirroring target platform, this can take a while ...");
try {
IMetadataRepository projectRepository = publishingRepository.getMetadataRepository();
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);
List.of(sourceMetadataRepository, projectRepository), agent);
IQueryable<IInstallableUnit> mirrorUnits;
if (PackagingType.TYPE_ECLIPSE_TARGET_DEFINITION.equals(project.getPackaging())) {
//for a target platform we like to mirror everything...
mirrorUnits = metadataRepository;
} else {
//for everything else we want to mirror only items that are required by the project
try {
IQueryResult<IInstallableUnit> query = projectRepository.query(QueryUtil.ALL_UNITS, null);
Set<IInstallableUnit> rootIus = query.toSet();
String label;
String projectName = project.getName();
if (projectName != null && !projectName.isBlank()) {
label = projectName;
} else {
label = project.getId();
}
rootIus.add(createCategory(label, query));
mirrorUnits = installableUnitSlicer.computeDependencies(rootIus, metadataRepository);
} catch (CoreException e) {
throw new MojoFailureException("Failed to compute dependencies to mirror", e);
}
}
Set<IInstallableUnit> toMirror = mirrorUnits.query(QueryUtil.ALL_UNITS, null).toSet();
if (!includeCategories) {
//remove any categories from the result
toMirror.removeIf(QueryUtil::isCategory);
}
getLog().info(
"Mirroring " + toMirror.size() + " unit(s) from the target platform, this can take a while ...");
mirrorService.mirrorDirect(artifactRepository, new CollectionResult<IInstallableUnit>(toMirror),
destination, name);
} catch (FacadeException e) {
throw new MojoFailureException(e.getMessage(), e.getCause());
}
}

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

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@
import java.util.Collection;
import java.util.Map;

import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.query.IQueryable;
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 @@ -121,9 +122,11 @@ void mirrorStandalone(RepositoryReferences sources, DestinationRepositoryDescrip
* the destination
* @param repositoryName
* the name of the new repository
* @throws FacadeException
*/
void mirrorDirect(IArtifactRepository sourceArtifactRepository, IMetadataRepository sourceMetadataRepository,
File repositoryDestination, String repositoryName) throws FacadeException;
void mirrorDirect(IArtifactRepository sourceArtifactRepository,
IQueryable<IInstallableUnit> sourceMetadataRepository, File repositoryDestination, String repositoryName)
throws FacadeException;

/**
* Modifies the artifact repository to add mapping rules to download Maven released artifacts
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
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.IQueryable;
import org.eclipse.equinox.p2.query.QueryUtil;
import org.eclipse.equinox.p2.repository.IRepositoryManager;
import org.eclipse.equinox.p2.repository.artifact.IArtifactDescriptor;
Expand Down Expand Up @@ -459,8 +460,9 @@ public void addMavenMappingRules(File repository, URI[] mavenRepositories) throw
}

@Override
public void mirrorDirect(IArtifactRepository sourceArtifactRepository, IMetadataRepository sourceMetadataRepository,
File repositoryDestination, String repositoryName) throws FacadeException {
public void mirrorDirect(IArtifactRepository sourceArtifactRepository,
IQueryable<IInstallableUnit> sourceMetadataRepository, File repositoryDestination, String repositoryName)
throws FacadeException {
if (repositoryDestination.exists()) {
FileUtils.deleteQuietly(repositoryDestination);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,20 @@

<plugin>
<groupId>org.eclipse.tycho</groupId>
<artifactId>tycho-packaging-plugin</artifactId>
<artifactId>target-platform-configuration</artifactId>
<version>${tycho-version}</version>
<configuration>
<deployableFeature>true</deployableFeature>
</configuration>
<executions>
<execution>
<id>inject</id>
<goals>
<goal>mirror-target-platform</goal>
</goals>
</execution>
</executions>
<configuration>
<destination>${project.build.directory}/site</destination>
<includeCategories>false</includeCategories>
</configuration>
</plugin>

<plugin>
Expand Down
17 changes: 13 additions & 4 deletions tycho-its/projects/TYCHO0439repositoryCategories/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,20 @@
</plugin>
<plugin>
<groupId>org.eclipse.tycho</groupId>
<artifactId>tycho-packaging-plugin</artifactId>
<artifactId>target-platform-configuration</artifactId>
<version>${tycho-version}</version>
<configuration>
<deployableFeature>true</deployableFeature>
</configuration>
<executions>
<execution>
<id>inject</id>
<goals>
<goal>mirror-target-platform</goal>
</goals>
</execution>
</executions>
<configuration>
<destination>${project.build.directory}/site</destination>
<includeCategories>false</includeCategories>
</configuration>
</plugin>
<plugin>
<groupId>org.eclipse.tycho</groupId>
Expand Down
3 changes: 0 additions & 3 deletions tycho-its/projects/brokenp2data/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@
<groupId>org.eclipse.tycho</groupId>
<artifactId>tycho-packaging-plugin</artifactId>
<version>${tycho-version}</version>
<configuration>
<deployableFeature>true</deployableFeature>
</configuration>
</plugin>
</plugins>
</build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,20 @@
<plugins>
<plugin>
<groupId>org.eclipse.tycho</groupId>
<artifactId>tycho-packaging-plugin</artifactId>
<artifactId>target-platform-configuration</artifactId>
<version>${tycho-version}</version>
<configuration>
<deployableFeature>true</deployableFeature>
</configuration>
<executions>
<execution>
<id>inject</id>
<goals>
<goal>mirror-target-platform</goal>
</goals>
</execution>
</executions>
<configuration>
<destination>${project.build.directory}/site</destination>
<includeCategories>false</includeCategories>
</configuration>
</plugin>
</plugins>
</build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,41 +28,41 @@

public class RepositoryCategoriesTest extends AbstractTychoIntegrationTest {

@Test
public void testDeployableFeature() throws Exception {
Verifier v01 = getVerifier("TYCHO0439repositoryCategories");
v01.executeGoal("install");
v01.verifyErrorFreeLog();
@Test
public void testDeployableFeature() throws Exception {
Verifier v01 = getVerifier("TYCHO0439repositoryCategories");
v01.executeGoal("install");
v01.verifyErrorFreeLog();

File site = new File(v01.getBasedir(), "target/site");
Assert.assertTrue(site.isDirectory());
File site = new File(v01.getBasedir(), "target/site");
Assert.assertTrue(site.isDirectory());

File content = new File(site, "content.jar");
Assert.assertTrue(content.isFile());
File content = new File(site, "content.jar");
Assert.assertTrue(content.getAbsolutePath() + " is not a file!", content.isFile());

boolean found = false;
boolean found = false;

XMLParser parser = new XMLParser();
Document document = null;
ZipFile contentJar = new ZipFile(content);
try {
ZipEntry contentXmlEntry = contentJar.getEntry("content.xml");
document = parser.parse(new XMLIOSource(contentJar.getInputStream(contentXmlEntry)));
} finally {
contentJar.close();
}
Element repository = document.getRootElement();
all_units: for (Element unit : repository.getChild("units").getChildren("unit")) {
for (Element property : unit.getChild("properties").getChildren("property")) {
if ("org.eclipse.equinox.p2.type.category".equals(property.getAttributeValue("name"))
&& Boolean.parseBoolean(property.getAttributeValue("value"))) {
found = true;
break all_units;
}
}
}
XMLParser parser = new XMLParser();
Document document = null;
ZipFile contentJar = new ZipFile(content);
try {
ZipEntry contentXmlEntry = contentJar.getEntry("content.xml");
document = parser.parse(new XMLIOSource(contentJar.getInputStream(contentXmlEntry)));
} finally {
contentJar.close();
}
Element repository = document.getRootElement();
all_units: for (Element unit : repository.getChild("units").getChildren("unit")) {
for (Element property : unit.getChild("properties").getChildren("property")) {
if ("org.eclipse.equinox.p2.type.category".equals(property.getAttributeValue("name"))
&& Boolean.parseBoolean(property.getAttributeValue("value"))) {
found = true;
break all_units;
}
}
}

Assert.assertTrue("Custom category", found);
}
Assert.assertTrue("Custom category is missing: " + content.getAbsolutePath(), found);
}

}
Loading

0 comments on commit cfc764f

Please sign in to comment.