Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2582,7 +2582,11 @@
exe = userGitExe + ".exe";
}

String[] pathDirs = System.getenv("PATH").split(File.pathSeparator);
String path = getEnvVar("PATH");
if (path == null) {

Check warning on line 2586 in src/main/java/org/jenkinsci/plugins/gitclient/CliGitAPIImpl.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 2586 is only partially covered, one branch is missing
path = "";

Check warning on line 2587 in src/main/java/org/jenkinsci/plugins/gitclient/CliGitAPIImpl.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered line

Line 2587 is not covered by tests
}
String[] pathDirs = path.split(File.pathSeparator);

for (String pathDir : pathDirs) {
File exeFile = new File(pathDir, exe);
Expand All @@ -2603,8 +2607,13 @@
return null;
}

/* Package protected for testing */
String getEnvVar(String envVar) {
return System.getenv(envVar);

Check warning on line 2612 in src/main/java/org/jenkinsci/plugins/gitclient/CliGitAPIImpl.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered line

Line 2612 is not covered by tests
}

private File getFileFromEnv(String envVar, String suffix) {
String envValue = System.getenv(envVar);
String envValue = getEnvVar(envVar);
if (envValue == null) {
return null;
}
Expand Down Expand Up @@ -2689,6 +2698,15 @@
}
}

// Check the system PATH last, the ssh of the git installation is preferred
String sshPath = getPathToExe("ssh");
if (sshPath != null) {
sshexe = new File(sshPath);
if (sshexe.exists()) {

Check warning on line 2705 in src/main/java/org/jenkinsci/plugins/gitclient/CliGitAPIImpl.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 2705 is only partially covered, one branch is missing
return sshexe;
}
}

throw new RuntimeException(
"ssh executable not found. The git plugin only supports official git client https://git-scm.com/download/win");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package org.jenkinsci.plugins.gitclient;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import org.jvnet.hudson.test.Issue;

/**
* Tests the order in which {@link CliGitAPIImpl#getSSHExecutable()} searches for ssh.
* The ssh of the git installation must be preferred over an ssh found on the system PATH.
*
* @author <a href="mailto:akash.manna.mymail@gmail.com">Akash Manna</a>
*/
class CliGitAPISshExecutableTest {

@TempDir
private File tempDir;

private CliGitAPIImpl gitClientWithEnv(String gitExe, Map<String, String> environmentVariables) {
return new CliGitAPIImpl(gitExe, tempDir, null, null) {
@Override
String getEnvVar(String envVar) {
return environmentVariables.get(envVar);
}
};
}

/* Paths are joined with a backslash, so on Unix the file name contains backslashes */
private File createExecutable(File executable) throws IOException {
File parent = executable.getParentFile();
if (parent != null) {
parent.mkdirs();
}
assertTrue(executable.createNewFile(), "Could not create " + executable);
return executable;
}

private File pathDirectoryWithSsh() throws IOException {
File pathDir = new File(tempDir, "path-dir");
pathDir.mkdirs();
createExecutable(new File(pathDir, "ssh.exe"));
return pathDir;
}

@Test
@Issue("JENKINS-1715")
void sshOfGitInstallationPreferredOverSshOnPath() throws Exception {
File programFiles = new File(tempDir, "Program Files");
File gitSsh = createExecutable(new File(programFiles + "\\Git\\bin\\ssh.exe"));

Map<String, String> env = new HashMap<>();
env.put("ProgramFiles", programFiles.getAbsolutePath());
env.put("PATH", pathDirectoryWithSsh().getAbsolutePath());

assertEquals(gitSsh, gitClientWithEnv("git", env).getSSHExecutable());
}

@Test
@Issue("JENKINS-1715")
void sshOfGitInstallationInUsrBinPreferredOverSshOnPath() throws Exception {
File programFiles = new File(tempDir, "Program Files");
File gitSsh = createExecutable(new File(programFiles + "\\Git\\usr\\bin\\ssh.exe"));

Map<String, String> env = new HashMap<>();
env.put("ProgramFiles", programFiles.getAbsolutePath());
env.put("PATH", pathDirectoryWithSsh().getAbsolutePath());

assertEquals(gitSsh, gitClientWithEnv("git", env).getSSHExecutable());
}

@Test
@Issue("JENKINS-1715")
void sshBesideGitExecutablePreferredOverSshOnPath() throws Exception {
File gitExe = new File(tempDir, "MinGit\\cmd\\git.exe");
File gitSsh = createExecutable(new File(gitExe.getParent() + "\\ssh.exe"));

Map<String, String> env = new HashMap<>();
env.put("PATH", pathDirectoryWithSsh().getAbsolutePath());

assertEquals(gitSsh, gitClientWithEnv(gitExe.getAbsolutePath(), env).getSSHExecutable());
}

@Test
@Issue("JENKINS-72450")
void sshOnPathUsedWhenGitInstallationHasNoSsh() throws Exception {
File pathDir = pathDirectoryWithSsh();

Map<String, String> env = new HashMap<>();
env.put("PATH", pathDir.getAbsolutePath());

assertEquals(
new File(pathDir, "ssh.exe"),
gitClientWithEnv(new File(tempDir, "no-ssh-here\\git.exe").getAbsolutePath(), env)
.getSSHExecutable());
}

@Test
@Issue("JENKINS-72450")
void gitSshEnvironmentVariablePreferredOverSshOnPath() throws Exception {
File gitSshVariable = createExecutable(new File(tempDir, "custom-ssh.exe"));

Map<String, String> env = new HashMap<>();
env.put("GIT_SSH", gitSshVariable.getAbsolutePath());
env.put("PATH", pathDirectoryWithSsh().getAbsolutePath());

assertEquals(gitSshVariable, gitClientWithEnv("git", env).getSSHExecutable());
}

@Test
void sshNotFoundReportsUnsupportedGitInstallation() {
Map<String, String> env = new HashMap<>();
env.put("PATH", new File(tempDir, "empty-dir").getAbsolutePath());

CliGitAPIImpl git = gitClientWithEnv(new File(tempDir, "no-ssh-here\\git.exe").getAbsolutePath(), env);
RuntimeException e = assertThrows(RuntimeException.class, git::getSSHExecutable);
assertTrue(e.getMessage().startsWith("ssh executable not found"), e.getMessage());
}
}