Skip to content
Browse files
[JENKINS-45771] Pick up consolidated MergeWithGitSCMExtension from gi…
…t plugin
  • Loading branch information
stephenc committed Jul 27, 2017
1 parent 9868e45 commit 3256676fa6a47d342a0442c59555df9eecde0b68
@@ -46,7 +46,7 @@
@@ -42,6 +42,7 @@
import java.util.Set;
import jenkins.plugins.git.AbstractGitSCMSource;
import jenkins.plugins.git.GitSCMBuilder;
import jenkins.plugins.git.MergeWithGitSCMExtension;
import jenkins.scm.api.SCMHead;
import jenkins.scm.api.SCMRevision;
import jenkins.scm.api.SCMSourceOwner;
@@ -29,7 +29,6 @@
import com.cloudbees.plugins.credentials.CredentialsProvider;
import com.cloudbees.plugins.credentials.common.StandardCredentials;
import com.cloudbees.plugins.credentials.common.StandardListBoxModel;
import edu.umd.cs.findbugs.annotations.CheckForNull;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
@@ -45,7 +44,6 @@
import hudson.model.Actionable;
import hudson.model.Item;
import hudson.model.TaskListener;
import hudson.plugins.git.GitSCM;
import hudson.plugins.git.extensions.GitSCMExtension;
import hudson.scm.SCM;
import hudson.util.FormValidation;
@@ -76,6 +74,7 @@
import javax.servlet.http.HttpServletResponse;
import jenkins.model.Jenkins;
import jenkins.plugins.git.AbstractGitSCMSource;
import jenkins.plugins.git.MergeWithGitSCMExtension;
import jenkins.plugins.git.traits.GitBrowserSCMSourceTrait;
import jenkins.scm.api.SCMHead;
import jenkins.scm.api.SCMHeadCategory;
@@ -34,94 +34,31 @@
import hudson.plugins.git.extensions.impl.PreBuildMerge;
import hudson.plugins.git.util.MergeRecord;
import org.apache.commons.lang.StringUtils;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.jenkinsci.plugins.gitclient.CheckoutCommand;
import org.jenkinsci.plugins.gitclient.GitClient;
import org.jenkinsci.plugins.gitclient.MergeCommand;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.DoNotUse;
import org.kohsuke.accmod.restrictions.NoExternalUse;

* Similar to {@link PreBuildMerge}, but we cannot use that unmodified: we need to specify the exact base branch
* hash. The hash is specified so that we are not subject to a race condition between the {@code baseHash} we think
* we are merging with and a possibly newer one that was just pushed.
* Retained for data migration.
* @since 2.2.0
* @deprecated use {@link jenkins.plugins.git.MergeWithGitSCMExtension}
public class MergeWithGitSCMExtension extends GitSCMExtension {
private final String baseName;
private final String baseHash;
public class MergeWithGitSCMExtension extends jenkins.plugins.git.MergeWithGitSCMExtension {

MergeWithGitSCMExtension(@NonNull String baseName, @CheckForNull String baseHash) {
this.baseName = baseName;
this.baseHash = baseHash;
super(baseName, baseHash);

public String getBaseName() {
return baseName;

public String getBaseHash() {
return baseHash;

public Revision decorateRevisionToBuild(GitSCM scm, Run<?, ?> build, GitClient git, TaskListener listener,
Revision marked, Revision rev)
throws IOException, InterruptedException, GitException {
ObjectId baseObjectId;
if (StringUtils.isBlank(baseHash)) {
try {
baseObjectId = git.revParse(Constants.R_REFS + baseName);
} catch (GitException e) {
listener.getLogger().printf("Unable to determine head revision of %s prior to merge with PR%n",
throw e;
} else {
baseObjectId = ObjectId.fromString(baseHash);
listener.getLogger().printf("Merging %s commit %s into PR head commit %s%n",
baseName,, rev.getSha1String()
checkout(scm, build, git, listener, rev);
try {
/* could parse out of JenkinsLocationConfiguration.get().getAdminAddress() but seems overkill */
git.setAuthor("Jenkins", "nobody@nowhere");
git.setCommitter("Jenkins", "nobody@nowhere");
MergeCommand cmd = git.merge().setRevisionToMerge(baseObjectId);
for (GitSCMExtension ext : scm.getExtensions()) {
// By default we do a regular merge, allowing it to fast-forward.
ext.decorateMergeCommand(scm, build, git, listener, cmd);
} catch (GitException x) {
// Try to revert merge conflict markers.
// TODO IGitAPI offers a reset(hard) method yet GitClient does not. Why?
checkout(scm, build, git, listener, rev);
// TODO would be nicer to throw an AbortException with just the message, but this is actually worse
// until git-client 1.19.7+
throw x;
new MergeRecord(baseName, baseObjectId.getName())); // does not seem to be used, but just in case
ObjectId mergeRev = git.revParse(Constants.HEAD);
listener.getLogger().println("Merge succeeded, producing " +;
return new Revision(mergeRev, rev.getBranches()); // note that this ensures Build.revision != Build.marked

private void checkout(GitSCM scm, Run<?, ?> build, GitClient git, TaskListener listener, Revision rev)
throws InterruptedException, IOException, GitException {
CheckoutCommand checkoutCommand = git.checkout().ref(rev.getSha1String());
for (GitSCMExtension ext : scm.getExtensions()) {
ext.decorateCheckoutCommand(scm, build, git, listener, checkoutCommand);
private Object readResolve() throws ObjectStreamException {
return new jenkins.plugins.git.MergeWithGitSCMExtension(getBaseName(), getBaseHash());
@@ -23,6 +23,7 @@
import jenkins.branch.BranchSource;
import jenkins.plugins.git.AbstractGitSCMSource;
import jenkins.plugins.git.GitSCMSourceDefaults;
import jenkins.plugins.git.MergeWithGitSCMExtension;
import jenkins.scm.api.SCMHead;
import jenkins.scm.api.SCMHeadOrigin;
import jenkins.scm.api.SCMRevision;

0 comments on commit 3256676

Please sign in to comment.