changeset 617:cea0fb35f941

Merge branch Gaya-8.0.x
author Dmitry Neverov <dmitry.neverov@gmail.com>
date Thu, 01 Aug 2013 12:06:08 +0400
parents a6c708e5bb10 (current diff) 7a4ecffe34a9 (diff)
children a1c6f85cf715
files
diffstat 7 files changed, 90 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Wed Jul 24 17:19:53 2013 +0200
+++ b/.hgignore	Thu Aug 01 12:06:08 2013 +0400
@@ -5,4 +5,5 @@
 mercurial.properties
 syntax: glob
 .idea/workspace.xml
-out
\ No newline at end of file
+out
+.DS_Store
\ No newline at end of file
--- a/build/ant.build.xml	Wed Jul 24 17:19:53 2013 +0200
+++ b/build/ant.build.xml	Thu Aug 01 12:06:08 2013 +0400
@@ -1,23 +1,30 @@
 <project name="build hooks" default="replace-tokens-in-teamcity-plugin-xml" basedir=".">
 
-
   <target name="replace-tokens-in-teamcity-plugin-xml">
     <property name="home" value="${artifact.output.path}"/>
 
-    <echo message="replacing tokens in teamcity-plugin.xml file under ${home}"/>
+    <tstamp>
+      <format property="timestamp" pattern="yyyyMMddhhmmss"/>
+    </tstamp>
 
-    <condition property="build.number" value="snapshot" else="${build.number}">
-      <not>
-        <isset property="build.number"/>
-      </not>
+    <property name="snapshot.build.number" value="SNAPSHOT-${timestamp}"/>
+
+    <condition property="plugin.version" value="${snapshot.build.number}" else="${build.number}">
+      <or>
+        <not>
+          <isset property="build.number"/>
+        </not>
+        <matches pattern="snapshot-.*" string="${build.number}" casesensitive="false"/>
+      </or>
     </condition>
 
-    <echo message="Setting version to: ${build.number}"/>
+    <echo message="replacing tokens in teamcity-plugin.xml file under ${home}"/>
+    <echo message="Setting version to: ${plugin.version}"/>
+
     <!-- update all references in teamcity-plugin.xml files -->
     <replace dir="${home}" summary="true">
       <include name="**/teamcity-plugin.xml"/>
-
-      <replacefilter token="@Plugin_Version@" value="${build.number}"/>
+      <replacefilter token="@version@" value="${plugin.version}"/>
     </replace>
   </target>
 
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgFileUtil.java	Wed Jul 24 17:19:53 2013 +0200
+++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgFileUtil.java	Thu Aug 01 12:06:08 2013 +0400
@@ -8,12 +8,15 @@
 import java.io.File;
 import java.io.FileFilter;
 import java.io.IOException;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 
 /**
  * @author dmitry.neverov
  */
 public final class HgFileUtil {
 
+  private final static ConcurrentMap<String, Object> myTmpDirLocks = new ConcurrentHashMap<String, Object>();
   private final static String TEMP_DIR_PREFIX = "hg";
 
   private HgFileUtil() {
@@ -28,13 +31,30 @@
     File parentDir = new File(FileUtil.getTempDirectory());
     int suffix = 0;
     File dir;
-    do {
+    while (true) {
       suffix++;
-      dir = new File(parentDir, TEMP_DIR_PREFIX + suffix);
-    } while (dir.exists() || !dir.createNewFile());
-    dir.delete();
-    dir.mkdir();
-    return dir;
+      String tmpDirName = TEMP_DIR_PREFIX + suffix;
+      dir = new File(parentDir, tmpDirName);
+      if (dir.exists())
+        continue;
+
+      synchronized (getTmpDirLock(tmpDirName)) {
+        if (!dir.createNewFile())
+          continue;
+        if (!dir.delete())
+          continue;
+        if (!dir.mkdir())
+          continue;
+      }
+      return dir;
+    }
+  }
+
+
+  private static Object getTmpDirLock(@NotNull String tmpDirName) {
+    Object tmpDirLock = new Object();
+    Object existingLock = myTmpDirLocks.putIfAbsent(tmpDirName, tmpDirLock);
+    return existingLock != null ? existingLock : tmpDirLock;
   }
 
 
--- a/mercurial-tests/mercurial-tests.iml	Wed Jul 24 17:19:53 2013 +0200
+++ b/mercurial-tests/mercurial-tests.iml	Thu Aug 01 12:06:08 2013 +0400
@@ -21,6 +21,7 @@
     <orderEntry type="library" name="TeamCity Vcs Api" level="project" />
     <orderEntry type="module" module-name="mercurial-server-tc" />
     <orderEntry type="library" name="quartz-1.6.0" level="project" />
+    <orderEntry type="library" name="IDEA-openapi" level="project" />
   </component>
 </module>
 
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgFileUtilTest.java	Wed Jul 24 17:19:53 2013 +0200
+++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgFileUtilTest.java	Thu Aug 01 12:06:08 2013 +0400
@@ -1,11 +1,18 @@
 package jetbrains.buildServer.buildTriggers.vcs.mercurial;
 
 
+import jetbrains.buildServer.util.TestFor;
 import org.testng.annotations.Test;
 
 import java.io.File;
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
 
+import static org.testng.AssertJUnit.assertEquals;
 import static org.testng.AssertJUnit.assertFalse;
 
 @Test
@@ -17,4 +24,37 @@
     assertFalse(tmpDir1.getCanonicalPath().equals(tmpDir2.getCanonicalPath()));
   }
 
