All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.telenav.cactus.maven.mojobase.ScopedCheckoutsMojo Maven / Gradle / Ivy

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// © 2011-2022 Telenav, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
package com.telenav.cactus.maven.mojobase;

import com.telenav.cactus.scope.Scope;
import com.telenav.cactus.scope.ProjectFamily;
import com.mastfrog.util.strings.Strings;
import com.telenav.cactus.git.GitCheckout;
import com.telenav.cactus.maven.commit.CommitMessage;
import com.telenav.cactus.maven.log.BuildLog;
import com.telenav.cactus.maven.model.Pom;
import com.telenav.cactus.maven.tree.ProjectTree;
import com.telenav.cactus.maven.trigger.RunPolicy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.project.MavenProject;

import static java.util.Collections.emptySet;

/**
 * Subtype of ScopeMojo for mojos that perform git operations against a set of
 * repositories, which pre-creates the project tree and collects the set of
 * repositories that match the requested scope.
 *
 * @author Tim Boudreau
 */
public abstract class ScopedCheckoutsMojo extends ScopeMojo
{
    protected ScopedCheckoutsMojo()
    {
    }

    /**
     * Create a new mojo.
     *
     * @param runFirst If true, this mojo should run on the first
     * invocation, in the case of an aggregator project, instead of on the last
     * - this is needed, for example, for mojos that want to change branches
     * before any code is built.
     */
    protected ScopedCheckoutsMojo(boolean runFirst)
    {
        super(runFirst);
    }

    /**
     * Create a new mojo.
     *
     * @param policy The policy for when this mojo should be run.
     */
    public ScopedCheckoutsMojo(RunPolicy policy)
    {
        super(policy);
    }

    /**
     * Run this mojo against the project tree and set of checkouts it is applied
     * to.
     *
     * @param log A log
     * @param project The project being invoked agains
     * @param myCheckout The checkout of the project invoked against
     * @param tree The project tree of all checkouts
     * @param checkouts The checkouts which matched the scope and other
     * parameters of this mojo
     * @throws Exception if something goes wrong
     */
    protected abstract void execute(BuildLog log, MavenProject project,
            GitCheckout myCheckout, ProjectTree tree,
            List checkouts) throws Exception;

    protected final CommitMessage addCommitMessageDetail(CommitMessage msg,
            Collection checkouts)
    {
        return addCommitMessageDetail(msg, checkouts, emptySet());
    }

    protected final CommitMessage addCommitMessageDetail(CommitMessage msg,
            Collection checkouts, Collection projects)
    {
        if (!projects.isEmpty())
        {
            try ( CommitMessage.Section sec = msg
                    .section("Affected Projects"))
            {
                projects.forEach(pom ->
                {
                    sec.bulletPoint(pom.toArtifactIdentifiers().toString());
                });
            }
        }
        if (!checkouts.isEmpty())
        {
            try ( CommitMessage.Section sec = msg.section(
                    "Affected Checkouts"))
            {
                checkouts.forEach(checkout ->
                {
                    String nm = checkout.name().isEmpty()
                                ? "(root)"
                                : checkout.name();
                    sec.bulletPoint(nm);
                });
            }
        }

        return msg;
    }

    /**
     * If this mojo should fail if any checkout it operates on is locally
     * modified, return true here.
     *
     * @return false by default
     */
    protected boolean forbidsLocalModifications()
    {
        return false;
    }

    @Override
    protected final void execute(BuildLog log, MavenProject project,
            GitCheckout myCheckout, Scope scope, Set families,
            boolean includeRoot, boolean pretend) throws Exception
    {
        withProjectTree(false, tree ->
        {
            List checkouts = tree.matchCheckouts(scope,
                    myCheckout, includeRoot, families, project
                            .getGroupId());

            log.ifDebug(() ->
            {
                log.debug(
                        "Operate on the following repositories for " + scope + ":");
                checkouts.forEach(co -> log.debug("  * " + co));
            });

            if (forbidsLocalModifications())
            {
                checkLocallyModified(checkouts);
            }

            execute(log, project, myCheckout, tree, checkouts);
        });
    }

    private void checkLocallyModified(Collection coll)
            throws Exception
    {
        List modified = coll
                .stream()
                .filter(GitCheckout::isDirty)
                .collect(Collectors.toCollection(() -> new ArrayList<>(coll
                .size())));
        if (!modified.isEmpty())
        {
            String message = "Some checkouts are locally modified:\n"
                    + Strings.join("\n  * ", modified);
            throw new MojoExecutionException(this, message, message);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy