view mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/CheckoutRepository.java @ 948:8e0b879e0c19

Remove unused ant scripts
author Dmitry Neverov <dmitry.neverov@gmail.com>
date Wed, 16 Mar 2016 14:28:49 +0100
parents a6405f5aad54
children 7bf4d943d5bb
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.buildTriggers.vcs.mercurial.command.HgVcsRoot;
import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.exception.WrongSubrepoUrlException;
import jetbrains.buildServer.vcs.VcsException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.File;
import java.io.IOException;
import java.util.Map;

import static jetbrains.buildServer.util.FileUtil.delete;

/**
 * Repository checkout which uses mirrors (updates them first)
 * and supports subrepos.
 */
public class CheckoutRepository {

  private final MirrorManager myMirrorManager;
  private final HgRepoFactory myHgRepoFactory;
  private final int myPullTimeout;
  private boolean myGlobalTagsAsBranches;
  private final HgVcsRoot myRoot;
  private final File myWorkingDir;
  private String myRevision;
  private String myBranch;

  CheckoutRepository(@NotNull MirrorManager mirrorManager,
                     @NotNull HgRepoFactory hgRepoFactory,
                     int pullTimeout,
                     boolean globalTagsAsBranches,
                     @NotNull HgVcsRoot root,
                     @NotNull File workingDir) {
    myMirrorManager = mirrorManager;
    myHgRepoFactory = hgRepoFactory;
    myPullTimeout = pullTimeout;
    myRoot = root;
    myWorkingDir = workingDir;
    myGlobalTagsAsBranches = globalTagsAsBranches;
  }

  public CheckoutRepository setRevision(String revision) {
    myRevision = revision;
    return this;
  }

  public CheckoutRepository setBranch(String branch) {
    myBranch = branch;
    return this;
  }

  public void checkout() throws VcsException {
    checkout(myRoot, myWorkingDir, myRevision);
  }

  private void checkout(@NotNull HgVcsRoot root,
                        @NotNull File workingDir,
                        @Nullable String revision) throws VcsException {
    revision = updateRepository(root, workingDir, revision);
    if (revision == null)
      return;
    updateSubrepos(root, workingDir, revision);
    updateWorkingDir(root, workingDir, revision);
  }


  @Nullable
  private String updateRepository(@NotNull HgVcsRoot root,
                                  @NotNull File workingDir,
                                  @Nullable String revision) throws VcsException {
    HgRepo repo = myHgRepoFactory.createRepo(root, workingDir);
    if (revision != null && repo.containsRevision(revision))
      return revision;

    String rev = updateMirror(root, revision);
    String mirrorUrl = getMirrorUrl(root);

    if (!repo.isValidRepository())
      repo.init().call();
    repo.pull().fromRepository(mirrorUrl)
            .withTimeout(myPullTimeout)
            .call();
    repo.setDefaultPath(root.getRepository());
    repo.setTeamCityConfig(root.getCustomHgConfig());
    return rev;
  }


  private void updateWorkingDir(@NotNull HgVcsRoot root,
                                @NotNull File workingDir,
                                @NotNull String revision) throws VcsException {
    HgRepo repo = myHgRepoFactory.createRepo(root, workingDir);
    repo.update().toRevision(revision).call();
  }


  private void updateSubrepos(@NotNull HgVcsRoot root,
                              @NotNull File workingDir,
                              @Nullable String revision) throws VcsException {
    HgRepo repo = myHgRepoFactory.createRepo(root, workingDir);
    if (!repo.hasSubreposAtRevision(revision))
      return;

    String workingDirRevision = repo.getWorkingDirRevision();
    Map<String, SubRepo> workingDirSubrepos = repo.getSubrepositories(workingDirRevision);
    Map<String, SubRepo> subrepos = repo.getSubrepositories(revision);
    for (Map.Entry<String, SubRepo> entry : subrepos.entrySet()) {
      String path = entry.getKey();
      SubRepo subrepoConfig = entry.getValue();
      SubRepo workingDirSubrepo = workingDirSubrepos.get(path);
      if (workingDirSubrepo != null && subrepoConfig.hasDifferentUrlThan(workingDirSubrepo))
        delete(subrepoConfigDir(repo, subrepoConfig));

      File subrepoDir = new File(workingDir, subrepoConfig.path());
      String subrepoUrl;
      try {
        subrepoUrl = subrepoConfig.resolveUrl(root.getRepository());
        if (subrepoConfig.vcsType() == SubRepo.VcsType.hg && !isRelativeUrl(subrepoUrl)) {
          HgVcsRoot subrepoRoot = root.withUrl(subrepoUrl);
          updateRepository(subrepoRoot, subrepoDir, subrepoConfig.revision());
        }
      } catch (WrongSubrepoUrlException e) {
        subrepoUrl = subrepoConfig.url();
      }

      updateSubrepos(root.withUrl(subrepoUrl), subrepoDir, subrepoConfig.revision());
    }
  }


  private boolean isRelativeUrl(@NotNull String url) {
    return url.startsWith(".");
  }


  private File subrepoConfigDir(@NotNull HgRepo parentRepo, @NotNull SubRepo subrepo) {
    return new File(parentRepo.getWorkingDir(), subrepo.path());
  }


  /**
   * @return the given revision if it was not null, or revision of the myBranch if myBranch != null,
   * otherwise returns null. Need to resolve a branch revision with mirror lock because bookmarks
   * can be deleted by another thread.
   */
  @Nullable
  private String updateMirror(@NotNull HgVcsRoot root, @Nullable String revision) throws VcsException {
    String url = root.getRepository();
    File mirrorDir = myMirrorManager.getMirrorDir(url);
    myMirrorManager.lockDir(mirrorDir);
    try {
      HgRepo repo = myHgRepoFactory.createRepo(root, mirrorDir);
      if (revision != null && repo.containsRevision(revision)) {
        return revision;
      }

      if (!repo.isValidRepository())
        repo.init().call();

      repo.pull().fromRepository(root.getRepository())
              .withTimeout(myPullTimeout)
              .call();
      repo.setDefaultPath(root.getRepository());
      repo.setTeamCityConfig(root.getCustomHgConfig());

      if (revision != null)
        return revision;
      if (myBranch == null)
        return null;
      boolean includeTags = myGlobalTagsAsBranches && root.useTagsAsBranches();
      return repo.getBranchRevisions(true, includeTags).get(myBranch);
    } finally {
      myMirrorManager.unlockDir(mirrorDir);
    }
  }

  private String getMirrorUrl(@NotNull HgVcsRoot root) throws VcsException {
    try {
      return myMirrorManager.getMirrorDir(root.getRepository()).getCanonicalPath();
    } catch (IOException e) {
      throw new VcsException(e);
    }
  }
}