    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *      https://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 * Unless required by applicable law or agreed to in writing, software
    012 * distributed under the License is distributed on an "AS IS" BASIS,
    013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 * See the License for the specific language governing permissions and
    015 * limitations under the License.
    016 */
    017package org.apache.commons.release.plugin.mojos;
    018
    019import java.io.File;
    020import java.util.Arrays;
    021import java.util.List;
    022
    023import org.apache.commons.lang3.StringUtils;
    024import org.apache.commons.release.plugin.SharedFunctions;
    025import org.apache.maven.plugin.AbstractMojo;
    026import org.apache.maven.plugin.MojoExecutionException;
    027import org.apache.maven.plugin.MojoFailureException;
    028import org.apache.maven.plugins.annotations.Component;
    029import org.apache.maven.plugins.annotations.LifecyclePhase;
    030import org.apache.maven.plugins.annotations.Mojo;
    031import org.apache.maven.plugins.annotations.Parameter;
    032import org.apache.maven.project.MavenProject;
    033import org.apache.maven.scm.ScmException;
    034import org.apache.maven.scm.ScmFileSet;
    035import org.apache.maven.scm.command.checkin.CheckInScmResult;
    036import org.apache.maven.scm.command.checkout.CheckOutScmResult;
    037import org.apache.maven.scm.command.remove.RemoveScmResult;
    038import org.apache.maven.scm.manager.BasicScmManager;
    039import org.apache.maven.scm.manager.ScmManager;
    040import org.apache.maven.scm.provider.ScmProvider;
    041import org.apache.maven.scm.provider.svn.repository.SvnScmProviderRepository;
    042import org.apache.maven.scm.provider.svn.svnexe.SvnExeScmProvider;
    043import org.apache.maven.scm.repository.ScmRepository;
    044import org.apache.maven.settings.Settings;
    045import org.apache.maven.settings.crypto.SettingsDecrypter;
    046
    047/**
    048 * This class checks out the dev distribution location, checks whether anything exists in the
    049 * distribution location, and if it is non-empty it deletes all the resources there.
    050 *
    051 * @since 1.6
    052 */
    053@Mojo(name = "clean-staging",
    054        defaultPhase = LifecyclePhase.POST_CLEAN,
    055        threadSafe = true,
    056        aggregator = true)
    057public final class CommonsStagingCleanupMojo extends AbstractMojo {
    058
    059    /**
    060     * The {@link MavenProject} object is essentially the context of the maven build at
    061     * a given time.
    062     */
    063    @Parameter(defaultValue = "${project}", required = true)
    064    private MavenProject project;
    065
    066    /**
    067     * The main working directory for the plugin, namely <code>target/commons-release-plugin</code>, but
    068     * that assumes that we're using the default maven <code>${project.build.directory}</code>.
    069     */
    070    @Parameter(defaultValue = "${project.build.directory}/commons-release-plugin", property = "commons.outputDirectory")
    071    private File workingDirectory;
    072
    073    /**
    074     * The location to which to checkout the dist subversion repository under our working directory, which
    075     * was given above. We then do an SVN delete on all the directories in this repository.
    076     */
    077    @Parameter(defaultValue = "${project.build.directory}/commons-release-plugin/scm-cleanup",
    078            property = "commons.distCleanupDirectory")
    079    private File distCleanupDirectory;
    080
    081    /**
    082     * A boolean that determines whether or not we actually commit the files up to the subversion repository.
    083     * If this is set to {@code true}, we do all but make the commits. We do checkout the repository in question
    084     * though.
    085     */
    086    @Parameter(property = "commons.release.dryRun", defaultValue = "false")
    087    private Boolean dryRun;
    088
    089    /**
    090     * The url of the subversion repository to which we wish the artifacts to be staged. Typically this would need to
    091     * be of the form: <code>scm:svn:https://dist.apache.org/repos/dist/dev/commons/foo/version-RC#</code>. Note. that
    092     * the prefix to the substring <code>https</code> is a requirement.
    093     */
    094    @Parameter(defaultValue = "", property = "commons.distSvnStagingUrl")
    095    private String distSvnStagingUrl;
    096
    097    /**
    098     * A parameter to generally avoid running unless it is specifically turned on by the consuming module.
    099     */
    100    @Parameter(defaultValue = "false", property = "commons.release.isDistModule")
    101    private Boolean isDistModule;
    102
    103    /**
    104     * The ID of the server (specified in settings.xml) which should be used for dist authentication.
    105     * This will be used in preference to {@link #username}/{@link #password}.
    106     */
    107    @Parameter(property = "commons.distServer")
    108    private String distServer;
    109
    110    /**
    111     * The username for the distribution subversion repository. This is typically your Apache id.
    112     */
    113    @Parameter(property = "user.name")
    114    private String username;
    115
    116    /**
    117     * The password associated with {@link CommonsDistributionStagingMojo#username}.
    118     */
    119    @Parameter(property = "user.password")
    120    private String password;
    121
    122    /**
    123     * Maven {@link Settings}.
    124     */
    125    @Parameter(defaultValue = "${settings}", readonly = true, required = true)
    126    private Settings settings;
    127
    128    /**
    129     * Maven {@link SettingsDecrypter} component.
    130     */
    131    @Component
    132    private SettingsDecrypter settingsDecrypter;
    133
    134    /**
    135     * Constructs a new instance.
    136     */
    137    public CommonsStagingCleanupMojo() {
    138        // empty
    139    }
    140
    141    @Override
    142    public void execute() throws MojoExecutionException, MojoFailureException {
    143        if (!isDistModule) {
    144            getLog().info("This module is marked as a non distribution "
    145                    + "or assembly module, and the plugin will not run.");
    146            return;
    147        }
    148        if (StringUtils.isEmpty(distSvnStagingUrl)) {
    149            getLog().warn("commons.distSvnStagingUrl is not set, the commons-release-plugin will not run.");
    150            return;
    151        }
    152        if (!workingDirectory.exists()) {
    153            SharedFunctions.initDirectory(getLog(), workingDirectory);
    154        }
    155        try {
    156            final ScmManager scmManager = new BasicScmManager();
    157            scmManager.setScmProvider("svn", new SvnExeScmProvider());
    158            final ScmRepository repository = scmManager.makeScmRepository(distSvnStagingUrl);
    159            final ScmProvider provider = scmManager.getProviderByRepository(repository);
    160            final SvnScmProviderRepository providerRepository = (SvnScmProviderRepository) repository
    161                    .getProviderRepository();
    162            SharedFunctions.setAuthentication(
    163                    providerRepository,
    164                    distServer,
    165                    settings,
    166                    settingsDecrypter,
    167                    username,
    168                    password
    169            );
    170            getLog().info("Checking out dist from: " + distSvnStagingUrl);
    171            final ScmFileSet scmFileSet = new ScmFileSet(distCleanupDirectory);
    172            final CheckOutScmResult checkOutResult = provider.checkOut(repository, scmFileSet);
    173            if (!checkOutResult.isSuccess()) {
    174                throw new MojoExecutionException("Failed to checkout files from SCM: "
    175                        + checkOutResult.getProviderMessage() + " [" + checkOutResult.getCommandOutput() + "]");
    176            }
    177            final List<File> filesToRemove = Arrays.asList(distCleanupDirectory.listFiles());
    178            if (filesToRemove.size() == 1) {
    179                getLog().info("No files to delete");
    180                return;
    181            }
    182            if (!dryRun) {
    183                final ScmFileSet fileSet = new ScmFileSet(distCleanupDirectory, filesToRemove);
    184                final RemoveScmResult removeScmResult = provider.remove(repository, fileSet,
    185                        "Cleaning up staging area");
    186                if (!removeScmResult.isSuccess()) {
    187                    throw new MojoFailureException("Failed to remove files from SCM: "
    188                            + removeScmResult.getProviderMessage()
    189                            + " [" + removeScmResult.getCommandOutput() + "]");
    190                }
    191                getLog().info("Cleaning distribution area for: " + project.getArtifactId());
    192                final CheckInScmResult checkInResult = provider.checkIn(
    193                        repository,
    194                        fileSet,
    195                        "Cleaning distribution area for: " + project.getArtifactId()
    196                );
    197                if (!checkInResult.isSuccess()) {
    198                    throw new MojoFailureException("Failed to commit files: " + removeScmResult.getProviderMessage()
    199                            + " [" + removeScmResult.getCommandOutput() + "]");
    200                }
    201            } else {
    202                getLog().info("Would have attempted to delete files from: " + distSvnStagingUrl);
    203            }
    204        } catch (final ScmException e) {
    205            throw new MojoFailureException(e.getMessage());
    206        }
    207
    208    }
    209}