blob: 5dc5872c05f035f0221cfe1f6a9fda9b72540066 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011, 2019 SAP AG and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Jan Sievers - initial API and implementation
* Mickael Istria (Red Hat Inc.) - 518813 Use target-platform repository
*******************************************************************************/
package org.eclipse.tycho.plugins.p2.extras;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.maven.execution.MavenSession;
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.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.eclipse.sisu.equinox.EquinoxServiceFactory;
import org.eclipse.tycho.BuildOutputDirectory;
import org.eclipse.tycho.core.TychoProject;
import org.eclipse.tycho.p2.facade.RepositoryReferenceTool;
import org.eclipse.tycho.p2.tools.DestinationRepositoryDescriptor;
import org.eclipse.tycho.p2.tools.FacadeException;
import org.eclipse.tycho.p2.tools.RepositoryReferences;
import org.eclipse.tycho.p2.tools.mirroring.facade.IUDescription;
import org.eclipse.tycho.p2.tools.mirroring.facade.MirrorApplicationService;
import org.eclipse.tycho.p2.tools.mirroring.facade.MirrorOptions;
/**
* Maven plugin front-end for org.eclipse.equinox.p2.internal.repository.tools.MirrorApplication.
* Intended as a replacement for the <a href=
* "http://help.eclipse.org/indigo/index.jsp?topic=%2Forg.eclipse.platform.doc.isv%2Fguide%2Fp2_repositorytasks.htm"
* >p2.mirror ant task</a>.
*/
@Mojo(name = "mirror")
public class MirrorMojo extends AbstractMojo {
@Parameter(property = "project", readonly = true)
private MavenProject project;
@Parameter(property = "session", readonly = true)
private MavenSession session;
@Component
private EquinoxServiceFactory p2;
@Component
private RepositoryReferenceTool repositoryReferenceTool;
@Component(role = TychoProject.class)
private Map<String, TychoProject> projectTypes;
/**
* Source repositori(es) to mirror from.
*
* @see also {@link #targetPlatformAsSource} and {@link #currentModuleAsSource}
*/
@Parameter(required = false)
private List<Repository> source;
/**
* The destination directory to mirror to.
*/
@Parameter(defaultValue = "${project.build.directory}/repository")
private File destination;
/**
* The target repository name.
*/
@Parameter
private String name;
/**
* (Optional) Which IUs to mirror. If omitted, all IUs available in the source repositories will
* be mirrored. An IU must specify an id and may specify a version. If version is omitted, the
* latest available version will be queried. By default, IUs required by the specified IUs will
* also be mirrored. See also {@link #followStrictOnly}, {@link #followOnlyFilteredRequirements}
* , {@link #includeOptional}, {@link #includeNonGreedy}, {@link #includeFeatures}.
*/
@Parameter
private List<Iu> ius;
/**
* Set to true if only strict dependencies should be followed. A strict dependency is defined by
* a version range only including exactly one version (e.g. [1.0.0.v2009, 1.0.0.v2009]). In
* particular, plugins/features included in a feature are normally required via a strict
* dependency from the feature to the included plugin/feature.
*/
@Parameter(defaultValue = "false")
private boolean followStrictOnly;
/**
* Whether or not to include features.
*/
@Parameter(defaultValue = "true")
private boolean includeFeatures;
/**
* Whether or not to include pack200 artifacts.
*/
@Parameter(defaultValue = "true")
private boolean includePacked;
/**
* Whether or not to follow optional requirements.
*/
@Parameter(defaultValue = "true")
private boolean includeOptional;
/**
* Whether or not to follow non-greedy requirements.
*/
@Parameter(defaultValue = "true")
private boolean includeNonGreedy;
/**
* Filter properties. In particular, a platform filter can be specified by using keys
* <code>osgi.os, osgi.ws, osgi.arch</code>.
*/
@Parameter
private Map<String, String> filter = new HashMap<>();
/**
* Follow only requirements which match the filter specified.
*/
@Parameter(defaultValue = "false")
private boolean followOnlyFilteredRequirements;
/**
* Set to <code>true</code> to filter the resulting set of IUs to only include the latest
* version of each Installable Unit only. By default, all versions satisfying dependencies are
* included.
*/
@Parameter(defaultValue = "false")
private boolean latestVersionOnly;
/**
* Whether to mirror metadata only (no artifacts).
*/
@Parameter(defaultValue = "false")
private boolean mirrorMetadataOnly;
/**
* Whether to compress the destination repository metadata files (artifacts.xml, content.xml).
*/
@Parameter(defaultValue = "true")
private boolean compress;
/**
* Whether to append to an existing destination repository. Note that appending an IU which
* already exists in the destination repository will cause the mirror operation to fail.
*/
@Parameter(defaultValue = "true")
private boolean append;
/**
* <p>
* Add XZ-compressed repository index files. XZ offers better compression ratios esp. for highly
* redundant file content.
* </p>
*
* @since 0.25.0
*/
@Parameter(defaultValue = "true")
private boolean xzCompress;
/**
* <p>
* If {@link #xzCompress} is <code>true</code>, whether jar or xml index files should be kept in
* addition to XZ-compressed index files. This fallback provides backwards compatibility for
* pre-Mars p2 clients which cannot read XZ-compressed index files.
* </p>
*
* @since 0.25.0
*/
@Parameter(defaultValue = "true")
private boolean keepNonXzIndexFiles;
/**
* <p>
* Whether to add the target-platform content as a source. Ignored for non-Tycho packaging
* types.
* </p>
*
* @since 1.1.0
*/
@Parameter(defaultValue = "false")
private boolean targetPlatformAsSource;
/**
* <p>
* Whether the current build p2 output should be added as source. Ignored for non-Tycho
* packaging types. Ignored if {@link #targetPlatformAsSource} == false;
* </p>
*
* @since 1.1.0
*/
@Parameter(defaultValue = "true")
private boolean currentModuleAsSource;
/**
* <p>
* If set to true, mirroring continues to run in the event of an error during the mirroring
* process and will just log an info message.
* </p>
*
* @since 1.1.0
*/
@Parameter(defaultValue = "false")
private boolean ignoreErrors;
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
final MirrorApplicationService mirrorService = p2.getService(MirrorApplicationService.class);
RepositoryReferences sourceDescriptor = null;
if (this.projectTypes.containsKey(project.getPackaging()) && this.repositoryReferenceTool != null
&& this.targetPlatformAsSource) {
sourceDescriptor = repositoryReferenceTool.getVisibleRepositories(this.project, this.session,
this.currentModuleAsSource ? RepositoryReferenceTool.REPOSITORIES_INCLUDE_CURRENT_MODULE : 0);
} else {
sourceDescriptor = new RepositoryReferences();
}
for (final Repository sourceRepository : source) {
if (sourceRepository.getLayout().hasMetadata()) {
sourceDescriptor.addMetadataRepository(sourceRepository.getLocation());
}
if (sourceRepository.getLayout().hasArtifacts()) {
sourceDescriptor.addArtifactRepository(sourceRepository.getLocation());
}
}
if (sourceDescriptor.getArtifactRepositories().isEmpty()
&& sourceDescriptor.getMetadataRepositories().isEmpty()) {
throw new MojoExecutionException("No repository provided as 'source'");
}
if (name == null) {
name = "";
}
final DestinationRepositoryDescriptor destinationDescriptor = new DestinationRepositoryDescriptor(destination,
name, compress, xzCompress, keepNonXzIndexFiles, mirrorMetadataOnly, append, Collections.emptyMap(),
Collections.emptyList());
getLog().info("Mirroring to " + destination + "...");
try {
mirrorService.mirrorStandalone(sourceDescriptor, destinationDescriptor, createIUDescriptions(),
createMirrorOptions(), getBuildOutputDirectory());
} catch (final FacadeException e) {
throw new MojoExecutionException("Error during mirroring", e);
}
}
private MirrorOptions createMirrorOptions() {
MirrorOptions options = new MirrorOptions();
options.setFollowOnlyFilteredRequirements(followOnlyFilteredRequirements);
options.setFollowStrictOnly(followStrictOnly);
options.setIncludeFeatures(includeFeatures);
options.setIncludeNonGreedy(includeNonGreedy);
options.setIncludeOptional(includeOptional);
options.setLatestVersionOnly(latestVersionOnly);
options.getFilter().putAll(filter);
options.setIncludePacked(includePacked);
options.setIgnoreErrors(ignoreErrors);
return options;
}
private Collection<IUDescription> createIUDescriptions() {
if (ius == null) {
return Collections.<IUDescription> emptyList();
}
List<IUDescription> result = new ArrayList<>();
for (Iu iu : ius) {
result.add(iu.toIUDescription());
}
return result;
}
private BuildOutputDirectory getBuildOutputDirectory() {
return new BuildOutputDirectory(project.getBuild().getDirectory());
}
}