org.sourcepit.b2.release.B2ScmHelper.java Source code

Java tutorial

Introduction

Here is the source code for org.sourcepit.b2.release.B2ScmHelper.java

Source

/*
 * Copyright 2014 Bernd Vogt and others.
 * 
 * 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
 * 
 * http://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 org.sourcepit.b2.release;

import java.io.File;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import javax.inject.Inject;
import javax.inject.Named;

import org.apache.maven.plugin.LegacySupport;
import org.apache.maven.project.MavenProject;
import org.apache.maven.scm.ScmException;
import org.apache.maven.scm.ScmFileSet;
import org.apache.maven.scm.ScmVersion;
import org.apache.maven.scm.command.checkin.CheckInScmResult;
import org.apache.maven.scm.command.edit.EditScmResult;
import org.apache.maven.scm.manager.NoSuchScmProviderException;
import org.apache.maven.scm.provider.ScmProvider;
import org.apache.maven.scm.repository.ScmRepository;
import org.apache.maven.scm.repository.ScmRepositoryException;
import org.apache.maven.settings.Settings;
import org.apache.maven.shared.release.ReleaseExecutionException;
import org.apache.maven.shared.release.config.ReleaseDescriptor;
import org.apache.maven.shared.release.env.ReleaseEnvironment;
import org.apache.maven.shared.release.scm.ReleaseScmCommandException;
import org.apache.maven.shared.release.scm.ReleaseScmRepositoryException;
import org.apache.maven.shared.release.scm.ScmRepositoryConfigurator;
import org.sourcepit.b2.files.ModuleDirectory;
import org.sourcepit.b2.maven.core.B2MavenBridge;
import org.sourcepit.common.utils.lang.Exceptions;

@Named
public class B2ScmHelper {
    private static final String CTX_KEY_COMMIT_PROPOSALS = B2ScmHelper.class.getName() + "#commitProposals";

    private final ScmRepositoryConfigurator scmRepositoryConfigurator;

    private final B2MavenBridge bridge;

    @Inject
    public B2ScmHelper(ScmRepositoryConfigurator scmRepositoryConfigurator, LegacySupport buildContext) {
        this.scmRepositoryConfigurator = scmRepositoryConfigurator;
        bridge = B2MavenBridge.get(buildContext.getSession());
    }

    public void edit(MavenProject mavenProject, ReleaseDescriptor releaseDescriptor, Settings settings, File file,
            boolean simulate) {
        if (!simulate) {
            doScmEdit(releaseDescriptor, settings, file);
        }
        markForCommit(mavenProject, file);
    }

    private void doScmEdit(ReleaseDescriptor releaseDescriptor, Settings settings, File file) {
        ScmRepository scmRepository;
        ScmProvider provider;
        try {
            scmRepository = scmRepositoryConfigurator.getConfiguredRepository(releaseDescriptor, settings);
            provider = scmRepositoryConfigurator.getRepositoryProvider(scmRepository);
        } catch (ScmRepositoryException e) {
            throw Exceptions.pipe(new ReleaseScmRepositoryException(e.getMessage(), e.getValidationMessages()));
        } catch (NoSuchScmProviderException e) {
            throw Exceptions.pipe(
                    new ReleaseExecutionException("Unable to configure SCM repository: " + e.getMessage(), e));
        }

        try {
            if (releaseDescriptor.isScmUseEditMode() || provider.requiresEditMode()) {
                EditScmResult scmResult = provider.edit(scmRepository,
                        new ScmFileSet(new File(releaseDescriptor.getWorkingDirectory()), file));

                if (!scmResult.isSuccess()) {
                    throw Exceptions.pipe(
                            new ReleaseScmCommandException("Unable to enable editing on the file", scmResult));
                }
            }
        } catch (ScmException e) {
            throw Exceptions.pipe(
                    new ReleaseExecutionException("An error occurred enabling edit mode: " + e.getMessage(), e));
        }
    }

    public void markForCommit(MavenProject mavenProject, File file) {
        final MavenProject moduleProject = determineModuleMavenProject(mavenProject);
        final ModuleDirectory moduleDirectory = bridge.getModuleDirectory(moduleProject);
        if (!moduleDirectory.isDerived(file)) {
            getCommitProposals(moduleProject).add(file);
        }
    }

    private MavenProject determineModuleMavenProject(MavenProject mavenProject) {
        MavenProject parentProject = mavenProject;
        while (parentProject != null) {
            if (bridge.getModule(parentProject) != null) {
                return parentProject;
            }
            parentProject = parentProject.getParent();
        }
        throw new IllegalStateException("Unable to determine module project for maven project " + mavenProject);
    }

    private static Set<File> getCommitProposals(MavenProject mavenProject) {
        @SuppressWarnings("unchecked")
        Set<File> files = (Set<File>) mavenProject.getContextValue(CTX_KEY_COMMIT_PROPOSALS);
        if (files == null) {
            files = new LinkedHashSet<File>();
            mavenProject.setContextValue(CTX_KEY_COMMIT_PROPOSALS, files);
        }
        return files;
    }

    public void performCheckins(ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment,
            List<MavenProject> mavenModuleProjects, String message)
            throws ReleaseScmRepositoryException, ReleaseExecutionException, ReleaseScmCommandException {
        ScmRepository repository;
        ScmProvider provider;
        try {
            repository = scmRepositoryConfigurator.getConfiguredRepository(releaseDescriptor,
                    releaseEnvironment.getSettings());

            repository.getProviderRepository().setPushChanges(releaseDescriptor.isPushChanges());

            provider = scmRepositoryConfigurator.getRepositoryProvider(repository);
        } catch (ScmRepositoryException e) {
            throw new ReleaseScmRepositoryException(e.getMessage(), e.getValidationMessages());
        } catch (NoSuchScmProviderException e) {
            throw new ReleaseExecutionException("Unable to configure SCM repository: " + e.getMessage(), e);
        }

        if (releaseDescriptor.isCommitByProject()) {
            for (MavenProject project : mavenModuleProjects) {
                List<File> pomFiles = collectFiles(releaseDescriptor, project);
                ScmFileSet fileSet = new ScmFileSet(project.getFile().getParentFile(), pomFiles);

                checkin(provider, repository, fileSet, releaseDescriptor, message);
            }
        } else {
            List<File> pomFiles = collectFiles(releaseDescriptor, mavenModuleProjects);
            ScmFileSet fileSet = new ScmFileSet(new File(releaseDescriptor.getWorkingDirectory()), pomFiles);

            checkin(provider, repository, fileSet, releaseDescriptor, message);
        }
    }

    private void checkin(ScmProvider provider, ScmRepository repository, ScmFileSet fileSet,
            ReleaseDescriptor releaseDescriptor, String message)
            throws ReleaseExecutionException, ReleaseScmCommandException {
        CheckInScmResult result;
        try {
            result = provider.checkIn(repository, fileSet, (ScmVersion) null, message);
        } catch (ScmException e) {
            throw new ReleaseExecutionException("An error is occurred in the checkin process: " + e.getMessage(),
                    e);
        }

        if (!result.isSuccess()) {
            throw new ReleaseScmCommandException("Unable to commit files", result);
        }
        if (releaseDescriptor.isRemoteTagging()) {
            releaseDescriptor.setScmReleasedPomRevision(result.getScmRevision());
        }
    }

    private List<File> collectFiles(ReleaseDescriptor releaseDescriptor, List<MavenProject> reactorProjects) {
        final List<File> files = new ArrayList<File>();
        for (MavenProject project : reactorProjects) {
            files.addAll(getCommitProposals(project));
        }
        return files;
    }

    private List<File> collectFiles(ReleaseDescriptor releaseDescriptor, MavenProject project) {
        return new ArrayList<File>(getCommitProposals(project));
    }
}