Skip to content

Commit

Permalink
Add includeAllSources property to include all available source bundles
Browse files Browse the repository at this point in the history
Fix #926
  • Loading branch information
laeubi committed Aug 23, 2022
1 parent 4f67446 commit f472406
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 13 deletions.
5 changes: 5 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ This page describes the noteworthy improvements provided by each release of Ecli

## 3.0.0 (under development)

### Support for inclusion of all source bundles in an update-site

The [tycho-p2-repository-plugin:2.7.0:assemble-repository](https://www.eclipse.org/tycho/sitedocs/tycho-p2/tycho-p2-repository-plugin/assemble-repository-mojo.html) now support a new property `includeAllSources` that,
when enabled, includes any available source bundle in the resulting repository.

### Support for Eclipse-Products with mixed Features and Plugins

Tycho now supports building _mixed_ Products. In mixed Products both the listed features and listed plug-ins are installed.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,15 @@
package org.eclipse.tycho.p2.tools.mirroring;

import java.net.URI;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.equinox.internal.p2.director.PermissiveSlicer;
import org.eclipse.equinox.internal.p2.director.Slicer;
import org.eclipse.equinox.internal.p2.metadata.IRequiredCapability;
Expand All @@ -26,8 +30,15 @@
import org.eclipse.equinox.p2.internal.repository.tools.RepositoryDescriptor;
import org.eclipse.equinox.p2.internal.repository.tools.SlicingOptions;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.metadata.IProvidedCapability;
import org.eclipse.equinox.p2.metadata.IRequirement;
import org.eclipse.equinox.p2.metadata.MetadataFactory;
import org.eclipse.equinox.p2.metadata.MetadataFactory.InstallableUnitDescription;
import org.eclipse.equinox.p2.metadata.Version;
import org.eclipse.equinox.p2.metadata.VersionRange;
import org.eclipse.equinox.p2.metadata.expression.IMatchExpression;
import org.eclipse.equinox.p2.query.CollectionResult;
import org.eclipse.equinox.p2.query.IQueryable;
import org.eclipse.equinox.p2.query.QueryUtil;
import org.eclipse.equinox.p2.repository.IRepository;
import org.eclipse.equinox.p2.repository.IRepositoryReference;
Expand All @@ -42,6 +53,7 @@ public class MirrorApplication extends org.eclipse.equinox.p2.internal.repositor

private final Map<String, String> extraArtifactRepositoryProperties;
private final List<RepositoryReference> repositoryReferences;
private boolean includeAllSource;

public MirrorApplication(IProvisioningAgent agent, Map<String, String> extraArtifactRepositoryProperties,
List<RepositoryReference> repositoryReferences) {
Expand Down Expand Up @@ -69,9 +81,10 @@ protected Slicer createSlicer(SlicingOptions options) {
boolean includeOptionalDependencies = options.includeOptionalDependencies();
boolean onlyFilteredRequirements = options.followOnlyFilteredRequirements();
boolean considerFilter = (context != null && context.size() > 1) ? true : false;
PermissiveSlicer slicer = new PermissiveSlicer(getCompositeMetadataRepository(), context,
includeOptionalDependencies, options.isEverythingGreedy(), options.forceFilterTo(),
options.considerStrictDependencyOnly(), onlyFilteredRequirements) {
IMetadataRepository repository = getCompositeMetadataRepository();
PermissiveSlicer slicer = new PermissiveSlicer(repository, context, includeOptionalDependencies,
options.isEverythingGreedy(), options.forceFilterTo(), options.considerStrictDependencyOnly(),
onlyFilteredRequirements) {
@Override
protected boolean isApplicable(IInstallableUnit iu, IRequirement req) {
if (QueryUtil.isGroup(iu)) {
Expand Down Expand Up @@ -99,10 +112,48 @@ protected boolean isApplicable(IInstallableUnit iu, IRequirement req) {
return super.isApplicable(iu, req);
}

@Override
public IQueryable<IInstallableUnit> slice(IInstallableUnit[] ius, IProgressMonitor monitor) {
IQueryable<IInstallableUnit> slice = super.slice(ius, monitor);
if (includeAllSource) {
Set<IInstallableUnit> units = slice.query(QueryUtil.ALL_UNITS, null).toSet();
IInstallableUnit sourceUnit = createSourceUnit(units);
IQueryable<IInstallableUnit> queryable = super.slice(new IInstallableUnit[] { sourceUnit },
monitor);
units.addAll(queryable.query(QueryUtil.ALL_UNITS, null).toSet());
units.remove(sourceUnit);
return new CollectionResult<>(units);
}
return slice;
}

};
return slicer;
}

private static final IInstallableUnit createSourceUnit(Collection<IInstallableUnit> units) {

final IRequirement bundleRequirement = MetadataFactory.createRequirement("org.eclipse.equinox.p2.eclipse.type",
"bundle", null, null, false, false, false);
InstallableUnitDescription sourceDescription = new MetadataFactory.InstallableUnitDescription();
String id = "Source-Bundles-" + UUID.randomUUID();
sourceDescription.setId(id);
final Version sourceIUVersion = Version.createOSGi(1, 0, 0);
sourceDescription.setVersion(sourceIUVersion);
sourceDescription.setCapabilities(new IProvidedCapability[] {
MetadataFactory.createProvidedCapability(IInstallableUnit.NAMESPACE_IU_ID, id, sourceIUVersion) });
sourceDescription.addRequirements(units.stream().filter(unit -> unit.satisfies(bundleRequirement))
.map(MirrorApplication::createSourceBundleRequirement).collect(Collectors.toList()));
return MetadataFactory.createInstallableUnit(sourceDescription);
}

private static IRequirement createSourceBundleRequirement(IInstallableUnit unit) {
IRequirement optionalGreedySourceBundleRequirement = MetadataFactory.createRequirement("osgi.bundle",
unit.getId() + ".source", new VersionRange(unit.getVersion(), true, unit.getVersion(), true), null,
true, false, true);
return optionalGreedySourceBundleRequirement;
}

@Override
protected IMetadataRepository initializeDestination(RepositoryDescriptor toInit, IMetadataRepositoryManager mgr)
throws ProvisionException {
Expand All @@ -125,4 +176,8 @@ private static org.eclipse.equinox.p2.repository.spi.RepositoryReference toSpiRe
type, rr.isEnable() ? IRepository.ENABLED : IRepository.NONE);
}

public void setIncludeSources(boolean includeAllSource) {
this.includeAllSource = includeAllSource;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -143,14 +143,15 @@ private static IQuery<IInstallableUnit> createQuery(IUDescription iu) {
@Override
public void mirrorReactor(RepositoryReferences sources, DestinationRepositoryDescriptor destination,
Collection<DependencySeed> projectSeeds, BuildContext context, boolean includeAllDependencies,
Map<String, String> filterProperties) throws FacadeException {
boolean includeAllSource, Map<String, String> filterProperties) throws FacadeException {
IProvisioningAgent agent = Activator.createProvisioningAgent(context.getTargetDirectory());
try {
final MirrorApplication mirrorApp = createMirrorApplication(sources, destination, agent);

// mirror scope: seed units...
mirrorApp.setSourceIUs(
toInstallableUnitList(projectSeeds, mirrorApp.getCompositeMetadataRepository(), sources));
mirrorApp.setIncludeSources(includeAllSource);

// TODO the p2 mirror tool should support mirroring multiple environments at once
for (TargetEnvironment environment : context.getEnvironments()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ public interface MirrorApplicationService {
* environment specific installable units
* @param includeAllDependencies
* Whether to include all transitive dependencies
* @param includeAllSource
* Whether to include all possible sources
* @param filterProperties
* additional filter properties to be set in the p2 slicing options. May be
* <code>null</code>
Expand All @@ -56,7 +58,7 @@ public interface MirrorApplicationService {
*/
public void mirrorReactor(RepositoryReferences sources, DestinationRepositoryDescriptor destination,
Collection<DependencySeed> seeds, BuildContext context, boolean includeAllDependencies,
Map<String, String> filterProperties) throws FacadeException;
boolean includeAllSource, Map<String, String> filterProperties) throws FacadeException;

/**
* recreates the metadata of an existing repository e.g. to account for changes in the contained
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,13 +97,13 @@ public void testMirrorNothing() throws Exception {
// make sure that this unsupported case is detected; the mirror application would just mirror everything
Collection<DependencySeed> noSeeds = Collections.emptyList();

subject.mirrorReactor(sourceRepos("patch", "e342"), destinationRepo, noSeeds, context, false, null);
subject.mirrorReactor(sourceRepos("patch", "e342"), destinationRepo, noSeeds, context, false, false, null);
}

@Test
public void testMirrorFeatureWithContent() throws Exception {
subject.mirrorReactor(sourceRepos("patch", "e342"), destinationRepo, seedFor(SIMPLE_FEATURE_IU), context, false,
null);
false, null);

logVerifier.expectNoWarnings();
assertTrue(repoFile(destinationRepo, "plugins/org.eclipse.core.runtime_3.4.0.v20080512.jar").exists());
Expand All @@ -119,7 +119,7 @@ public void testExtraArtifactRepositoryProperties() throws Exception {
destinationRepo = new DestinationRepositoryDescriptor(tempFolder.newFolder("dest2"), DEFAULT_NAME, false, false,
false, false, true, extraArtifactRepositoryProperties, Collections.emptyList());
subject.mirrorReactor(sourceRepos("patch", "e342"), destinationRepo, seedFor(SIMPLE_FEATURE_IU), context, false,
null);
false, null);

logVerifier.expectNoWarnings();
File artifactsXml = repoFile(destinationRepo, "artifacts.xml");
Expand All @@ -142,7 +142,7 @@ public void testExtraArtifactRepositoryProperties() throws Exception {
@Test
public void testMirrorPatch() throws Exception {
subject.mirrorReactor(sourceRepos("patch", "e352"), destinationRepo, seedFor(FEATURE_PATCH_IU), context, false,
null);
false, null);

//TODO why mirror tool emits a warning here? logVerifier.expectNoWarnings();
assertTrue(repoFile(destinationRepo, "plugins/org.eclipse.core.runtime_3.5.0.v20090525.jar").exists());
Expand All @@ -152,7 +152,7 @@ public void testMirrorPatch() throws Exception {
@Test
public void testMirrorFeatureAndPatch() throws Exception {
subject.mirrorReactor(sourceRepos("patch", "e352"), destinationRepo,
seedFor(SIMPLE_FEATURE_IU, FEATURE_PATCH_IU), context, false, null);
seedFor(SIMPLE_FEATURE_IU, FEATURE_PATCH_IU), context, false, false, null);

assertTrue(repoFile(destinationRepo, "plugins/org.eclipse.core.runtime_3.5.0.v20090525.jar").exists());
assertTrue(repoFile(destinationRepo, "features/" + SIMPLE_FEATURE + "_1.0.0.jar").exists());
Expand All @@ -170,7 +170,7 @@ public void testMirrorWithMissingMandatoryContent() throws Exception {
* since it is not easy to distinguish between patched and unpatched dependencies, only a
* warning is issued.
*/
subject.mirrorReactor(sourceRepos("patch"), destinationRepo, seedFor(SIMPLE_FEATURE_IU), context, false, null);
subject.mirrorReactor(sourceRepos("patch"), destinationRepo, seedFor(SIMPLE_FEATURE_IU), context, false, false, null);

logVerifier.expectWarning(not(is("")));
}
Expand All @@ -184,7 +184,7 @@ public void testMirrorForSeedWithNullIU() throws Exception {
List<DependencySeed> seeds = Collections
.singletonList(new DependencySeed(null, "org.eclipse.core.runtime", null));

subject.mirrorReactor(sourceRepos("e342"), destinationRepo, seeds, context, false, null);
subject.mirrorReactor(sourceRepos("e342"), destinationRepo, seeds, context, false, false, null);

assertTrue(repoFile(destinationRepo, "plugins/org.eclipse.core.runtime_3.4.0.v20080512.jar").exists());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,15 @@ public class AssembleRepositoryMojo extends AbstractRepositoryMojo {
@Parameter(defaultValue = "false")
private boolean includeAllDependencies;

/**
* <p>
* By default, only explicitly mentioned sources are included. Set this parameter to
* <code>true</code> to include all sources that are available and included in this repository.
* </p>
*/
@Parameter(defaultValue = "false")
private boolean includeAllSources;

/**
* <p>
* Compress the repository index files <tt>content.xml</tt> and <tt>artifacts.xml</tt>.
Expand Down Expand Up @@ -167,7 +176,7 @@ public void execute() throws MojoExecutionException, MojoFailureException {
destination, repositoryName, compress, xzCompress, keepNonXzIndexFiles,
!createArtifactRepository, true, extraArtifactRepositoryProperties, repositoryRefrences);
mirrorApp.mirrorReactor(sources, destinationRepoDescriptor, projectSeeds, getBuildContext(),
includeAllDependencies, profileProperties);
includeAllDependencies, includeAllSources, profileProperties);
} catch (FacadeException e) {
throw new MojoExecutionException("Could not assemble p2 repository", e);
}
Expand Down

0 comments on commit f472406

Please sign in to comment.