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:
parent
6389948a81
commit
69cd6f5864
|
@ -52,6 +52,7 @@
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
import org.eclipse.jgit.junit.JGitTestUtil;
|
import org.eclipse.jgit.junit.JGitTestUtil;
|
||||||
|
import org.eclipse.jgit.util.FS.ExecutionResult;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
@ -163,6 +164,45 @@ public void testWrongScript() throws IOException, InterruptedException {
|
||||||
assertEquals(127, rc);
|
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 {
|
private File writeTempFile(String body) throws IOException {
|
||||||
File f = File.createTempFile("RunProcessTestScript_", "");
|
File f = File.createTempFile("RunProcessTestScript_", "");
|
||||||
JGitTestUtil.write(f, body);
|
JGitTestUtil.write(f, body);
|
||||||
|
|
|
@ -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. */
|
/** The auto-detected implementation selected for this operating system and JRE. */
|
||||||
public static final FS DETECTED = detect();
|
public static final FS DETECTED = detect();
|
||||||
|
@ -1004,10 +1051,10 @@ private static boolean shutdownAndAwaitTermination(ExecutorService pool) {
|
||||||
pool.shutdown(); // Disable new tasks from being submitted
|
pool.shutdown(); // Disable new tasks from being submitted
|
||||||
try {
|
try {
|
||||||
// Wait a while for existing tasks to terminate
|
// 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
|
pool.shutdownNow(); // Cancel currently executing tasks
|
||||||
// Wait a while for tasks to respond to being canceled
|
// Wait a while for tasks to respond to being canceled
|
||||||
if (!pool.awaitTermination(5, TimeUnit.SECONDS))
|
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
|
||||||
hasShutdown = false;
|
hasShutdown = false;
|
||||||
}
|
}
|
||||||
} catch (InterruptedException ie) {
|
} catch (InterruptedException ie) {
|
||||||
|
@ -1034,6 +1081,31 @@ private static boolean shutdownAndAwaitTermination(ExecutorService pool) {
|
||||||
*/
|
*/
|
||||||
public abstract ProcessBuilder runInShell(String cmd, String[] args);
|
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> {
|
private static class Holder<V> {
|
||||||
final V value;
|
final V value;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue