Skip to content

Commit

Permalink
Fixed 'go' Commands Issue in Windows Paths with Spaces (#772)
Browse files Browse the repository at this point in the history
  • Loading branch information
noyshabtay authored Dec 20, 2023
1 parent 302fecc commit c231897
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package org.jfrog.build.extractor.go;

import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.SystemUtils;
import org.jfrog.build.api.util.Log;
import org.jfrog.build.extractor.executor.CommandExecutor;
import org.jfrog.build.extractor.executor.CommandResults;
Expand All @@ -24,18 +26,60 @@ public class GoDriver implements Serializable {
private static final String GO_GET_CMD = "get";
private static final String GO_LIST_MODULE_CMD = "list -m";
private static final String GO_VERSION_CMD = "version";
private static final String DEFAULT_EXECUTABLE_NAME = "go";

private static final long serialVersionUID = 1L;
private final CommandExecutor commandExecutor;
private final File workingDirectory;
private final Log logger;

public GoDriver(String executablePath, Map<String, String> env, File workingDirectory, Log logger) {
this.commandExecutor = new CommandExecutor(StringUtils.defaultIfEmpty(executablePath, "go"), env);
this.commandExecutor = generateCommandExecutor(executablePath, env);
this.workingDirectory = workingDirectory;
this.logger = logger;
}

/**
* Generate a new mutable copy of environment variables map with the Go executable directory path inserted to the beginning of the Path.
*
* @param executablePath Go executable path
* @param env Environment variables map
* @return a new Environment variables map
*/
static Map<String, String> generateWindowsEnv(String executablePath, Map<String, String> env) {
// If executablePath ends with "go" or "go.exe" - remove it from the directory path
executablePath = StringUtils.removeEnd(executablePath, ".exe");
executablePath = StringUtils.removeEnd(executablePath, DEFAULT_EXECUTABLE_NAME);

// Insert the Go executable directory path to the beginning of the Path environment variable
// Make sure to copy the environment variables map to avoid changing the original map or in case it is immutable
Map<String, String> newEnv = Maps.newHashMap(env);
String windowsPathEnvKey = "Path";
if (newEnv.containsKey(windowsPathEnvKey)) {
newEnv.put(windowsPathEnvKey, executablePath + File.pathSeparator + newEnv.get(windowsPathEnvKey));
} else {
newEnv.put(windowsPathEnvKey, executablePath);
}
return newEnv;
}

/**
* Create a CommandExecutor with the given executable path and environment variables.
*
* @param executablePath Go executable path
* @param env Environment variables map
* @return CommandExecutor
*/
private static CommandExecutor generateCommandExecutor(String executablePath, Map<String, String> env) {
if (!SystemUtils.IS_OS_WINDOWS || StringUtils.isBlank(executablePath) || StringUtils.equals(executablePath, DEFAULT_EXECUTABLE_NAME) || env == null) {
return new CommandExecutor(StringUtils.defaultIfEmpty(executablePath, DEFAULT_EXECUTABLE_NAME), env);
}
// Handling Windows case with a given executable path:
// A bug was identified for the Go executable in Windows where the executable path may be incorrectly parsed
// as two command arguments when the path contains spaces (e.g., "C:\Program Files\Go\bin\go.exe").
return new CommandExecutor(DEFAULT_EXECUTABLE_NAME, generateWindowsEnv(executablePath, env));
}

public CommandResults runCmd(String args, boolean verbose) throws IOException {
List<String> argsList = new ArrayList<>(Arrays.asList(args.split(" ")));
return runCmd(argsList, verbose);
Expand Down Expand Up @@ -109,8 +153,9 @@ public void modTidy(boolean verbose, boolean ignoreErrors) throws IOException {

/**
* Run go get.
*
* @param componentId - Component ID string. ( Example: github.com/jfrog/[email protected] )
* @param verbose - True if should print the results to the log
* @param verbose - True if should print the results to the log
* @throws IOException - in case of any I/O error.
*/
public void get(String componentId, boolean verbose) throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

import com.google.common.collect.Sets;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.SystemUtils;
import org.jfrog.build.api.util.NullLog;
import org.jfrog.build.extractor.executor.CommandResults;
import org.testng.Assert;
import org.testng.SkipException;
import org.testng.annotations.Test;

import java.io.File;
Expand All @@ -13,6 +15,7 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -114,4 +117,20 @@ public void testGoGet() throws IOException {
FileUtils.deleteDirectory(projectDir);
}
}

@Test
public void testGoDriverWindowsInit() throws IOException {
if (!SystemUtils.IS_OS_WINDOWS) {
throw new SkipException("Skipping non-windows test");
}
File projectDir = Files.createTempDirectory("").toFile();
try {
Map<String, String> systemEnv = System.getenv();
String executablePath = "C:\\Program Files\\Go\\bin\\go";
Map<String, String> executorEnv = GoDriver.generateWindowsEnv(executablePath, systemEnv);
assertTrue(executorEnv.get("Path").startsWith("C:\\Program Files\\Go\\bin"));
} finally {
FileUtils.deleteDirectory(projectDir);
}
}
}

0 comments on commit c231897

Please sign in to comment.