changeset 783:d60aa99940ba Gaya-8.1.x

TW-36113 retrieve bookmarks with repository lock held
author Dmitry Neverov <dmitry.neverov@gmail.com>
date Thu, 17 Apr 2014 19:56:05 +0200
parents 3cd449e58f70
children f0327df85b9d 83e1fb5aa843
files mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/CheckoutRepository.java mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialCollectChangesPolicy.java mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialCommitsInfoBuilderSupport.java mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/VcsCallable.java
diffstat 5 files changed, 90 insertions(+), 34 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/CheckoutRepository.java	Wed Apr 16 18:12:04 2014 +0200
+++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/CheckoutRepository.java	Thu Apr 17 19:56:05 2014 +0200
@@ -54,6 +54,7 @@
     myPullTimeout = pullTimeout;
     myRoot = root;
     myWorkingDir = workingDir;
+    myGlobalTagsAsBranches = globalTagsAsBranches;
   }
 
   public CheckoutRepository setRevision(String revision) {
@@ -73,13 +74,7 @@
   private void checkout(@NotNull HgVcsRoot root,
                         @NotNull File workingDir,
                         @Nullable String revision) throws VcsException {
-    updateRepository(root, workingDir, revision);
-    if (revision == null && myBranch != null) {
-      HgRepo repo = myHgRepoFactory.createRepo(root, workingDir);
-      boolean includeTags = myGlobalTagsAsBranches && root.useTagsAsBranches();
-      Map<String, String> revisions = repo.getBranchRevisions(true, includeTags);
-      revision = revisions.get(myBranch);
-    }
+    revision = updateRepository(root, workingDir, revision);
     if (revision == null)
       return;
     updateSubrepos(root, workingDir, revision);
@@ -87,14 +82,15 @@
   }
 
 
-  private void updateRepository(@NotNull HgVcsRoot root,
-                                @NotNull File workingDir,
-                                @Nullable String revision) throws VcsException {
+  @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;
+      return revision;
 
-    updateMirror(root, revision);
+    String rev = updateMirror(root, revision);
     String mirrorUrl = getMirrorUrl(root);
 
     if (repo.isValidRepository()) {
@@ -108,6 +104,7 @@
 
       repo.setDefaultPath(root.getRepository());
     }
+    return rev;
   }
 
 
@@ -163,24 +160,42 @@
   }
 
 
-  private void updateMirror(@NotNull HgVcsRoot root, @Nullable String revision) throws VcsException {
+  /**
+   * @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);
-    HgRepo repo = myHgRepoFactory.createRepo(root, mirrorDir);
-    if (revision != null && repo.containsRevision(revision)) {
-      return;
-    }
+    myMirrorManager.lockDir(mirrorDir);
+    try {
+      HgRepo repo = myHgRepoFactory.createRepo(root, mirrorDir);
+      if (revision != null && repo.containsRevision(revision)) {
+        return revision;
+      }
 
-    if (repo.isValidRepository()) {
-      repo.pull().fromRepository(root.getRepository())
-              .withTimeout(myPullTimeout)
-              .call();
-    } else {
-      repo.doClone().fromRepository(root.getRepository())
-              .setUpdateWorkingDir(false)
-              .useUncompressedTransfer(root.isUncompressedTransfer())
-              .call();
-      repo.setDefaultPath(root.getRepository());
+      if (repo.isValidRepository()) {
+        repo.pull().fromRepository(root.getRepository())
+                .withTimeout(myPullTimeout)
+                .call();
+      } else {
+        repo.doClone().fromRepository(root.getRepository())
+                .setUpdateWorkingDir(false)
+                .useUncompressedTransfer(root.isUncompressedTransfer())
+                .call();
+        repo.setDefaultPath(root.getRepository());
+      }
+
+      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);
     }
   }
 
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialCollectChangesPolicy.java	Wed Apr 16 18:12:04 2014 +0200
+++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialCollectChangesPolicy.java	Thu Apr 17 19:56:05 2014 +0200
@@ -60,9 +60,12 @@
 
   @NotNull
   public RepositoryStateData getCurrentState(@NotNull VcsRoot root) throws VcsException {
-    HgVcsRoot hgRoot = myHgVcsRootFactory.createHgRoot(root);
-    myVcs.syncRepository(hgRoot);
-    final Map<String, String> revisions = getHeads(hgRoot);
+    final HgVcsRoot hgRoot = myHgVcsRootFactory.createHgRoot(root);
+    Map<String, String> revisions = myVcs.syncRepository(hgRoot, new VcsCallable<Map<String, String>>() {
+      public Map<String, String> call() throws VcsException {
+        return getHeads(hgRoot);
+      }
+    });
     String defaultBranchName = hgRoot.getBranchName();
     if (revisions.get(defaultBranchName) == null) {
       throw new VcsException("Cannot find revision of the default branch '" +
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialCommitsInfoBuilderSupport.java	Wed Apr 16 18:12:04 2014 +0200
+++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialCommitsInfoBuilderSupport.java	Thu Apr 17 19:56:05 2014 +0200
@@ -59,9 +59,11 @@
 
     final HgVcsRoot hgRoot = myHgVcsRootFactory.createHgRoot(root);
     final ServerHgRepo repo = mySupport.createRepo(hgRoot);
-    mySupport.syncRepository(hgRoot);
-
-    final MultiMapToList<String, String> heads = commitToBranchs(mySupport.getCollectChangesPolicy().getHeads(hgRoot));
+    final MultiMapToList<String, String> heads = mySupport.syncRepository(hgRoot, new VcsCallable<MultiMapToList<String, String>>() {
+      public MultiMapToList<String, String> call() throws VcsException {
+        return commitToBranchs(mySupport.getCollectChangesPolicy().getHeads(hgRoot));
+      }
+    });
     repo.logSubstates().call(new CommitsAndMountPointsCommand.Callback() {
       private final MercurialCommitsInfoBuilderStates subs = new MercurialCommitsInfoBuilderStates();
 
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java	Wed Apr 16 18:12:04 2014 +0200
+++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java	Thu Apr 17 19:56:05 2014 +0200
@@ -494,6 +494,10 @@
   }
 
   public void syncRepository(@NotNull final HgVcsRoot root) throws VcsException {
+    syncRepository(root, VcsCallable.NO_OP);
+  }
+
+  public <T> T syncRepository(@NotNull HgVcsRoot root, @NotNull VcsCallable<T> cmd) throws VcsException {
     File workingDir = getWorkingDir(root);
     lockWorkDir(workingDir);
     HgRepo repo = createRepo(root);
@@ -520,6 +524,7 @@
                 .call();
         repo.setDefaultPath(root.getRepository());
       }
+      return cmd.call();
     } finally {
       unlockWorkDir(workingDir);
     }
@@ -638,7 +643,7 @@
     return label.replace(':', '_').replace('\r', '_').replace('\n', '_');
   }
 
-  public File getWorkingDir(HgVcsRoot root) {
+  public File getWorkingDir(@NotNull HgVcsRoot root) {
     File customDir = root.getCustomWorkingDir();
     return customDir != null ? customDir : myMirrorManager.getMirrorDir(root.getRepository());
   }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/VcsCallable.java	Thu Apr 17 19:56:05 2014 +0200
@@ -0,0 +1,31 @@
+/*
+ * 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.vcs.VcsException;
+
+import java.util.concurrent.Callable;
+
+public interface VcsCallable<T> extends Callable<T> {
+  VcsCallable<Void> NO_OP = new VcsCallable<Void>() {
+    public Void call() throws VcsException {
+      return null;
+    }
+  };
+
+  public T call() throws VcsException;
+}