Skip to content

Commit

Permalink
Adds a run system command in a path macro and fixes existing docu
Browse files Browse the repository at this point in the history
Signed-off-by: Juergen Albert <j.albert@data-in-motion.biz>
  • Loading branch information
juergen-albert committed Aug 30, 2024
1 parent 38272cf commit 36e63cd
Show file tree
Hide file tree
Showing 7 changed files with 197 additions and 137 deletions.
80 changes: 80 additions & 0 deletions biz.aQute.bndlib.tests/test/test/MacroTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.junit.jupiter.api.condition.EnabledForJreRange;
import org.junit.jupiter.api.condition.EnabledOnOs;
import org.junit.jupiter.api.condition.JRE;
import org.junit.jupiter.api.condition.OS;

import aQute.bnd.osgi.About;
import aQute.bnd.osgi.Analyzer;
Expand Down Expand Up @@ -1376,6 +1377,85 @@ public void testSystemAllowFail() throws Exception {
}
}

@Test
@DisabledOnOs(WINDOWS)
public void testSystemInPath() throws Exception {
try (Processor p = new Processor()) {
Macro macro = new Macro(p);
assertEquals("/tmp", macro.process("${system-in-path;/tmp;pwd}"));
} catch (IOException e) {
fail(e);
}
}

@Test
@DisabledOnOs({
OS.MAC, OS.LINUX
})
public void testSystemInPathWindows() throws Exception {
try (Processor p = new Processor()) {
Macro macro = new Macro(p);
assertEquals("c:\\", macro.process("${system-in-path;c:/;echo %cd%}"));
} catch (IOException e) {
fail(e);
}
}

@Test
@DisabledOnOs(WINDOWS)
/**
* Verify system-allow-fail command
*/
public void testSystemInPathAllowFailWorks() throws Exception {
try (Processor p = new Processor()) {
Macro macro = new Macro(p);
assertEquals("/tmp", macro.process("${system-in-path-allow-fail;/tmp;pwd}"));
} catch (IOException e) {
fail(e);
}
}

@Test
@DisabledOnOs({
OS.MAC, OS.LINUX
})
public void testSystemInPathWindowsAllowFailWorks() throws Exception {
try (Processor p = new Processor()) {
Macro macro = new Macro(p);
assertEquals("c:\\", macro.process("${system-in-path-allow-fail;c:/;echo %cd%}"));
} catch (IOException e) {
fail(e);
}
}

@Test
@DisabledOnOs(WINDOWS)
/**
* Verify system-allow-fail command
*/
public void testSystemInPathAllowFail() throws Exception {
try (Processor p = new Processor()) {
Macro macro = new Macro(p);
assertEquals("", macro.process("${system-in-path-allow-fail;/tmp;mostidioticcommandthatwillsurelyfail}"));
} catch (IOException e) {
fail(e);
}
}

@Test
@DisabledOnOs({
OS.MAC, OS.LINUX
})
public void testSystemInPathWindowsAllowFail() throws Exception {
try (Processor p = new Processor()) {
Macro macro = new Macro(p);
assertEquals("",
macro.process("${system-in-path-allow-fail;c:/;mostidioticcommandthatwillsurelyfail}"));
} catch (IOException e) {
fail(e);
}
}

/**
* Check that variables override macros.
*/
Expand Down
53 changes: 44 additions & 9 deletions biz.aQute.bndlib/src/aQute/bnd/osgi/Macro.java
Original file line number Diff line number Diff line change
Expand Up @@ -1195,21 +1195,37 @@ boolean isLocalTarget(String string) {
* System command. Execute a command and insert the result.
*/
public String system_internal(boolean allowFail, String[] args) throws Exception {
return system_internal(allowFail, false, args);
}

/**
* System command. Execute a command and insert the result.
*/
public String system_internal(boolean allowFail, boolean extractPath, String[] args) throws Exception {
if (nosystem)
throw new RuntimeException("Macros in this mode cannot excute system commands");

verifyCommand(args, allowFail ? _system_allow_failHelp : _systemHelp, null, 2, 3);
String command = args[1];
String command = null;
String path = null;
String input = null;

if (args.length > 2) {
input = args[2];
if (extractPath) {
verifyCommand(args, allowFail ? _system_in_path_allow_failHelp : _system_in_pathHelp, null, 3, 4);
path = args[1];
command = args[2];
if (args.length > 3) {
input = args[3];
}
return domain.system(allowFail, path, command, input);
} else {
verifyCommand(args, allowFail ? _system_allow_failHelp : _systemHelp, null, 2, 3);
command = args[1];
if (args.length > 2) {
input = args[2];
}
return domain.system(allowFail, command, input);
}

return domain.system(allowFail, command, input);
}

static final String _systemHelp = "${system;<command>[;<in>]}, execute a system command";
static final String _systemHelp = "${system;<command>[;<in>]}, execute a system command in the projects directory";

public String _system(String[] args) throws Exception {
return system_internal(false, args);
Expand All @@ -1228,6 +1244,25 @@ public String _system_allow_fail(String[] args) throws Exception {
}
}

static final String _system_in_pathHelp = "${system-in-path;<path>;<command>[;<in>]}, execute a system command in the given path";

public String _system_in_path(String[] args) throws Exception {
return system_internal(false, true, args);
}

static final String _system_in_path_allow_failHelp = "${system-in-path-allow-fail;<path>;;<command>[;<in>]}, execute a system command allowing command failure in the given path";

public String _system_in_path_allow_fail(String[] args) throws Exception {
String result = "";
try {
result = system_internal(true, true, args);
return result == null ? "" : result;
} catch (Throwable t) {
/* ignore */
return "";
}
}

static final String _envHelp = "${env;<name>[;alternative]}, get the environment variable";

public String _env(String[] args) {
Expand Down
12 changes: 11 additions & 1 deletion biz.aQute.bndlib/src/aQute/bnd/osgi/Processor.java
Original file line number Diff line number Diff line change
Expand Up @@ -2436,6 +2436,16 @@ public Parameters getParameters(String key, boolean allowDuplicates) {
}

public String system(boolean allowFail, String command, String input) throws IOException, InterruptedException {
return system(allowFail, getBase(), command, input);
}

public String system(boolean allowFail, String runDirectory, String command, String input)
throws IOException, InterruptedException, InterruptedException {
return system(allowFail, new File(runDirectory), command, input);
}

public String system(boolean allowFail, File runDirectory, String command, String input)
throws IOException, InterruptedException {
List<String> args;
if (IO.isWindows()) {
args = Lists.of("cmd", "/c", Command.windowsQuote(command));
Expand All @@ -2445,7 +2455,7 @@ public String system(boolean allowFail, String command, String input) throws IOE
.collect(toList());
}

Process process = new ProcessBuilder(args).directory(getBase())
Process process = new ProcessBuilder(args).directory(runDirectory)
.start();

try (OutputStream stdin = process.getOutputStream()) {
Expand Down
74 changes: 11 additions & 63 deletions docs/_macros/system.md
Original file line number Diff line number Diff line change
@@ -1,72 +1,20 @@
---
layout: default
class: Macro
title: system ';' STRING ( ';' STRING )?
title: system ';' CMD ( ';' INPUT )?
summary: Execute a system command
---

Executes a System command in the current project directory.
This can be used to execute command line tools. If an INPUT is given, it will be given to the process via the Standard Input.

public String _system(String args[]) throws Exception {
return system_internal(false, args);
}
If the Process exits with anything other than `0`, the result will be become an error.

public String _system_allow_fail(String args[]) throws Exception {
String result = "";
try {
result = system_internal(true, args);
}
catch (Throwable t) {
/* ignore */
}
return result;
}
Usage Example:
```
# Extracts the current git SHA for the Project
Git-SHA: ${system;git rev-list -1 --no-abbrev-commit HEAD}
/**
* System command. Execute a command and insert the result.
*
* @param args
* @param help
* @param patterns
* @param low
* @param high
*/
public String system_internal(boolean allowFail, String args[]) throws Exception {
if (nosystem)
throw new RuntimeException("Macros in this mode cannot excute system commands");

verifyCommand(args, "${" + (allowFail ? "system-allow-fail" : "system")
+ ";<command>[;<in>]}, execute a system command", null, 2, 3);
String command = args[1];
String input = null;

if (args.length > 2) {
input = args[2];
}
if ( File.separatorChar == '\\')
command = "cmd /c \"" + command + "\"";

Process process = Runtime.getRuntime().exec(command, null, domain.getBase());
if (input != null) {
process.getOutputStream().write(input.getBytes("UTF-8"));
}
process.getOutputStream().close();

String s = IO.collect(process.getInputStream(), "UTF-8");
int exitValue = process.waitFor();
if (exitValue != 0)
return exitValue + "";

if (exitValue != 0) {
if (!allowFail) {
domain.error("System command " + command + " failed with exit code " + exitValue);
} else {
domain.warning("System command " + command + " failed with exit code " + exitValue + " (allowed)");

}
}

return s.trim();
}

# Extracts the current git SHA for the Project and enters the password as input
Git-SHA: ${system;git rev-list -1 --no-abbrev-commit HEAD;mypassword}
```
75 changes: 11 additions & 64 deletions docs/_macros/system_allow_fail.md
Original file line number Diff line number Diff line change
@@ -1,73 +1,20 @@
---
layout: default
class: Macro
title: system_allow_fail ';' STRING ( ';' STRING )?
title: system-allow-fail ';' CMD ( ';' INPUT )?
summary: Execute a system command but ignore any failures
---

Executes a System command in the current project directory.
This can be used to execute command line tools. If an INPUT is given, it will be given to the process via the Standard Input.

If the Process exits with anything other than `0`, the result will be be marked as a warning.

public String _system(String args[]) throws Exception {
return system_internal(false, args);
}
Usage Example:
```
# Extracts the current git SHA for the Project
Git-SHA: ${system-allow-fail;git rev-list -1 --no-abbrev-commit HEAD}
public String _system_allow_fail(String args[]) throws Exception {
String result = "";
try {
result = system_internal(true, args);
}
catch (Throwable t) {
/* ignore */
}
return result;
}

/**
* System command. Execute a command and insert the result.
*
* @param args
* @param help
* @param patterns
* @param low
* @param high
*/
public String system_internal(boolean allowFail, String args[]) throws Exception {
if (nosystem)
throw new RuntimeException("Macros in this mode cannot excute system commands");

verifyCommand(args, "${" + (allowFail ? "system-allow-fail" : "system")
+ ";<command>[;<in>]}, execute a system command", null, 2, 3);
String command = args[1];
String input = null;

if (args.length > 2) {
input = args[2];
}
if ( File.separatorChar == '\\')
command = "cmd /c \"" + command + "\"";

Process process = Runtime.getRuntime().exec(command, null, domain.getBase());
if (input != null) {
process.getOutputStream().write(input.getBytes("UTF-8"));
}
process.getOutputStream().close();

String s = IO.collect(process.getInputStream(), "UTF-8");
int exitValue = process.waitFor();
if (exitValue != 0)
return exitValue + "";

if (exitValue != 0) {
if (!allowFail) {
domain.error("System command " + command + " failed with exit code " + exitValue);
} else {
domain.warning("System command " + command + " failed with exit code " + exitValue + " (allowed)");

}
}

return s.trim();
}

# Extracts the current git SHA for the Project and enters the password as input
Git-SHA: ${system-allow-fail;git rev-list -1 --no-abbrev-commit HEAD;mypassword}
```
20 changes: 20 additions & 0 deletions docs/_macros/system_in_path.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
layout: default
class: Macro
title: system-in-path ';' PATH ';' CMD ( ';' INPUT )?
summary: Execute a system command
---

Executes a System command in the given path. The path can be anywhere, even outside the current Project.
This can be used to execute command line tools. If an INPUT is given, it will be given to the process via the Standard Input.

If the Process exits with anything other than `0`, the result will be become an error.

Usage Example:
```
# Extracts the current git SHA in the given path
Git-SHA: ${system-in-path; ~/git/someproject; git rev-list -1 --no-abbrev-commit HEAD}
# Extracts the current git SHA in the given path and enters the password as input
Git-SHA: ${system-in-path; ~/git/someproject; git rev-list -1 --no-abbrev-commit HEAD;mypassword}
```
Loading

0 comments on commit 36e63cd

Please sign in to comment.