view mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/SharingMercurialUpdater.java @ 870:6df89e185a3c

TW-19916 ability to specify custom mercurial config for VCS root
author Dmitry Neverov <dmitry.neverov@jetbrains.com>
date Wed, 24 Sep 2014 19:40:10 +0200
parents 03275807f45b
children bf83331f51f0
line wrap: on
line source
/*
 * Copyright 2000-2014 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 jetbrains.buildServer.agent.AgentRunningBuild;
import jetbrains.buildServer.util.FileUtil;
import jetbrains.buildServer.vcs.VcsException;
import jetbrains.buildServer.vcs.VcsRoot;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.File;
import java.io.IOException;

public class SharingMercurialUpdater extends MercurialIncludeRuleUpdater {
  public SharingMercurialUpdater(@NotNull AgentPluginConfig pluginConfig,
                                 @NotNull MirrorManager mirrorManager,
                                 @NotNull AgentRepoFactory repoFactory,
                                 @NotNull VcsRoot root,
                                 @NotNull String toVersion,
                                 @NotNull AgentRunningBuild build) {
    super(pluginConfig, mirrorManager, repoFactory, root, toVersion, build);
  }

  @Override
  protected void updateRepository(@NotNull File workingDir) throws VcsException, IOException {
    HgRepo repo = myRepoFactory.createRepo(myRoot, workingDir);
    if (repo.isEmpty() || !repo.isValidRepository())
      repo.init().call();
    repo.setDefaultPath(myRoot.getRepository());
    repo.setTeamCityConfig(myRoot.getCustomHgConfig());

    File mirrorHg = getMirrorHg(myRoot.getRepository());
    String sharedPath = readSharedPath(workingDir);
    if (mirrorHg.getCanonicalPath().equals(sharedPath)) {
      writeRequires(mirrorHg, workingDir);
    } else {
      writeRequires(mirrorHg, workingDir);
      writeSharedPath(mirrorHg, workingDir);
    }
  }

  @Override
  protected void syncSubrepo(@NotNull HgRepo subrepository, @NotNull String subrepoUrl, @NotNull String subrepoRevision) throws VcsException, IOException {
    if (subrepository.isEmpty() || !subrepository.isValidRepository())
      subrepository.init().call();
    subrepository.setDefaultPath(subrepoUrl);
    subrepository.setTeamCityConfig(myRoot.getCustomHgConfig());

    if (!subrepository.containsRevision(subrepoRevision)) {
      updateLocalMirror(subrepoUrl, subrepoRevision);
      File mirrorHg = getMirrorHg(subrepoUrl);
      String sharedPath = readSharedPath(subrepository.getWorkingDir());
      if (mirrorHg.getCanonicalPath().equals(sharedPath)) {
        writeRequires(mirrorHg, subrepository.getWorkingDir());
      } else {
        writeRequires(mirrorHg, subrepository.getWorkingDir());
        writeSharedPath(mirrorHg, subrepository.getWorkingDir());
      }
    }
  }

  @Nullable
  private String readSharedPath(@NotNull File workingDir) throws IOException {
    File sharedPath = getSharedPath(workingDir);
    if (!sharedPath.exists())
      return null;
    return FileUtil.readText(sharedPath);
  }

  private void writeSharedPath(@NotNull File mirrorHg, @NotNull File workingDir) throws IOException {
    FileUtil.writeToFile(getSharedPath(workingDir), mirrorHg.getCanonicalPath().getBytes("UTF-8"));
  }

  private void writeRequires(@NotNull File mirrorHg, @NotNull File workingDir) throws IOException {
    //Copy .hg/requires from mirror to working dir because it could be created by
    //an older version or mercurial. When shared repositories are used this can
    //lead to errors, because mercurial command is trying to work with .hg in
    //mirrors as if it was of a newer version.
    File mirrorRequires = new File(mirrorHg, "requires");
    File workingDirRequires = new File(new File(workingDir, ".hg"), "requires");
    FileUtil.copy(mirrorRequires, workingDirRequires);
    FileUtil.writeToFile(workingDirRequires, "shared\n".getBytes(), true);
  }

  @NotNull
  private File getSharedPath(File workingDir) {
    return new File(new File(workingDir, ".hg"), "sharedpath");
  }

  @NotNull
  private File getMirrorHg(@NotNull String repositoryUrl) {
    File mirrorDir = myMirrorManager.getMirrorDir(repositoryUrl);
    return new File(mirrorDir, ".hg");
  }
}