io.fabric8.git.internal.GitHelpers.java Source code

Java tutorial

Introduction

Here is the source code for io.fabric8.git.internal.GitHelpers.java

Source

/**
 *  Copyright 2005-2014 Red Hat, Inc.
 *
 *  Red Hat licenses this file to you 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 io.fabric8.git.internal;

import io.fabric8.api.Profiles;
import io.fabric8.utils.Strings;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.regex.Pattern;

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.NoHeadException;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.revwalk.RevCommit;
import org.gitective.core.CommitUtils;
import org.jboss.gravia.utils.IllegalStateAssertion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A bunch of helper methods for working with Git
 */
public class GitHelpers {

    private static final Logger LOGGER = LoggerFactory.getLogger(GitHelpers.class);

    static final String CONFIGS = "fabric";
    static final String CONFIGS_PROFILES = CONFIGS + File.separator + "profiles";
    static final String VERSION_ATTRIBUTES = "version.attributes";
    static final String REMOTE_ORIGIN = "origin";
    static final String MASTER_BRANCH = "master";
    static final String ROOT_TAG = "root";

    static final Pattern ENSEMBLE_PROFILE_PATTERN = Pattern
            .compile("fabric-ensemble-[0-9]+|fabric-ensemble-[0-9]+-[0-9]+");

    /**
     * Returns the root directory of the git repo which contains the ".git" directory
     */
    public static File getRootGitDirectory(Git git) {
        return git.getRepository().getDirectory().getParentFile();
    }

    public static File getProfilesDirectory(Git git) {
        return new File(GitHelpers.getRootGitDirectory(git), CONFIGS_PROFILES);
    }

    public static File getProfileDirectory(Git git, String profileId) {
        File profilesDirectory = getProfilesDirectory(git);
        String path = convertProfileIdToDirectory(profileId);
        return new File(profilesDirectory, path);
    }

    /**
     * Takes a profile ID of the form "foo-bar" and if we are using directory trees for profiles then
     * converts it to "foo/bar.profile"
     */
    public static String convertProfileIdToDirectory(String profileId) {
        return Profiles.convertProfileIdToPath(profileId);
    }

    public static RevCommit getVersionLastCommit(Git git, String branch) {
        return getLastCommit(git, branch, GitHelpers.CONFIGS_PROFILES);
    }

    public static RevCommit getProfileLastCommit(Git git, String branch, String profilePath) {
        return getLastCommit(git, branch, GitHelpers.CONFIGS_PROFILES + "/" + profilePath);
    }

    private static RevCommit getLastCommit(Git git, String branch, String path) {
        RevCommit profileRef = null;
        try {
            Ref versionRef = git.getRepository().getRefDatabase().getRef(branch);
            if (versionRef != null) {
                String revision = versionRef.getObjectId().getName();
                profileRef = CommitUtils.getLastCommit(git.getRepository(), revision, path != null ? path : ".");
            }
        } catch (IOException ex) {
            // ignore
        }
        return profileRef;
    }

    public static boolean localBranchExists(Git git, String branch) throws GitAPIException {
        List<Ref> list = git.branchList().call();
        String fullName = "refs/heads/" + branch;
        boolean localBranchExists = false;
        for (Ref ref : list) {
            String name = ref.getName();
            if (equals(name, fullName)) {
                localBranchExists = true;
                break;
            }
        }
        return localBranchExists;
    }

    public static String currentBranch(Git git) {
        String branch = null;
        Exception gitException = null;
        try {
            branch = git.getRepository().getBranch();
        } catch (Exception ex) {
            gitException = ex;
        }
        if (branch == null || gitException != null) {
            throw new IllegalStateException("Failed to get the current branch", gitException);
        }
        return branch;
    }

    public static boolean hasGitHead(Git git) throws GitAPIException, IOException {
        boolean hasHead = true;
        try {
            git.log().all().call();
            hasHead = git.getRepository().getAllRefs().containsKey("HEAD");
        } catch (NoHeadException e) {
            hasHead = false;
        }
        return hasHead;
    }

    public static void createOrCheckoutBranch(Git git, String branch, String remote) throws GitAPIException {
        Ref ref = null;
        String current = currentBranch(git);
        if (!equals(current, branch) && !localBranchExists(git, branch)) {
            ref = git.checkout().setName(branch).setForce(true).setCreateBranch(true).call();
            if (remote != null) {
                configureBranch(git, branch, remote);
            }
        } else {
            ref = git.checkout().setName(branch).setForce(true).call();
        }
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("Checked out branch " + branch + " with results " + ref.getName());
        }
    }

    public static boolean checkoutBranch(Git git, String branch) throws GitAPIException {
        String current = currentBranch(git);
        if (equals(current, branch)) {
            return true;
        } else if (localBranchExists(git, branch)) {
            Ref ref = git.checkout().setName(branch).setForce(true).call();
            LOGGER.debug("Checked out branch {} with results: ", branch, ref.getName());
            return true;
        } else {
            LOGGER.debug("Branch {} not found!", branch);
            return false;
        }
    }

    public static boolean checkoutTag(Git git, String tagName) throws GitAPIException {
        git.checkout().setName(tagName).setForce(true).call();
        LOGGER.debug("Checked out tag: {}", tagName);
        return true;
    }

    public static boolean removeBranch(Git git, String branch) throws GitAPIException {
        IllegalStateAssertion.assertFalse("master".equals(branch), "Cannot remove master branch");
        if (localBranchExists(git, branch)) {
            String current = currentBranch(git);
            if (equals(current, branch)) {
                checkoutBranch(git, "master");
            }
            List<String> list = git.branchDelete().setBranchNames(branch).setForce(true).call();
            LOGGER.debug("Deleted branch {} with results: {}", branch, list);
            return true;
        } else {
            LOGGER.debug("Branch {} not found!", branch);
            return true;
        }
    }

    protected static void configureBranch(Git git, String branch, String remote) {
        // lets update the merge config
        if (Strings.isNotBlank(branch)) {
            StoredConfig config = git.getRepository().getConfig();
            if (Strings.isNullOrBlank(config.getString("branch", branch, "remote"))
                    || Strings.isNullOrBlank(config.getString("branch", branch, "merge"))) {
                config.setString("branch", branch, "remote", remote);
                config.setString("branch", branch, "merge", "refs/heads/" + branch);
                try {
                    config.save();
                } catch (IOException e) {
                    LOGGER.error("Failed to configure the branch configuration to " + getRootGitDirectory(git)
                            + " with branch " + branch + " on remote repo: " + remote + ". " + e, e);
                }
            }
        }
    }

    static boolean equals(Object a, Object b) {
        return (a == b) || (a != null && a.equals(b));
    }

    /**
     * Returns the git branch of the given profile identity.
     */
    public static String getProfileBranch(String versionId, String profileId) {
        if (profileId != null && ENSEMBLE_PROFILE_PATTERN.matcher(profileId).matches()) {
            return "master";
        } else {
            return versionId;
        }
    }
}