Skip to content
Merged
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
4 changes: 2 additions & 2 deletions src/it/projects/envscript/src/build/env.sh
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
MY_ENV_SCRIPT_SET_A_VAR_TO=something
export MY_ENV_SCRIPT_SET_A_VAR_TO
#!/bin/sh
export MY_ENV_SCRIPT_SET_A_VAR_TO=something
43 changes: 38 additions & 5 deletions src/main/java/org/codehaus/mojo/exec/ExecMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
*/

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
Expand Down Expand Up @@ -277,9 +278,11 @@ public class ExecMojo extends AbstractExecMojo {
private Map<String, String> environmentVariables = new HashMap<>();

/**
* Environment script to be merged with <i>environmentVariables</i> This script is platform specifics, on Unix its
* must be Bourne shell format. Use this feature if you have a need to create environment variable dynamically such
* as invoking Visual Studio environment script file
* Environment script to be merged with <i>environmentVariables</i>. on Unix-like system if the script
* contains a shebang line, the executable filename is read from the shebang line; otherwise,
* Bourne shell format is used.
* Use this feature if you have a need to create environment variable dynamically such as invoking
* Visual Studio environment script file.
*
* @since 1.4.0
*/
Expand Down Expand Up @@ -1013,6 +1016,22 @@ private void createArgFile(String filePath, List<String> lines) throws IOExcepti
}
}

String getShebang(File script) {
if (script == null || !script.canRead()) {
getLog().warn("Cannot read script file " + script);
return null;
}
try (BufferedReader reader = Files.newBufferedReader(script.toPath())) {
String line = reader.readLine();
if (line != null && line.startsWith("#!")) {
return line.substring(2).trim();
}
} catch (IOException e) {
getLog().warn("Could not read shebang from " + script.getAbsolutePath(), e);
}
return null;
}

protected Map<String, String> createEnvs(File envScriptFile) throws MojoExecutionException {
Map<String, String> results = null;

Expand All @@ -1023,7 +1042,16 @@ protected Map<String, String> createEnvs(File envScriptFile) throws MojoExecutio
Commandline cl = new Commandline(); // commons-exec instead?
cl.setExecutable(tmpEnvExecFile.getAbsolutePath());
if (!OS.isFamilyWindows()) {
cl.setExecutable("sh");
String shebang = getShebang(envScriptFile);
if (shebang != null && !shebang.isEmpty()) {
String[] parts = shebang.split("\\s+");
cl.setExecutable(parts[0]);
for (int i = 1; i < parts.length; i++) {
cl.createArg().setValue(parts[i]);
}
} else {
cl.setExecutable("sh");
}
cl.createArg().setFile(tmpEnvExecFile);
}

Expand Down Expand Up @@ -1077,8 +1105,13 @@ protected File createEnvWrapperFile(File envScript) throws IOException {
} else {
tmpFile = Files.createTempFile("env", ".sh").toFile();
// tmpFile.setExecutable( true );//java 6 only
String shebang = getShebang(envScript);
try (PrintWriter writer = new PrintWriter(tmpFile)) {
writer.append("#! /bin/sh").println();
if (shebang != null && !shebang.isEmpty()) {
writer.append("#!").append(shebang).println();
} else {
writer.append("#!/bin/sh").println();
}
writer.append(". ").append(envScript.getCanonicalPath()).println(); // works on all unix??
writer.append("echo " + EnvStreamConsumer.START_PARSING_INDICATOR)
.println();
Expand Down
76 changes: 76 additions & 0 deletions src/test/java/org/codehaus/mojo/exec/ExecMojoTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -356,4 +356,80 @@ private String getCommandLineAsString(CommandLine commandline) {
}
return result;
}

public void testGetShebang() throws Exception {
ExecMojo execMojo = new ExecMojo();

// without shebang
File noShebang = Files.createTempFile("noShebang", ".sh").toFile();
Files.write(noShebang.toPath(), Arrays.asList("echo hello"), StandardCharsets.UTF_8);
assertNull(execMojo.getShebang(noShebang));
noShebang.delete();

// with shebang
File withShebang = Files.createTempFile("withShebang", ".sh").toFile();
Files.write(withShebang.toPath(), Arrays.asList("#!/bin/bash -x", "echo hello"), StandardCharsets.UTF_8);
assertEquals("/bin/bash -x", execMojo.getShebang(withShebang));
withShebang.delete();

// with shebang but no args
File withShebangNoArgs =
Files.createTempFile("withShebangNoArgs", ".sh").toFile();
Files.write(
withShebangNoArgs.toPath(),
Arrays.asList("#!/usr/bin/env python3", "print('hello')"),
StandardCharsets.UTF_8);
assertEquals("/usr/bin/env python3", execMojo.getShebang(withShebangNoArgs));
withShebangNoArgs.delete();
}

public void testCreateEnvWrapperFile() throws Exception {
ExecMojo execMojo = new ExecMojo();

// without shebang
File envScript = Files.createTempFile("envScript", ".sh").toFile();
Files.write(envScript.toPath(), Arrays.asList("export TEST_VAR=test_value"), StandardCharsets.UTF_8);
File wrapper = execMojo.createEnvWrapperFile(envScript);
List<String> lines = Files.readAllLines(wrapper.toPath(), StandardCharsets.UTF_8);

if (OS.isFamilyWindows()) {
assertEquals("@echo off", lines.get(0));
assertTrue(lines.get(1).startsWith("call \""));
assertTrue(lines.get(1).endsWith(envScript.getCanonicalPath() + "\""));
assertEquals("echo " + EnvStreamConsumer.START_PARSING_INDICATOR, lines.get(2));
assertEquals("set", lines.get(3));
} else {
assertEquals("#!/bin/sh", lines.get(0));
assertEquals(". " + envScript.getCanonicalPath(), lines.get(1));
assertEquals("echo " + EnvStreamConsumer.START_PARSING_INDICATOR, lines.get(2));
assertEquals("env", lines.get(3));
}
wrapper.delete();
envScript.delete();

// with shebang
File envScriptWithShebang =
Files.createTempFile("envScriptWithShebang", ".sh").toFile();
Files.write(
envScriptWithShebang.toPath(),
Arrays.asList("#!/bin/bash", "export TEST_VAR=test_value"),
StandardCharsets.UTF_8);
File wrapper2 = execMojo.createEnvWrapperFile(envScriptWithShebang);
List<String> lines2 = Files.readAllLines(wrapper2.toPath(), StandardCharsets.UTF_8);

if (OS.isFamilyWindows()) {
assertEquals("@echo off", lines2.get(0));
assertTrue(lines2.get(1).startsWith("call \""));
assertTrue(lines2.get(1).endsWith(envScriptWithShebang.getCanonicalPath() + "\""));
assertEquals("echo " + EnvStreamConsumer.START_PARSING_INDICATOR, lines2.get(2));
assertEquals("set", lines2.get(3));
} else {
assertEquals("#!/bin/bash", lines2.get(0));
assertEquals(". " + envScriptWithShebang.getCanonicalPath(), lines2.get(1));
assertEquals("echo " + EnvStreamConsumer.START_PARSING_INDICATOR, lines2.get(2));
assertEquals("env", lines2.get(3));
}
wrapper2.delete();
envScriptWithShebang.delete();
}
}
Loading