Skip to content
Permalink
Browse files

[Fixed JENKINS-21806] Improve ssh.exe finding on Windows with msysgit

Adapt to msysgit installed in non-default locations, and to msysgit
alternative configurations as allowed by the msysgit installer.  The
mssygit installer allows the user to choose to make no changes to the
PATH, or to add the "cmd" directory to the PATH, or add the "bin"
directory to the PATH.

If the user chooses to make no changes to the PATH, then they
configure their Jenkins git with the absolute path of the git
executable.

If the user chooses to add the "cmd" directory to the PATH, then they
configure their Jenkins git with the executable as "git", "git.exe",
or (with some msysgit versions) "git.cmd".

If the user chooses to add the "bin" directory to the PATH, then they
configure similarly to the "cmd" directory case.

The plugin attempts to handle all those cases correctly.

Special thanks to Thiago Zanetti for providing the original code for
this fix.
  • Loading branch information...
MarkEWaite committed Jul 15, 2014
1 parent 824d028 commit 9430af74220cc9a11dd5e523332c0f5006cbafdd
@@ -1258,26 +1258,99 @@ private File createUnixSshAskpass(SSHUserPrivateKey sshUser) throws IOException
return ssh;
}

private String getPathToExe(String userGitExe) {
userGitExe = userGitExe.toLowerCase();

String cmd;
String exe;
if (userGitExe.endsWith(".exe")) {
cmd = userGitExe.replace(".exe", ".cmd");
exe = userGitExe;
} else if (userGitExe.endsWith(".cmd")) {
cmd = userGitExe;
exe = userGitExe.replace(".cmd", ".exe");
} else {
cmd = userGitExe + ".cmd";
exe = userGitExe + ".exe";
}

private File createWindowsGitSSH(File key) throws IOException {
File ssh = File.createTempFile("ssh", ".bat");
// windows git installer place C:\Program Files\Git\cmd\git.exe in PATH

String progFiles = System.getenv("ProgramFiles");
String sshPath = "/Git/bin/ssh.exe";
File sshexe = new File(progFiles + sshPath);
if (!sshexe.exists()) {
// try the (x86) version for 64-bit Windows builds
sshexe = new File(progFiles + " (x86)" + sshPath);
String[] pathDirs = System.getenv("PATH").split(File.pathSeparator);

for (String pathDir : pathDirs) {
File exeFile = new File(pathDir, exe);
if (exeFile.exists()) {
return exeFile.getAbsolutePath();
}
File cmdFile = new File(pathDir, cmd);
if (cmdFile.exists()) {
return cmdFile.getAbsolutePath();
}
}

return null;
}

private File getFileFromEnv(String envVar, String suffix) {
String envValue = System.getenv(envVar);
if (envValue == null) {
return null;
}
if (!sshexe.exists()) {
// try the ssh.exe next to known git.exe
sshexe = new File(new File(gitExe).getParentFile(), "ssh.exe");
return new File(envValue + suffix);
}

private File getSSHExeFromGitExeParentDir(String userGitExe) {
String parentPath = new File(userGitExe).getParent();
if (parentPath == null) {
return null;
}
return new File(parentPath + "\\ssh.exe");
}

if (!sshexe.exists()) {
throw new RuntimeException("git plugin only support official git client http://git-scm.com/download/win");
/* package */ File getSSHExecutable() {
// First check the GIT_SSH environment variable
File sshexe = getFileFromEnv("GIT_SSH", "");
if (sshexe != null && sshexe.exists()) {
return sshexe;
}

// Check Program Files
sshexe = getFileFromEnv("ProgramFiles", "\\Git\\bin\\ssh.exe");
if (sshexe != null && sshexe.exists()) {
return sshexe;
}

// Check Program Files(x86) for 64 bit computer
sshexe = getFileFromEnv("ProgramFiles(x86)", "\\Git\\bin\\ssh.exe");
if (sshexe != null && sshexe.exists()) {
return sshexe;
}

// Search for an ssh.exe near the git executable.
sshexe = getSSHExeFromGitExeParentDir(gitExe);
if (sshexe != null && sshexe.exists()) {
return sshexe;
}

// Search for git on the PATH, then look near it
String gitPath = getPathToExe(gitExe);
if (gitPath != null) {
// In case we are using msysgit from the cmd directory
// instead of the bin directory, replace cmd with bin in
// the path while trying to find ssh.exe.
sshexe = getSSHExeFromGitExeParentDir(gitPath.replace("/cmd/", "/bin/").replace("\\cmd\\", "\\bin\\"));
if (sshexe != null && sshexe.exists()) {
return sshexe;
}
}

throw new RuntimeException("ssh executable not found. The git plugin only supports official git client http://git-scm.com/download/win");
}

private File createWindowsGitSSH(File key) throws IOException {
File ssh = File.createTempFile("ssh", ".bat");

File sshexe = getSSHExecutable();

PrintWriter w = new PrintWriter(ssh);
w .println("@echo off");
w .println("\"" + sshexe.getAbsolutePath() + "\" -i \"" + key.getAbsolutePath() +"\" -o StrictHostKeyChecking=no %* ");
@@ -2619,4 +2619,14 @@ public void test_longpaths_disabled() throws Exception {
w.cmd("git config --add core.longpaths false");
check_longpaths(false);
}

@NotImplementedInJGit
/* Not implemented in JGit because it is not needed there */
public void test_git_ssh_executable_found_on_windows() throws Exception {
if (!SystemUtils.IS_OS_WINDOWS) {
return;
}

assertTrue("ssh.exe not found", w.cgit().getSSHExecutable().exists());
}
}

1 comment on commit 9430af7

@thiagozanetti

This comment has been minimized.

Copy link

commented on 9430af7 Jul 15, 2014

As you can see, Java is not my real deal. :) I'll checkout this version and try it here. Thanks!

Please sign in to comment.
You can’t perform that action at this time.