hudson.plugins.git.util.DefaultBuildChooser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of git Show documentation
Show all versions of git Show documentation
Integrates Hudson with GIT SCM
The newest version!
/*******************************************************************************
*
* Copyright (c) 2011 Oracle Corporation.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*
* Andrew Bayer, Anton Kozak, Nikita Levyankov
*
*******************************************************************************/
package hudson.plugins.git.util;
import hudson.Extension;
import hudson.model.TaskListener;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.Set;
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 org.eclipse.jgit.lib.ObjectId;
import org.kohsuke.stapler.DataBoundConstructor;
import static java.util.Collections.emptyList;
public class DefaultBuildChooser extends BuildChooser {
@DataBoundConstructor
public DefaultBuildChooser() {
}
/**
* Determines which Revisions to build.
*
* If only one branch is chosen and only one repository is listed, then
* just attempt to find the latest revision number for the chosen branch.
*
* If multiple branches are selected or the branches include wildcards, then
* use the advanced usecase as defined in the getAdvancedCandidateRevisons
* method.
*
* @throws IOException
* @throws GitException
*/
public Collection getCandidateRevisions(boolean isPollCall, String singleBranch,
IGitAPI git, TaskListener listener, BuildData data)
throws GitException, IOException {
verbose(listener, "getCandidateRevisions({0},{1},,,{2}) considering branches to build", isPollCall,
singleBranch, data);
// if the branch name contains more wildcards then the simple usecase
// does not apply and we need to skip to the advanced usecase
if (singleBranch == null || singleBranch.contains("*")) {
return getAdvancedCandidateRevisions(isPollCall, listener, new GitUtils(listener, git), data);
}
// check if we're trying to build a specific commit
// this only makes sense for a build, there is no
// reason to poll for a commit
if (!isPollCall && singleBranch.matches("[0-9a-f]{6,40}")) {
try {
ObjectId sha1 = git.revParse(singleBranch);
Revision revision = new Revision(sha1);
revision.getBranches().add(new Branch("detached", sha1));
verbose(listener, "Will build the detached SHA1 {0}", sha1);
return Collections.singletonList(revision);
} catch (GitException e) {
// revision does not exist, may still be a branch
// for example a branch called "badface" would show up here
verbose(listener, "Not a valid SHA1 {0}", singleBranch);
}
}
// if it doesn't contain '/' then it could be either a tag or an unqualified branch
if (!singleBranch.contains("/")) {
// the 'branch' could actually be a tag:
Set tags = git.getTagNames(singleBranch);
if (tags.size() == 0) {
// its not a tag, so lets fully qualify the branch
String repository = gitSCM.getRepositories().get(0).getName();
singleBranch = repository + "/" + singleBranch;
verbose(listener, "{0} is not a tag. Qualifying with the repository {1} a a branch", singleBranch,
repository);
}
}
try {
ObjectId sha1 = git.revParse(singleBranch);
verbose(listener, "rev-parse {0} -> {1}", singleBranch, sha1);
// if polling for changes don't select something that has
// already been built as a build candidate
if (isPollCall && data.hasBeenBuilt(sha1)) {
verbose(listener, "{0} has already been built", sha1);
return emptyList();
}
verbose(listener, "Found a new commit {0} to be built on {1}", sha1, singleBranch);
Revision revision = new Revision(sha1);
revision.getBranches().add(new Branch(singleBranch, sha1));
return Collections.singletonList(revision);
} catch (GitException e) {
// branch does not exist, there is nothing to build
verbose(listener, "Failed to rev-parse: {0}", singleBranch);
return emptyList();
}
}
/**
* In order to determine which Revisions to build.
*
* Does the following :
* 1. Find all the branch revisions
* 2. Filter out branches that we don't care about from the revisions.
* Any Revisions with no interesting branches are dropped.
* 3. Get rid of any revisions that are wholly subsumed by another
* revision we're considering.
* 4. Get rid of any revisions that we've already built.
*
* NB: Alternate BuildChooser implementations are possible - this
* may be beneficial if "only 1" branch is to be built, as much of
* this work is irrelevant in that usecase.
*
* @throws IOException
* @throws GitException
*/
private Collection getAdvancedCandidateRevisions(boolean isPollCall, TaskListener listener,
GitUtils utils, BuildData data)
throws GitException, IOException {
// 1. Get all the (branch) revisions that exist
Collection revs = utils.getAllBranchRevisions();
verbose(listener, "Starting with all the branches: {0}", revs);
// 2. Filter out any revisions that don't contain any branches that we
// actually care about (spec)
for (Iterator i = revs.iterator(); i.hasNext();) {
Revision r = i.next();
// filter out uninteresting branches
for (Iterator j = r.getBranches().iterator(); j.hasNext();) {
Branch b = j.next();
boolean keep = false;
for (BranchSpec bspec : gitSCM.getBranches()) {
if (bspec.matches(b.getName())) {
keep = true;
break;
}
}
if (!keep) {
verbose(listener, "Ignoring {0} because it doesn't match branch specifier", b);
j.remove();
}
}
if (r.getBranches().size() == 0) {
verbose(listener, "Ignoring {0} because we don't care about any of the branches that point to it", r);
i.remove();
}
}
verbose(listener, "After branch filtering: {0}", revs);
// 3. We only want 'tip' revisions
revs = utils.filterTipBranches(revs);
verbose(listener, "After non-tip filtering: {0}", revs);
// 4. Finally, remove any revisions that have already been built.
verbose(listener, "Removing what's already been built: {0}", data.getBuildsByBranchName());
for (Iterator i = revs.iterator(); i.hasNext();) {
Revision r = i.next();
if (data.hasBeenBuilt(r.getSha1())) {
i.remove();
}
}
verbose(listener, "After filtering out what's already been built: {0}", revs);
// if we're trying to run a build (not an SCM poll) and nothing new
// was found then just run the last build again
if (!isPollCall && revs.isEmpty() && data.getLastBuiltRevision() != null) {
if (!utils.git.isCommitInRepo(data.getLastBuiltRevision().getSha1String())) {
return revs;
}
verbose(listener, "Nothing seems worth building, so falling back to the previously built revision: {0}",
data.getLastBuiltRevision());
return Collections.singletonList(data.getLastBuiltRevision());
}
return revs;
}
/**
* Write the message to the listener only when the verbose mode is on.
*/
private void verbose(TaskListener listener, String format, Object... args) {
if (GitSCM.VERBOSE) {
listener.getLogger().println(MessageFormat.format(format, args));
}
}
@Extension
public static final class DescriptorImpl extends BuildChooserDescriptor {
@Override
public String getDisplayName() {
return "Default";
}
@Override
public String getLegacyId() {
return "Default";
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy