view mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CommandUtil.java @ 339:b799355b4016

Merge branch Eluru-6.5.x
author Dmitry Neverov <dmitry.neverov@jetbrains.com>
date Fri, 02 Dec 2011 15:35:00 +0300
parents 092373ee11e5 d31d7c81b637
children 4a49a0baf30b
line wrap: on
line source
/*
 * Copyright 2000-2011 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package jetbrains.buildServer.buildTriggers.vcs.mercurial.command;

import com.intellij.execution.configurations.GeneralCommandLine;
import jetbrains.buildServer.ExecResult;
import jetbrains.buildServer.SimpleCommandLineProcessRunner;
import jetbrains.buildServer.log.Loggers;
import jetbrains.buildServer.util.StringUtil;
import jetbrains.buildServer.vcs.VcsException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Collections;
import java.util.Set;

public class CommandUtil {
  private static final int DEFAULT_COMMAND_TIMEOUT_SEC = 3600;

  public static void checkCommandFailed(@NotNull String cmdName, @NotNull ExecResult res) throws VcsException {
    if (res.getExitCode() != 0 || res.getException() != null)
      commandFailed(cmdName, res);
    if (res.getStderr().length() > 0) {
      Loggers.VCS.warn("Error output produced by: " + cmdName);
      Loggers.VCS.warn(res.getStderr());
    }
  }

  public static void commandFailed(final String cmdName, final ExecResult res) throws VcsException {
    final String message = createCommandLogMessage(cmdName, res);
    Loggers.VCS.warn(message);
    if (hasImportantException(res))
      Loggers.VCS.error("Error during executing '" + cmdName + "'", res.getException());
    throw new VcsException(message);
  }

  private static String createCommandLogMessage(final String cmdName, final ExecResult res) {
    String stderr = res.getStderr();
    String stdout = res.getStdout();
    String exceptionMessage = getExceptionMessage(res);
    return "'" + cmdName + "' command failed.\n" +
            (!StringUtil.isEmpty(stdout) ? "stdout: " + stdout + "\n" : "") +
            (!StringUtil.isEmpty(stderr) ? "stderr: " + stderr + "\n" : "") +
            (exceptionMessage != null ? "exception: " + exceptionMessage : "");
  }

  @Nullable
  private static String getExceptionMessage(ExecResult result) {
    Throwable exception = result.getException();
    String message = null;
    if (exception != null) {
      message = exception.getMessage();
      if (message == null) {
        message = exception.getClass().getName();
      }
    }
    return message;
  }

  private static boolean hasImportantException(ExecResult result) {
    Throwable exception = result.getException();
    if (exception != null) {
      return exception instanceof NullPointerException;
    } else {
      return false;
    }
  }

  public static ExecResult runCommand(@NotNull GeneralCommandLine cli) throws VcsException {
    return runCommand(cli, DEFAULT_COMMAND_TIMEOUT_SEC, Collections.<String>emptySet());
  }

  public static ExecResult runCommand(@NotNull GeneralCommandLine cli, @NotNull Set<String> privateData) throws VcsException {
    return runCommand(cli, DEFAULT_COMMAND_TIMEOUT_SEC, privateData);
  }

  public static ExecResult runCommand(@NotNull GeneralCommandLine cli, final int executionTimeout, @NotNull Set<String> privateData) throws VcsException {
    return runCommand(cli, executionTimeout, privateData, true);
  }

  public static ExecResult runCommand(@NotNull GeneralCommandLine cli, @NotNull Set<String> privateData, final boolean checkFailure) throws VcsException {
    return runCommand(cli, DEFAULT_COMMAND_TIMEOUT_SEC, privateData, checkFailure);
  }

  public static ExecResult runCommand(@NotNull GeneralCommandLine cli, final int executionTimeout, @NotNull Set<String> privateData, final boolean checkFailure) throws VcsException {
    final String cmdStr = removePrivateData(cli.getCommandLineString(), privateData);
    Loggers.VCS.debug("Run command: " + cmdStr);
    final long start = System.currentTimeMillis();
    ExecResult res = SimpleCommandLineProcessRunner.runCommand(cli, null, new SimpleCommandLineProcessRunner.RunCommandEventsAdapter() {
      @Override
      public Integer getOutputIdleSecondsTimeout() {
        return executionTimeout;
      }
      @Override
      public void onProcessFinished(Process ps) {
        long duration = System.currentTimeMillis() - start;
        Loggers.VCS.debug("Command " + cmdStr + " took " + duration + "ms");
      }
    });

    removePrivateData(privateData, res);

    if (checkFailure)
      CommandUtil.checkCommandFailed(cmdStr, res);
    Loggers.VCS.debug("Command " + cmdStr + " output:\n" + res.getStdout());
    return res;
  }

  private static void removePrivateData(final Set<String> privateData, final ExecResult res) {
    res.setStdout(removePrivateData(res.getStdout(), privateData));
    res.setStderr(removePrivateData(res.getStderr(), privateData));
  }

  public static String removePrivateData(final String str, final Set<String> privateData) {
    String result = str;
    for (String data: privateData) {
      if (data == null || data.length() == 0) continue;
      result = result.replace(data, "******");
    }

    return result;
  }
}