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