view mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgDetector.java @ 976:7bf4d943d5bb

Update copyright
author pavel.sher
date Mon, 22 Jan 2018 11:39:20 +0100
parents 3795b579d310
children 10dc26b32c35
line wrap: on
line source
/*
 * Copyright 2000-2018 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;

import com.intellij.openapi.diagnostic.Logger;
import jetbrains.buildServer.agent.AgentLifeCycleAdapter;
import jetbrains.buildServer.agent.AgentLifeCycleListener;
import jetbrains.buildServer.agent.BuildAgent;
import jetbrains.buildServer.agent.BuildAgentConfiguration;
import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.CommandSettingsFactory;
import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.VersionCommand;
import jetbrains.buildServer.util.EventDispatcher;
import jetbrains.buildServer.vcs.VcsException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.File;
import java.util.Arrays;
import java.util.List;

/**
 * @author dmitry.neverov
 */
public class HgDetector extends AgentLifeCycleAdapter {

  final static String AGENT_HG_PATH_PROPERTY = "teamcity.hg.agent.path";
  private final static String AGENT_HG_VERSION = "teamcity.hg.version";
  private final static Logger LOG = Logger.getInstance(HgDetector.class.getName());
  private final static HgVersion LEAST_SUPPORTED_VERSION = new HgVersion(1, 5, 2);
  private final CommandSettingsFactory myCommandSettingsFactory;
  private final List<String> myHgPaths = Arrays.asList("hg");


  public HgDetector(@NotNull EventDispatcher<AgentLifeCycleListener> dispatcher,
                    @NotNull CommandSettingsFactory commandSettingsFactory) {
    myCommandSettingsFactory = commandSettingsFactory;
    dispatcher.addListener(this);
  }


  @Override
  public void beforeAgentConfigurationLoaded(@NotNull final BuildAgent agent) {
    BuildAgentConfiguration config = agent.getConfiguration();
    String agentHgPath = config.getConfigurationParameters().get(AGENT_HG_PATH_PROPERTY);
    File tmpDir = config.getTempDirectory();
    if (agentHgPath == null) {
      HgExec detectedHg = detectHg(tmpDir);
      if (detectedHg != null) {
        LOG.info("Detect installed mercurial at path " + detectedHg.getPath() + ", provide it as a property " + AGENT_HG_PATH_PROPERTY);
        config.addConfigurationParameter(AGENT_HG_PATH_PROPERTY, "hg");
        config.addConfigurationParameter(AGENT_HG_VERSION, detectedHg.getVersion().toString());
      } else {
        LOG.info("Cannot detect installed mercurial");
      }
    } else {
      HgExec hg = detectHgAtPath(tmpDir, agentHgPath, true);
      if (hg == null) {
        LOG.warn("Cannot run mercurial at path " + agentHgPath);
      } else {
        if (isCompatible(hg.getVersion())) {
          config.addConfigurationParameter(AGENT_HG_VERSION, hg.getVersion().toString());
        } else {
          LOG.warn("Mercurial at path " + agentHgPath + " is not compatible with TeamCity");
        }
      }
    }
  }


  @Nullable
  private HgExec detectHg(@NotNull File tmpDir) {
    for (String path : myHgPaths) {
      HgExec exec = detectHgAtPath(tmpDir, path, false);
      if (exec == null)
        continue;
      if (isCompatible(exec.getVersion())) {
        return exec;
      } else {
        warn("Mercurial version at path " + path + " is " + exec.getVersion() + ", required version is " + LEAST_SUPPORTED_VERSION + "+", false);
      }
    }
    return null;
  }


  @Nullable
  private HgExec detectHgAtPath(@NotNull File tmpDir, @NotNull String hgPath, boolean logWarnings) {
    try {
      HgVersion version = getVersion(hgPath, tmpDir);
      return new HgExec(hgPath, version);
    } catch (VcsException e) {
      warn("Error while trying to get hg version, hg path: " + hgPath, e, logWarnings);
      return null;
    }
  }


  @NotNull
  private HgVersion getVersion(@NotNull String hgPath, @NotNull File workDir) throws VcsException {
    return new VersionCommand(myCommandSettingsFactory.create(), hgPath, workDir).call();
  }


  private void warn(@NotNull final String msg, final boolean logWarnings) {
    if (logWarnings)
      LOG.warn(msg);
    else if (LOG.isDebugEnabled())
      LOG.debug(msg);
  }

  private void warn(@NotNull final String msg, @NotNull final Throwable t, final boolean logWarnings) {
    if (logWarnings)
      LOG.warn(msg, t);
    else if (LOG.isDebugEnabled())
      LOG.debug(msg, t);
  }

  private boolean isCompatible(@NotNull final HgVersion version) {
    return version.isEqualsOrGreaterThan(LEAST_SUPPORTED_VERSION);
  }


  private class HgExec {
    private final String myPath;
    private final HgVersion myVersion;

    public HgExec(@NotNull String path, @NotNull HgVersion version) {
      myPath = path;
      myVersion = version;
    }

    @NotNull
    public String getPath() {
      return myPath;
    }

    @NotNull
    public HgVersion getVersion() {
      return myVersion;
    }
  }
}