+
+  @TestFor(issues = "TW-30589")
+  @Test(invocationCount = 10)
+  public void createTempFile_should_always_return_unique_dir() throws Exception {
+    final CountDownLatch allThreadsInitialized = new CountDownLatch(1);
+    final Set<File> tmpFiles = new HashSet<File>();
+    Runnable createTmpFile = new Runnable() {
+      public void run() {
+        try {
+          allThreadsInitialized.await();
+          tmpFiles.add(HgFileUtil.createTempDir());
+        } catch (Exception e) {
+          //ignore
+        }
+      }
+    };
+
+    List<Thread> threads = new ArrayList<Thread>();
+    for (int i = 0; i < 50; i++) {
+      Thread t = new Thread(createTmpFile);
+      t.start();
+      threads.add(t);
+    }
+
+    allThreadsInitialized.countDown();
+
+    for (Thread t : threads) {
+      t.join();
+    }
+
+    assertEquals("Race condition in createTempDir", threads.size(), tmpFiles.size());
+  }
+
 }
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/Util.java	Wed Jul 24 17:19:53 2013 +0200
+++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/Util.java	Thu Aug 01 12:06:08 2013 +0400
@@ -2,6 +2,7 @@
 
 import jetbrains.buildServer.TempFiles;
 import jetbrains.buildServer.util.FileUtil;
+import com.intellij.openapi.util.SystemInfo;
 import jetbrains.buildServer.vcs.CheckoutRules;
 import jetbrains.buildServer.vcs.VcsException;
 import jetbrains.buildServer.vcs.VcsRoot;
@@ -22,11 +23,11 @@
 
   public static String getHgPath() throws IOException {
     String providedHg = System.getenv(Constants.HG_PATH_ENV);
-    if (providedHg != null) {
+    if (providedHg != null)
       return providedHg;
-    } else {
+    if (SystemInfo.isWindows)
       return new File("mercurial-tests/testData/bin/hg.exe").getAbsolutePath();
-    }
+    return "hg"; //assume it is somethere in the $PATH
   }
 
 
--- a/teamcity-plugin.xml	Wed Jul 24 17:19:53 2013 +0200
+++ b/teamcity-plugin.xml	Thu Aug 01 12:06:08 2013 +0400
@@ -4,7 +4,7 @@
   <info>
     <name>mercurial</name>
     <display-name>VCS Support: Mercurial</display-name>
-    <version>@Plugin_Version@</version>
+    <version>@version@</version>
     <vendor>
       <name>JetBrains, s.r.o.</name>
       <url>http://www.jetbrains.com</url>