diff --git a/src/de/uni_passau/fim/seibt/gitwrapper/process/ProcessExecutor.java b/src/de/uni_passau/fim/seibt/gitwrapper/process/ProcessExecutor.java index 52036d24dd4f792fdbbbee50e41430c018cae48b..b84546ecd5810bad1f379d16c269ab3a7e192a2f 100644 --- a/src/de/uni_passau/fim/seibt/gitwrapper/process/ProcessExecutor.java +++ b/src/de/uni_passau/fim/seibt/gitwrapper/process/ProcessExecutor.java @@ -2,6 +2,7 @@ package de.uni_passau.fim.seibt.gitwrapper.process; import java.io.File; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Optional; import java.util.logging.Level; @@ -10,6 +11,9 @@ import java.util.stream.Stream; import org.apache.commons.io.IOUtils; +import static de.uni_passau.fim.seibt.gitwrapper.repo.GitWrapper.EXIT_FAIL; +import static java.util.logging.Level.WARNING; + /** * Contains static methods for executing commands and gathering their output and exit code. */ @@ -22,7 +26,8 @@ public class ProcessExecutor { */ public static class ExecRes { public int exitCode; - public String output; + public String stdOut; + public String stdErr; } /** @@ -83,20 +88,44 @@ public class ProcessExecutor { */ public static Optional<ExecRes> exec(ProcessBuilder builder) { String cmd = String.join(" ", builder.command()); - LOG.fine(() -> String.format("Executing '%s'.", cmd)); + LOG.fine(() -> String.format("Executing '%s' in '%s'.", cmd, builder.directory().getAbsolutePath())); try { ExecRes res = new ExecRes(); Process p = builder.start(); - res.exitCode = p.waitFor(); - res.output = IOUtils.toString(p.getInputStream()); + res.stdOut = IOUtils.toString(p.getInputStream(), StandardCharsets.UTF_8).trim(); + res.stdErr = IOUtils.toString(p.getErrorStream(), StandardCharsets.UTF_8).trim(); + + IOUtils.closeQuietly(p.getInputStream()); + IOUtils.closeQuietly(p.getErrorStream()); + IOUtils.closeQuietly(p.getOutputStream()); + + try { + res.exitCode = p.waitFor(); + } catch (InterruptedException e) { + LOG.log(WARNING, e, () -> String.format("Interrupted while waiting for '%s' to finish.", cmd)); + + p.destroyForcibly(); + res.exitCode = EXIT_FAIL; + } LOG.fine(() -> String.format("Execution of '%s' returned exit code %d.", cmd, res.exitCode)); - LOG.finest(() -> String.format("Execution of '%s' output:%n%s", cmd, res.output.trim())); + + if (res.stdOut.isEmpty()) { + LOG.finest(() -> String.format("Execution of '%s' returned no standard output.", cmd)); + } else { + LOG.finest(() -> String.format("Execution of '%s' returned standard output:%n%s", cmd, res.stdOut)); + } + + if (res.stdErr.isEmpty()) { + LOG.finest(() -> String.format("Execution of '%s' returned no standard error output.", cmd)); + } else { + LOG.finest(() -> String.format("Execution of '%s' returned standard error output:%n%s", cmd, res.stdErr)); + } return Optional.of(res); - } catch (IOException | InterruptedException e) { + } catch (IOException e) { LOG.log(Level.SEVERE, e, () -> String.format("Exception executing '%s'.", cmd)); return Optional.empty(); } diff --git a/src/de/uni_passau/fim/seibt/gitwrapper/repo/Commit.java b/src/de/uni_passau/fim/seibt/gitwrapper/repo/Commit.java index 78214d5df63ce70d0ea16d8500cf7981031c08f8..59a7f9b014df62e8d6741a538912662269eb9dbf 100644 --- a/src/de/uni_passau/fim/seibt/gitwrapper/repo/Commit.java +++ b/src/de/uni_passau/fim/seibt/gitwrapper/repo/Commit.java @@ -45,7 +45,7 @@ public class Commit { public List<Commit> getParents() { Optional<ExecRes> revList = git.exec(repo.getDir(), "rev-list", "--parents", "-n", "1", id); Function<ExecRes, List<Commit>> toParentsList = res -> { - String[] ids = res.output.split("\\s+"); + String[] ids = res.stdOut.split("\\s+"); LOG.fine(() -> String.format("Found %d parents for %s.", ids.length - 1, this)); LOG.finer(() -> String.format("Commit id and parents are:%n%s", String.join(System.lineSeparator(), ids))); @@ -83,7 +83,7 @@ public class Commit { return null; } - Commit base = repo.getCommitUnchecked(res.output.trim()); + Commit base = repo.getCommitUnchecked(res.stdOut.trim()); LOG.fine(() -> String.format("Commits %s and %s have the merge base %s.", this, other, base)); diff --git a/src/de/uni_passau/fim/seibt/gitwrapper/repo/GitWrapper.java b/src/de/uni_passau/fim/seibt/gitwrapper/repo/GitWrapper.java index b51a61b33960d3e0390242bc851f8fdf0f561f86..1813547f4fe91457161b6cdbe291eaf1d9f447ad 100644 --- a/src/de/uni_passau/fim/seibt/gitwrapper/repo/GitWrapper.java +++ b/src/de/uni_passau/fim/seibt/gitwrapper/repo/GitWrapper.java @@ -43,7 +43,7 @@ public class GitWrapper extends ToolWrapper { @Override protected boolean isWorking() { - Function<ExecRes, Boolean> checkPrefix = execRes -> execRes.output.startsWith(GIT_VERSION_PREFIX); + Function<ExecRes, Boolean> checkPrefix = execRes -> execRes.stdOut.startsWith(GIT_VERSION_PREFIX); return ProcessExecutor.exec(cmd, new File("."), true, GIT_VERSION_C).map(checkPrefix).orElse(false); } @@ -65,7 +65,7 @@ public class GitWrapper extends ToolWrapper { Optional<ExecRes> res = exec(parentDir, "clone", url); Function<ExecRes, Repository> toRepo = execRes -> { - Scanner sc = new Scanner(execRes.output); + Scanner sc = new Scanner(execRes.stdOut); if (!sc.hasNextLine()) { LOG.warning(() -> String.format("No output while cloning '%s'.", url)); @@ -141,7 +141,7 @@ public class GitWrapper extends ToolWrapper { * @return whether the git command failed */ public boolean failed(ExecRes res) { - return res.exitCode != EXIT_SUCCESS || res.output.startsWith(FATAL_PREFIX) || res.output.startsWith(ERROR_PREFIX); + return res.exitCode != EXIT_SUCCESS || res.stdOut.startsWith(FATAL_PREFIX) || res.stdOut.startsWith(ERROR_PREFIX); } /** diff --git a/src/de/uni_passau/fim/seibt/gitwrapper/repo/Repository.java b/src/de/uni_passau/fim/seibt/gitwrapper/repo/Repository.java index 798ecda86a6f3987543144855bd1c6b83f47c2aa..2b82420ce586b7b88992ee5842055052a94a2b61 100644 --- a/src/de/uni_passau/fim/seibt/gitwrapper/repo/Repository.java +++ b/src/de/uni_passau/fim/seibt/gitwrapper/repo/Repository.java @@ -115,7 +115,7 @@ public class Repository { return null; } - String[] lines = res.output.split("[\\r?\\n]+"); + String[] lines = res.stdOut.split("[\\r?\\n]+"); LOG.fine(() -> String.format("Found %d merge commits in %s.", lines.length, this)); LOG.finer(() -> String.format("Merge commits are:%n%s", String.join(System.lineSeparator(), lines))); @@ -175,7 +175,7 @@ public class Repository { return null; } - boolean isCommit = res.output.startsWith(TYPE_COMMIT); + boolean isCommit = res.stdOut.startsWith(TYPE_COMMIT); if (isCommit) { LOG.finer(() -> String.format("%s is a commit.", id)); @@ -203,9 +203,9 @@ public class Repository { return null; } - LOG.finer(() -> String.format("Resolved %s to %s.", id, res.output)); + LOG.finer(() -> String.format("Resolved %s to %s.", id, res.stdOut)); - return res.output; + return res.stdOut; }; return revParse.map(toHash);