Introduce FS.execute() to execute a command defined by a ProcessBuilder

Change-Id: I2ad2c71ad30b969455bdea89637b8e996b1dad8c
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
This commit is contained in:
Christian Halstrick 2015-10-28 13:24:28 +01:00 committed by Matthias Sohn
parent 6389948a81
commit 69cd6f5864
2 changed files with 115 additions and 3 deletions

View File

@ -52,6 +52,7 @@
import java.io.InputStream;
import org.eclipse.jgit.junit.JGitTestUtil;
import org.eclipse.jgit.util.FS.ExecutionResult;
import org.junit.Before;
import org.junit.Test;
@ -163,6 +164,45 @@ public void testWrongScript() throws IOException, InterruptedException {
assertEquals(127, rc);
}
@Test
public void testCopyStdInExecute()
throws IOException, InterruptedException {
String inputStr = "a\nb\rc\r\nd";
File script = writeTempFile("cat -");
ProcessBuilder pb = new ProcessBuilder("/bin/sh", script.getPath());
ExecutionResult res = FS.DETECTED.execute(pb,
new ByteArrayInputStream(inputStr.getBytes()));
assertEquals(0, res.getRc());
assertEquals(inputStr, new String(res.getStdout().toByteArray()));
assertEquals("", new String(res.getStderr().toByteArray()));
}
@Test
public void testStdErrExecute() throws IOException, InterruptedException {
File script = writeTempFile("echo hi >&2");
ProcessBuilder pb = new ProcessBuilder("/bin/sh", script.getPath());
ExecutionResult res = FS.DETECTED.execute(pb, null);
assertEquals(0, res.getRc());
assertEquals("", new String(res.getStdout().toByteArray()));
assertEquals("hi" + sep, new String(res.getStderr().toByteArray()));
}
@Test
public void testAllTogetherBinExecute()
throws IOException, InterruptedException {
String inputStr = "a\nb\rc\r\nd";
File script = writeTempFile(
"echo $#,$1,$2,$3,$4,$5,$6 >&2 ; cat -; exit 5");
ProcessBuilder pb = new ProcessBuilder("/bin/sh", script.getPath(), "a",
"b", "c");
ExecutionResult res = FS.DETECTED.execute(pb,
new ByteArrayInputStream(inputStr.getBytes()));
assertEquals(5, res.getRc());
assertEquals(inputStr, new String(res.getStdout().toByteArray()));
assertEquals("3,a,b,c,,," + sep,
new String(res.getStderr().toByteArray()));
}
private File writeTempFile(String body) throws IOException {
File f = File.createTempFile("RunProcessTestScript_", "");
JGitTestUtil.write(f, body);

View File

@ -110,7 +110,54 @@ public FS detect(Boolean cygwinUsed) {
}
}
final static Logger LOG = LoggerFactory.getLogger(FS.class);
/**
* Result of an executed process. The caller is responsible to close the
* contained {@link TemporaryBuffer}s
*
* @since 4.2
*/
public static class ExecutionResult {
private TemporaryBuffer stdout;
private TemporaryBuffer stderr;
private int rc;
/**
* @param stdout
* @param stderr
* @param rc
*/
public ExecutionResult(TemporaryBuffer stdout, TemporaryBuffer stderr,
int rc) {
this.stdout = stdout;
this.stderr = stderr;
this.rc = rc;
}
/**
* @return buffered standard output stream
*/
public TemporaryBuffer getStdout() {
return stdout;
}
/**
* @return buffered standard error stream
*/
public TemporaryBuffer getStderr() {
return stderr;
}
/**
* @return the return code of the process
*/
public int getRc() {
return rc;
}
}
private final static Logger LOG = LoggerFactory.getLogger(FS.class);
/** The auto-detected implementation selected for this operating system and JRE. */
public static final FS DETECTED = detect();
@ -1004,10 +1051,10 @@ private static boolean shutdownAndAwaitTermination(ExecutorService pool) {
pool.shutdown(); // Disable new tasks from being submitted
try {
// Wait a while for existing tasks to terminate
if (!pool.awaitTermination(5, TimeUnit.SECONDS)) {
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
pool.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being canceled
if (!pool.awaitTermination(5, TimeUnit.SECONDS))
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
hasShutdown = false;
}
} catch (InterruptedException ie) {
@ -1034,6 +1081,31 @@ private static boolean shutdownAndAwaitTermination(ExecutorService pool) {
*/
public abstract ProcessBuilder runInShell(String cmd, String[] args);
/**
* Execute a command defined by a {@link ProcessBuilder}.
*
* @param pb
* The command to be executed
* @param in
* The standard input stream passed to the process
* @return The result of the executed command
* @throws InterruptedException
* @throws IOException
* @since 4.2
*/
public ExecutionResult execute(ProcessBuilder pb, InputStream in)
throws IOException, InterruptedException {
TemporaryBuffer stdout = new TemporaryBuffer.LocalFile(null);
TemporaryBuffer stderr = new TemporaryBuffer.Heap(1024, 1024 * 1024);
try {
int rc = runProcess(pb, stdout, stderr, in);
return new ExecutionResult(stdout, stderr, rc);
} finally {
stdout.close();
stderr.close();
}
}
private static class Holder<V> {
final V value;