changeset 846:cea91fa66d3b

Support sharing local mirror clones on agent
author Dmitry Neverov <dmitry.neverov@jetbrains.com>
date Mon, 30 Jun 2014 21:02:29 +0200
parents 07a3d55dda1b
children fbd8e6725fe5
files mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentPluginConfig.java mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentPluginConfigImpl.java mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialAgentSideVcsSupport.java mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialIncludeRuleUpdater.java mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/SharingMercurialUpdater.java
diffstat 5 files changed, 108 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentPluginConfig.java	Wed Jun 25 21:43:40 2014 +0200
+++ b/mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentPluginConfig.java	Mon Jun 30 21:02:29 2014 +0200
@@ -26,6 +26,8 @@
 
   boolean isUseLocalMirrors(@NotNull AgentRunningBuild build);
 
+  boolean shareLocalMirrors(@NotNull AgentRunningBuild build);
+
   int getPullTimeout(@NotNull AgentRunningBuild build);
 
   boolean runWithTraceback(@NotNull AgentRunningBuild build);
--- a/mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentPluginConfigImpl.java	Wed Jun 25 21:43:40 2014 +0200
+++ b/mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentPluginConfigImpl.java	Mon Jun 30 21:02:29 2014 +0200
@@ -18,6 +18,7 @@
 
 import jetbrains.buildServer.agent.AgentRunningBuild;
 import jetbrains.buildServer.agent.BuildAgentConfiguration;
+import jetbrains.buildServer.util.StringUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -29,7 +30,7 @@
 public class AgentPluginConfigImpl implements AgentPluginConfig {
 
   private static final String PULL_TIMEOUT_SECONDS = "teamcity.hg.pull.timeout.seconds";
-  private final int DEFAULT_PULL_TIMEOUT_SECONDS = 3600;
+  private static final int DEFAULT_PULL_TIMEOUT_SECONDS = 3600;
 
   private final BuildAgentConfiguration myAgentConfig;
 
@@ -41,6 +42,15 @@
     return Boolean.valueOf(build.getSharedConfigParameters().get("teamcity.hg.use.local.mirrors"));
   }
 
+  @SuppressWarnings("ConstantConditions")
+  public boolean shareLocalMirrors(@NotNull AgentRunningBuild build) {
+    boolean defaultValue = false;
+    String buildValue = build.getSharedConfigParameters().get("teamcity.hg.shareLocalMirrors");
+    if (buildValue == null || StringUtil.isEmpty(buildValue))
+      return defaultValue;
+    return Boolean.valueOf(buildValue);
+  }
+
   @NotNull
   public File getCachesDir() {
     return myAgentConfig.getCacheDirectory("mercurial");
--- a/mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialAgentSideVcsSupport.java	Wed Jun 25 21:43:40 2014 +0200
+++ b/mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialAgentSideVcsSupport.java	Mon Jun 30 21:02:29 2014 +0200
@@ -42,7 +42,11 @@
   }
 
   public IncludeRuleUpdater getUpdater(@NotNull final VcsRoot vcsRoot, @NotNull final CheckoutRules checkoutRules, @NotNull final String toVersion, @NotNull final File checkoutDirectory, @NotNull final AgentRunningBuild build, boolean cleanCheckoutRequested) throws VcsException {
-    return new MercurialIncludeRuleUpdater(myConfig, myMirrorManager, myRepoFactory, vcsRoot, toVersion, build);
+    if (myConfig.isUseLocalMirrors(build) && myConfig.shareLocalMirrors(build)) {
+      return new SharingMercurialUpdater(myConfig, myMirrorManager, myRepoFactory, vcsRoot, toVersion, build);
+    } else {
+      return new MercurialIncludeRuleUpdater(myConfig, myMirrorManager, myRepoFactory, vcsRoot, toVersion, build);
+    }
   }
 
   @NotNull
--- a/mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialIncludeRuleUpdater.java	Wed Jun 25 21:43:40 2014 +0200
+++ b/mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialIncludeRuleUpdater.java	Mon Jun 30 21:02:29 2014 +0200
@@ -42,9 +42,9 @@
  */
 public class MercurialIncludeRuleUpdater implements IncludeRuleUpdater {
 
-  private final MirrorManager myMirrorManager;
-  private final AgentRepoFactory myRepoFactory;
-  private final HgVcsRoot myRoot;
+  protected final MirrorManager myMirrorManager;
+  protected final AgentRepoFactory myRepoFactory;
+  protected final HgVcsRoot myRoot;
   private final AuthSettings myAuthSettings;
   private final String myToVersion;
   private final BuildProgressLogger myLogger;
@@ -116,7 +116,7 @@
   }
 
 
-  private void updateRepository(@NotNull File workingDir) throws VcsException, IOException {
+  protected void updateRepository(@NotNull File workingDir) throws VcsException, IOException {
     String repositoryUrl = getDefaultPullUrl(myRoot, myUseLocalMirrors);
     HgRepo repo = myRepoFactory.createRepo(myRoot, workingDir);
     myLogger.message("Update repository " + workingDir.getAbsolutePath());
@@ -243,7 +243,7 @@
   }
 
 
-  private String getDefaultPullUrl(HgVcsRoot root, boolean useLocalMirror) throws IOException {
+  protected String getDefaultPullUrl(HgVcsRoot root, boolean useLocalMirror) throws IOException {
     if (useLocalMirror) {
       File mirrorDir = myMirrorManager.getMirrorDir(root.getRepository());
       return mirrorDir.getCanonicalPath();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/SharingMercurialUpdater.java	Mon Jun 30 21:02:29 2014 +0200
@@ -0,0 +1,85 @@
+/*
+ * 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());
+
+    File mirrorDir = myMirrorManager.getMirrorDir(myRoot.getRepository());
+    File mirrorHg = new File(mirrorDir, ".hg");
+    String sharedPath = readSharedPath(workingDir);
+    if (mirrorHg.getCanonicalPath().equals(sharedPath)) {
+      writeRequires(mirrorHg, workingDir);
+    } else {
+      writeRequires(mirrorHg, workingDir);
+      writeSharedPath(workingDir, mirrorDir);
+    }
+  }
+
+
+  @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 workingDir, @NotNull File mirrorDir) throws IOException {
+    FileUtil.writeToFile(getSharedPath(workingDir), (new File(mirrorDir, ".hg").getCanonicalPath() + "\n").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");
+  }
+}