diff --git a/pom.xml b/pom.xml
index 0fe50a1c28..11e37a54df 100644
--- a/pom.xml
+++ b/pom.xml
@@ -26,6 +26,8 @@
6
2
+ 128m
+ -XX:MaxPermSize=${permgen.size}
false
1.14.2
@@ -175,6 +177,18 @@
1.10.19
test
+
+ org.powermock
+ powermock-module-junit4
+ 1.6.2
+ test
+
+
+ org.powermock
+ powermock-api-mockito
+ 1.6.2
+ test
+
org.apache.httpcomponents
httpclient
diff --git a/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java b/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java
index c4f5a2d086..8d2ae9273b 100644
--- a/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java
+++ b/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java
@@ -39,6 +39,7 @@
import hudson.plugins.git.BranchSpec;
import hudson.plugins.git.GitException;
import hudson.plugins.git.GitSCM;
+import hudson.plugins.git.GitTool;
import hudson.plugins.git.Revision;
import hudson.plugins.git.SubmoduleConfig;
import hudson.plugins.git.UserRemoteConfig;
@@ -148,6 +149,16 @@ public String getRemoteName() {
return "origin";
}
+ @CheckForNull
+ protected GitTool resolveGitTool() {
+ GitTool tool = Jenkins.getInstance().getDescriptorByType(GitTool.DescriptorImpl.class)
+ .getInstallation(getGitTool());
+ if (getGitTool() == null) {
+ tool = GitTool.getDefaultInstallation();
+ }
+ return tool;
+ }
+
@CheckForNull
@Override
protected SCMRevision retrieve(@NonNull SCMHead head, @NonNull TaskListener listener)
@@ -157,7 +168,8 @@ protected SCMRevision retrieve(@NonNull SCMHead head, @NonNull TaskListener list
cacheLock.lock();
try {
File cacheDir = getCacheDir(cacheEntry);
- Git git = Git.with(listener, new EnvVars(EnvVars.masterEnvVars)).in(cacheDir);
+ GitTool tool = resolveGitTool();
+ Git git = Git.with(listener, new EnvVars(EnvVars.masterEnvVars)).using(tool.getGitExe()).in(cacheDir);
GitClient client = git.getClient();
client.addDefaultCredentials(getCredentials());
if (!client.hasGitRepo()) {
@@ -193,7 +205,8 @@ protected void retrieve(@NonNull final SCMHeadObserver observer,
cacheLock.lock();
try {
File cacheDir = getCacheDir(cacheEntry);
- Git git = Git.with(listener, new EnvVars(EnvVars.masterEnvVars)).in(cacheDir);
+ GitTool tool = resolveGitTool();
+ Git git = Git.with(listener, new EnvVars(EnvVars.masterEnvVars)).using(tool.getGitExe()).in(cacheDir);
GitClient client = git.getClient();
client.addDefaultCredentials(getCredentials());
if (!client.hasGitRepo()) {
diff --git a/src/test/java/jenkins/plugins/git/AbstractGitSCMSourceRetrieveHeadsTest.java b/src/test/java/jenkins/plugins/git/AbstractGitSCMSourceRetrieveHeadsTest.java
new file mode 100644
index 0000000000..88e492f8c9
--- /dev/null
+++ b/src/test/java/jenkins/plugins/git/AbstractGitSCMSourceRetrieveHeadsTest.java
@@ -0,0 +1,129 @@
+package jenkins.plugins.git;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.List;
+
+import hudson.FilePath;
+import hudson.model.TaskListener;
+import hudson.plugins.git.GitTool;
+import jenkins.scm.api.SCMHead;
+import jenkins.scm.api.SCMHeadObserver;
+import org.eclipse.jgit.transport.RefSpec;
+import org.jenkinsci.plugins.gitclient.Git;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+/**
+ * Tests for {@link AbstractGitSCMSource}
+ */
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(Git.class)
+public class AbstractGitSCMSourceRetrieveHeadsTest {
+
+ public static final String EXPECTED_GIT_EXE = "git-custom";
+
+ private AbstractGitSCMSource gitSCMSource;
+
+ @Before
+ public void setup() throws Exception {
+ // Mock GitTool
+ GitTool mockedTool = PowerMockito.mock(GitTool.class, Mockito.RETURNS_DEFAULTS);
+ PowerMockito.doReturn(EXPECTED_GIT_EXE).when(mockedTool).getGitExe();
+
+ // Mock git implementation
+ Git git = Mockito.mock(Git.class, Mockito.CALLS_REAL_METHODS);
+ PowerMockito.doThrow(new GitToolSpecified()).when(git).using(EXPECTED_GIT_EXE);
+ PowerMockito.doThrow(new GitToolNotSpecified()).when(git).getClient();
+ PowerMockito.doReturn(git).when(git).in(Mockito.any(File.class));
+ PowerMockito.doReturn(git).when(git).in(Mockito.any(FilePath.class));
+
+ // mock static factory to return our git mock
+ PowerMockito.mockStatic(Git.class, Mockito.CALLS_REAL_METHODS);
+ PowerMockito.doReturn(git).when(Git.class, "with", Mockito.any(), Mockito.any());
+
+ // Partial mock our AbstractGitSCMSourceImpl
+ gitSCMSource = PowerMockito.spy(new AbstractGitSCMSourceImpl());
+ // Always resolve to mocked GitTool
+ PowerMockito.doReturn(mockedTool).when(gitSCMSource).resolveGitTool();
+ }
+
+ /**
+ * Validate that the correct git installation is used when fetching latest heads.
+ * That means {@link Git#using(String)} is called properly.
+ */
+ @Test(expected = GitToolSpecified.class)
+ public void correctGitToolIsUsed() throws Exception {
+ try {
+ // Should throw exception confirming that Git#using was used correctly
+ gitSCMSource.retrieve(new SCMHead("master"), TaskListener.NULL);
+ } catch (GitToolNotSpecified e) {
+ Assert.fail("Git client was constructed wirth arbitrary git tool");
+ }
+ }
+
+ /**
+ * Validate that the correct git installation is used when fetching latest heads.
+ * That means {@link Git#using(String)} is called properly.
+ */
+ @Test(expected = GitToolSpecified.class)
+ public void correctGitToolIsUsed2() throws Exception {
+ try {
+ // Should throw exception confirming that Git#using was used correctly
+ gitSCMSource.retrieve(PowerMockito.mock(SCMHeadObserver.class), TaskListener.NULL);
+ } catch (GitToolNotSpecified e) {
+ Assert.fail("Git client was constructed with arbitrary git tool");
+ }
+ }
+
+ public static class GitToolSpecified extends RuntimeException {
+
+ }
+
+ public static class GitToolNotSpecified extends RuntimeException {
+
+ }
+
+ public static class AbstractGitSCMSourceImpl extends AbstractGitSCMSource {
+
+ public AbstractGitSCMSourceImpl() {
+ super("AbstractGitSCMSourceImpl-id");
+ }
+
+ @Override
+ public String getGitTool() {
+ return "EXPECTED_GIT_EXE";
+ }
+
+ @Override
+ public String getCredentialsId() {
+ return "";
+ }
+
+ @Override
+ public String getRemote() {
+ return "";
+ }
+
+ @Override
+ public String getIncludes() {
+ return "";
+ }
+
+ @Override
+ public String getExcludes() {
+ return "";
+ }
+
+ @Override
+ protected List getRefSpecs() {
+ return Collections.emptyList();
+ }
+ }
+}