changeset 596:a37960e1f0a0

Log stderr when hg command fails to ease troubleshooting
author Dmitry Neverov <dmitry.neverov@jetbrains.com>
date Mon, 29 Apr 2013 14:23:20 +0400
parents f2a2bf159f4c
children 65f5e86206e6
files mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CommandResult.java mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CommandUtil.java mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CommandResultTest.java
diffstat 3 files changed, 44 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CommandResult.java	Mon Apr 29 13:44:45 2013 +0400
+++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CommandResult.java	Mon Apr 29 14:23:20 2013 +0400
@@ -40,15 +40,18 @@
   private final String myCommand;
   private final ExecResult myDelegate;
   private final Set<String> myPrivateData;
+  private final CommandSettings mySettings;
 
   public CommandResult(@NotNull Logger logger,
                        @NotNull String command,
                        @NotNull ExecResult execResult,
-                       @NotNull Set<String> privateData) {
+                       @NotNull Set<String> privateData,
+                       @NotNull CommandSettings settings) {
     myLogger = logger;
     myCommand = command;
     myDelegate = execResult;
     myPrivateData = privateData;
+    mySettings = settings;
   }
 
   @NotNull
@@ -78,7 +81,7 @@
     myLogger.warn(message);
     if (hasImportantException())
       myLogger.error("Error during executing '" + getCommand() + "'", getException());
-    throwVcsException(message);
+    throwVcsException(getExceptionMessage());
   }
 
   private void throwVcsException(@NotNull String message) throws VcsException {
@@ -146,19 +149,24 @@
   }
 
   private String createCommandLogMessage() {
-    return "'" + getCommand() + "' command failed.";
+    StringBuilder message = new StringBuilder();
+    message.append("'").append(getCommand()).append("' command failed.");
+    String stderr = getStderr();
+    if (!isEmpty(stderr)) {
+      int logOutputLimit = mySettings.getLogOutputLimit();
+      if (logOutputLimit == -1) {
+        message.append("\nstderr:\n").append(stderr);
+      } else {
+        message.append(StringUtil.truncateStringValueWithDotsAtEnd(stderr, logOutputLimit));
+      }
+    }
+    return message.toString();
   }
 
-  @Nullable
   private String getExceptionMessage() {
-    //noinspection ThrowableResultOfMethodCallIgnored
-    Throwable exception = getException();
-    if (exception == null)
-      return null;
-    String message = exception.getMessage();
-    if (message == null)
-      message = exception.getClass().getName();
-    return message;
+    StringBuilder message = new StringBuilder();
+    message.append("'").append(getCommand()).append("' command failed.");
+    return message.toString();
   }
 
   private void rethrowDetectedError() throws VcsException {
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CommandUtil.java	Mon Apr 29 13:44:45 2013 +0400
+++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CommandUtil.java	Mon Apr 29 14:23:20 2013 +0400
@@ -30,7 +30,7 @@
   public static CommandResult runCommand(@NotNull MercurialCommandLine cli, @NotNull CommandSettings settings) throws VcsException {
     final String command = removePrivateData(cli.getCommandLineString(), settings.getPrivateData());
     logRunCommand(cli, command, settings);
-    CommandResult res = run(cli, settings.getTimeout(), command, settings.getPrivateData());
+    CommandResult res = run(cli, settings.getTimeout(), command, settings.getPrivateData(), settings);
     if (settings.isCheckForFailure() || settings.isFailWithNonEmptyStderr())
       res.checkFailure(settings.isFailWithNonEmptyStderr());
     logCommandOutput(command, res, settings);
@@ -40,7 +40,8 @@
   private static CommandResult run(@NotNull final MercurialCommandLine cli,
                                    final int executionTimeout,
                                    @NotNull final String command,
-                                   @NotNull final Set<String> privateData) {
+                                   @NotNull final Set<String> privateData,
+                                   @NotNull CommandSettings settings) {
     final long start = System.currentTimeMillis();
     ExecResult res = SimpleCommandLineProcessRunner.runCommand(cli, null, new SimpleCommandLineProcessRunner.ProcessRunCallbackAdapter() {
       @Override
@@ -53,7 +54,7 @@
         Loggers.VCS.debug("Command " + command + " took " + duration + "ms");
       }
     });
-    return new CommandResult(Loggers.VCS, command, res, privateData);
+    return new CommandResult(Loggers.VCS, command, res, privateData, settings);
   }
 
   public static String removePrivateData(final String str, final Set<String> privateData) {
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CommandResultTest.java	Mon Apr 29 13:44:45 2013 +0400
+++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CommandResultTest.java	Mon Apr 29 14:23:20 2013 +0400
@@ -23,6 +23,7 @@
 import static org.hamcrest.Matchers.containsString;
 import static org.hamcrest.Matchers.not;
 import static org.testng.AssertJUnit.*;
+import static org.testng.AssertJUnit.assertTrue;
 
 /**
  * @author dmitry.neverov
@@ -101,12 +102,22 @@
     }
   }
 
+  public void when_command_fails_stderr_should_be_logged() {
+    CommandResult cr = commandResultFor(execResult().withStderr("an important error").withExitCode(255));
+    try {
+      cr.checkCommandFailed();
+    } catch (VcsException e) {
+      //ignore
+    }
+    assertTrue(myLogger.contains("an important error"));
+  }
+
   ExecResultBuilder execResult() {
     return new ExecResultBuilder();
   }
 
   CommandResult commandResultFor(ExecResultBuilder builder, String... privateData) {
-    return new CommandResult(myLogger, "", builder.build(), new HashSet<String>(Arrays.asList(privateData)));
+    return new CommandResult(myLogger, "", builder.build(), new HashSet<String>(Arrays.asList(privateData)), new CommandSettings());
   }
 
   private class ExecResultBuilder {
@@ -159,6 +170,14 @@
 
     private List<String> myMessages = new ArrayList<String>();
 
+    public boolean contains(@NotNull String entry) {
+      for (String message : myMessages) {
+        if (message.contains(entry))
+          return true;
+      }
+      return false;
+    }
+
     public void assertLogMessagesDontContain(@NotNull String... strs) {
       for (String s : strs) {
         for (String message : myMessages)