Package hudson.plugins.git.util

Source Code of hudson.plugins.git.util.GitUtils

package hudson.plugins.git.util;

import hudson.EnvVars;
import hudson.FilePath;
import hudson.Launcher;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.BuildListener;
import hudson.model.Environment;
import hudson.model.Hudson;
import hudson.model.Node;
import hudson.model.ParametersAction;
import hudson.model.StreamBuildListener;
import hudson.model.TaskListener;
import hudson.plugins.git.Branch;
import hudson.plugins.git.BranchSpec;
import hudson.plugins.git.GitException;
import hudson.plugins.git.GitSCM;
import hudson.plugins.git.IGitAPI;
import hudson.plugins.git.Revision;
import hudson.slaves.NodeProperty;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.transport.RemoteConfig;

public class GitUtils {

    public static final String DEFAULD_REPO_NAME = Constants.DEFAULT_REMOTE_NAME;

    IGitAPI git;
    TaskListener listener;

    public GitUtils(TaskListener listener, IGitAPI git) {
        this.git = git;
        this.listener = listener;
    }

    /**
     * Return a list of "Revisions" - where a revision knows about all the branch names that refer to
     * a SHA1.
     *
     * @return
     * @throws IOException
     * @throws GitException
     */
    public Collection<Revision> getAllBranchRevisions() throws GitException, IOException {
        Map<ObjectId, Revision> revisions = new HashMap<ObjectId, Revision>();
        List<Branch> branches = git.getRemoteBranches();
        for (Branch b : branches) {
            Revision r = revisions.get(b.getSHA1());
            if (r == null) {
                r = new Revision(b.getSHA1());
                revisions.put(b.getSHA1(), r);
            }
            r.getBranches().add(b);
        }
        return revisions.values();
    }

    /**
     * Return the revision containing the branch name.
     *
     * @param branchName
     * @return
     * @throws IOException
     * @throws GitException
     */
    public Revision getRevisionContainingBranch(String branchName) throws GitException, IOException {
        for (Revision revision : getAllBranchRevisions()) {
            for (Branch b : revision.getBranches()) {
                if (b.getName().equals(branchName)) {
                    return revision;
                }
            }
        }
        return null;
    }

    public Revision getRevisionForSHA1(ObjectId sha1) throws GitException, IOException {
        for (Revision revision : getAllBranchRevisions()) {
            if (revision.getSha1().equals(sha1)) {
                return revision;
            }
        }
        return null;
    }

    /**
     * Return a list of 'tip' branches (I.E. branches that aren't included entirely within another branch).
     *
     * @param git
     * @return
     */
    public Collection<Revision> filterTipBranches(Collection<Revision> revisions) {
        // If we have 3 branches that we might want to build
        // ----A--.---.--- B
        //        \-----C

        // we only want (B) and (C), as (A) is an ancestor (old).

        List<Revision> l = new ArrayList<Revision>(revisions);

        OUTER:
        for (int i = 0; i < l.size(); i++) {
            for (int j = i + 1; j < l.size(); j++) {
                Revision ri = l.get(i);
                Revision rj = l.get(j);
                ObjectId commonAncestor = git.mergeBase(ri.getSha1(), rj.getSha1());
                if (commonAncestor == null) {
                    continue;
                }

                if (commonAncestor.equals(ri.getSha1())) {
                    LOGGER.fine("filterTipBranches: " + rj + " subsumes " + ri);
                    l.remove(i);
                    i--;
                    continue OUTER;
                }
                if (commonAncestor.equals(rj.getSha1())) {
                    LOGGER.fine("filterTipBranches: " + ri + " subsumes " + rj);
                    l.remove(j);
                    j--;
                }
            }
        }

        return l;
    }

    /**
     * An attempt to generate at least semi-useful EnvVars for polling calls, based on previous build.
     * Cribbed from various places.
     */
    public static EnvVars getPollEnvironment(AbstractProject p, FilePath ws, Launcher launcher, TaskListener listener)
        throws IOException, InterruptedException {
        EnvVars env;

        AbstractBuild b = (AbstractBuild) p.getLastBuild();

        if (b != null) {
            Node lastBuiltOn = b.getBuiltOn();

            if (lastBuiltOn != null) {
                env = lastBuiltOn.toComputer().getEnvironment().overrideAll(b.getCharacteristicEnvVars());
            } else {
                env = new EnvVars(System.getenv());
            }

            String rootUrl = Hudson.getInstance().getRootUrl();
            if (rootUrl != null) {
                env.put("HUDSON_URL", rootUrl);
                env.put("BUILD_URL", rootUrl + b.getUrl());
                env.put("JOB_URL", rootUrl + p.getUrl());
            }

            if (!env.containsKey("HUDSON_HOME")) {
                env.put("HUDSON_HOME", Hudson.getInstance().getRootDir().getPath());
            }

            if (ws != null) {
                env.put("WORKSPACE", ws.getRemote());
            }


            p.getScm().buildEnvVars(b, env);

            StreamBuildListener buildListener = new StreamBuildListener((OutputStream) listener.getLogger());

            for (NodeProperty nodeProperty : Hudson.getInstance().getGlobalNodeProperties()) {
                Environment environment = nodeProperty.setUp(b, launcher, (BuildListener) buildListener);
                if (environment != null) {
                    environment.buildEnvVars(env);
                }
            }

            if (lastBuiltOn != null) {
                for (NodeProperty nodeProperty : lastBuiltOn.getNodeProperties()) {
                    Environment environment = nodeProperty.setUp(b, launcher, buildListener);
                    if (environment != null) {
                        environment.buildEnvVars(env);
                    }
                }
            }

            EnvVars.resolve(env);
        } else {
            env = new EnvVars(System.getenv());
        }

        return env;
    }

    /**
     * Builds branch envvars. If several branches or repos are present, env key will be generated based on pattern:
     * GIT_BRANCH_$repoIdx_$branchIdx. If there is only one branch and repo - {@link GitSCM#GIT_BRANCH} will be used.
     *
     * @param build {@link AbstractBuild}
     * @param env environment variables.
     * @param repositories list of repos.
     * @param branches list of {@link BranchSpec}
     */
    public static void buildBranchEnvVar(AbstractBuild<?, ?> build, Map<String, String> env,
                                         List<RemoteConfig> repositories, List<BranchSpec> branches) {
        if (CollectionUtils.isNotEmpty(repositories) && CollectionUtils.isNotEmpty(branches)) {
            int branchesSize = branches.size();
            int repoSize = repositories.size();
            if (1 == branchesSize && 1 == repoSize) {
                String branch = getSingleBranch(build, repositories, branches);
                if (branch != null) {
                    env.put(GitSCM.GIT_BRANCH, branch);
                }
            } else if (branchesSize > 1 || repoSize > 1) {
                int repoIdx = 1;
                int branchIdx = 1;
                for (RemoteConfig repo : repositories) {
                    for (BranchSpec branchSpec : branches) {
                        // replace repository wildcard with repository name
                        String branchName = buildBranch(build, repo.getName(), branchSpec.getName());
                        if (null != branchName) {
                            String key = GitSCM.GIT_BRANCH + "_" + repoIdx + "_" + branchIdx;
                            env.put(key, repo.getName() + "/" + branchName);
                            branchIdx++;
                        }
                    }
                    repoIdx++;
                    branchIdx = 1;
                }
            }
        }
    }

    /**
     * If the configuration is such that we are tracking just one branch of one repository
     * return that branch specifier (in the form of something like "origin/master"
     * <p/>
     * Otherwise return null.
     */
    public static String getSingleBranch(AbstractBuild<?, ?> build, List<RemoteConfig> repositories,
                                         List<BranchSpec> branches) {
        // if we have multiple branches skip to advanced usecase
        if (branches.size() != 1 || repositories.size() != 1) {
            return null;
        }

        String branch = branches.get(0).getName();
        String repository = repositories.get(0).getName();
        return buildBranch(build, repository, branch);
    }

    /**
     * Builds branch based on params.Applied build params if any. Returns null if branch contains *,
     *
     * @param build {@link AbstractBuild}
     * @param repository repo name
     * @param branchName branch name
     * @return branch name
     */
    public static String buildBranch(AbstractBuild<?, ?> build, String repository, String branchName) {
        // replace repository wildcard with repository name
        if (branchName.startsWith("*/")) {
            branchName = repository + branchName.substring(1);
        }

        // if the branchName name contains more wildcards then the simple usecase
        // does not apply and we need to skip to the advanced usecase
        if (branchName.contains("*")) {
            return null;
        }

        // substitute build parameters if available
        ParametersAction parameters = build.getAction(ParametersAction.class);
        if (parameters != null) {
            branchName = parameters.substitute(build, branchName);
        }
        return branchName;
    }

    public static String[] fixupNames(String[] names, String[] urls) {
        String[] returnNames = new String[urls.length];
        Set<String> usedNames = new HashSet<String>();

        for (int i = 0; i < urls.length; i++) {
            String name = names[i];

            if (name == null || name.trim().length() == 0) {
                name = DEFAULD_REPO_NAME;
            }

            String baseName = name;
            int j = 1;
            while (usedNames.contains(name)) {
                name = baseName + (j++);
            }

            usedNames.add(name);
            returnNames[i] = name;
        }


        return returnNames;
    }

    /**
     * Verifies whether array of the repository Urls is empty.
     *
     * @param urls repository Urls.
     * @return true if array is empty.
     */
    public static boolean isEmpty(String[] urls) {
        if (ArrayUtils.isEmpty(urls)) {
            return true;
        }
        for (String url : urls) {
            if (StringUtils.isNotEmpty(url)) {
                return false;
            }
        }
        return true;
    }

    /**
     * Verifies if first collection equals second without ordering.
     * @param c1 collection
     * @param c2 collection
     * @return true if collections equal.
     */
    public static boolean isEqualCollection(Collection c1, Collection c2) {
        if (c1 == c2) {
            return true;
        }
        if (c1 == null && c2 == null) {
            return true;
        }
        if (c1 == null || c2 == null) {
            return false;
        }
        return CollectionUtils.isEqualCollection(c1, c2);
    }

    /**
     * Verifies if first array equals second without ordering.
     * @param o1 array
     * @param o2 array
     * @return true if arrays equal.
     */
    public static boolean isEqualArray(Object[] o1, Object[] o2) {
        if (o1 == o2) {
            return true;
        }
        if (o1 == null && o2 == null) {
            return true;
        }
        if (o1 == null || o2 == null) {
            return false;
        }
        return CollectionUtils.isEqualCollection(Arrays.asList(o1), Arrays.asList(o2));
    }

    private static final Logger LOGGER = Logger.getLogger(GitUtils.class.getName());
}
TOP

Related Classes of hudson.plugins.git.util.GitUtils

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.