changeset 355:69d66e4f60e3

Extract MirrorManager interface
author Dmitry Neverov <dmitry.neverov@jetbrains.com>
date Fri, 27 Jan 2012 15:27:49 +0400
parents 5b3280c0fb2f
children 53b430731041 262b57d2b94f
files mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialAgentSideVcsSupport.java mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MirrorManager.java mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MirrorManagerImpl.java mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MirrorManagerTest.java mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/SettingsTest.java mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/BaseCommandTestCase.java
diffstat 7 files changed, 316 insertions(+), 278 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialAgentSideVcsSupport.java	Mon Jan 23 13:21:27 2012 +0400
+++ b/mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialAgentSideVcsSupport.java	Fri Jan 27 15:27:49 2012 +0400
@@ -37,7 +37,7 @@
                                       @NotNull final HgPathProvider hgPathProvider) {
     myConfig = pluginConfig;
     myHgPathProvider = hgPathProvider;
-    myMirrorManager = new MirrorManager(myConfig.getCachesDir());
+    myMirrorManager = new MirrorManagerImpl(myConfig);
   }
 
   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 {
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MirrorManager.java	Mon Jan 23 13:21:27 2012 +0400
+++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MirrorManager.java	Fri Jan 27 15:27:49 2012 +0400
@@ -1,46 +1,14 @@
 package jetbrains.buildServer.buildTriggers.vcs.mercurial;
 
-import com.intellij.openapi.diagnostic.Logger;
-import jetbrains.buildServer.util.FileUtil;
-import jetbrains.buildServer.util.Hash;
 import org.jetbrains.annotations.NotNull;
 
 import java.io.File;
-import java.io.IOException;
-import java.util.*;
-import java.util.concurrent.locks.ReadWriteLock;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-
-import static jetbrains.buildServer.util.FileUtil.isEmptyDir;
+import java.util.List;
 
 /**
- * Manages local mirrors of remote repositories.
- * Each unique url get unique local mirror. Each mirror is used for one url only.
  * @author dmitry.neverov
  */
-public final class MirrorManager {
-
-  private static Logger LOG = Logger.getInstance(MirrorManager.class.getName());
-  private static final String MIRROR_DIR_PREFIX = "hg_";
-  private static final String MAPPING_FILE_NAME = "map";
-
-  private final ReadWriteLock myLock = new ReentrantReadWriteLock();
-  private final File myRootDir;
-  /*Only one thread read or write to this file, it is protected by myLock.writeLock()*/
-  private final File myMappingFile;
-  /*Protected by myLock*/
-  private final Map<String, File> myMirrors = new HashMap<String, File>();
-  private HashCalculator myHash = new StandartHash();
-
-  /**
-   * @param rootDir root directory where all mirrors are stored
-   */
-  public MirrorManager(File rootDir) {
-    myRootDir = rootDir;
-    myMappingFile = new File(myRootDir, MAPPING_FILE_NAME);
-    readMappingFromFile();
-  }
-
+public interface MirrorManager {
 
   /**
    * Get directory of local mirror repository for specified url, if directory is not exists it is created
@@ -48,29 +16,14 @@
    * @return see above
    */
   @NotNull
-  public File getMirrorDir(@NotNull final String url) {
-    File result = getMirrorDirWithLock(url);
-    if (result == null) {
-      result = createDirFor(url);
-    }
-    return result;
-  }
-
+  public File getMirrorDir(@NotNull final String url);
 
   /**
    * Get all local mirror repository dirs
    * @return see above
    */
   @NotNull
-  public List<File> getMirrors() {
-    myLock.readLock().lock();
-    try {
-      return new ArrayList<File>(myMirrors.values());
-    } finally {
-      myLock.readLock().unlock();
-    }
-  }
-
+  public List<File> getMirrors();
 
   /**
    * Forget specified dir. After call to this method with non-empty dir,
@@ -80,201 +33,6 @@
    *
    * @param dir dir of interest
    */
-  public void forgetDir(@NotNull final File dir) {
-    myLock.writeLock().lock();
-    try {
-      removeMappingsToDir(dir);
-      saveMappingToFile();
-    } finally {
-      myLock.writeLock().unlock();
-    }
-  }
-
-  private void removeMappingsToDir(@NotNull final File dir) {
-    Set<String> keysToRemove = getUrlsMappedToDir(dir);
-    for (String key : keysToRemove) {
-      myMirrors.remove(key);
-    }
-  }
-
-  private Set<String> getUrlsMappedToDir(@NotNull final File dir) {
-    Set<String> urlsMappedToDir = new HashSet<String>();
-    for (Map.Entry<String, File> entry : myMirrors.entrySet()) {
-      File f = entry.getValue();
-      if (f.equals(dir))
-        urlsMappedToDir.add(entry.getKey());
-    }
-    return urlsMappedToDir;
-  }
-
-
-  //for tests only
-  void setHashCalculator(HashCalculator hash) {
-    myHash = hash;
-  }
-
-
-  private File createDirFor(String url) {
-    File result;
-    myLock.writeLock().lock();
-    try {
-      File mirrorDir = getUniqueDir(url);
-      result = saveMappingIfAbsent(url, mirrorDir);
-    } finally {
-      myLock.writeLock().unlock();
-    }
-    if (!result.exists()) {
-      result.mkdirs();
-    }
-    return result;
-  }
-
-
-  private File getMirrorDirWithLock(String url) {
-    myLock.readLock().lock();
-    try {
-      return myMirrors.get(url);
-    } finally {
-      myLock.readLock().unlock();
-    }
-  }
-
-
-  //should be called with myLock.writeLock() held
-  private File saveMappingIfAbsent(String url, File mirrorDir) {
-    File existing = myMirrors.get(url);
-    if (existing != null) {
-      return existing;
-    } else {
-      myMirrors.put(url, mirrorDir);
-      saveMappingToFile();
-      return mirrorDir;
-    }
-  }
-
-
-  private File getUniqueDir(String url) {
-    myLock.readLock().lock();
-    try {
-      String dirName = MIRROR_DIR_PREFIX + hash(normalize(url));
-      File result = PathUtil.getCanonicalFile(new File(myRootDir, dirName));
-      while (isUsedForOtherUrl(result, url) || !isEmptyDir(result)) {
-        dirName = MIRROR_DIR_PREFIX + hash(result.getName());
-        result = PathUtil.getCanonicalFile(new File(myRootDir, dirName));
-      }
-      return result;
-    } finally {
-      myLock.readLock().unlock();
-    }
-  }
-
+  public void forgetDir(@NotNull final File dir);
 
-  private boolean isUsedForOtherUrl(File repositoryDir, String url) {
-    myLock.readLock().lock();
-    try {
-      for (Map.Entry<String, File> mirror : myMirrors.entrySet()) {
-        String mirrorUrl = mirror.getKey();
-        File mirrorDir = mirror.getValue();
-        if (mirrorDir.equals(repositoryDir) && !mirrorUrl.equals(url)) {
-          return true;
-        }
-      }
-      return false;
-    } finally {
-      myLock.readLock().unlock();
-    }
-  }
-
-
-  private String hash(String value) {
-    return String.valueOf(myHash.calc(value));
-  }
-
-
-  private static String normalize(final String path) {
-    String normalized = PathUtil.normalizeSeparator(path);
-    if (path.endsWith("/")) {
-      return normalized.substring(0, normalized.length()-1);
-    }
-    return normalized;
-  }
-
-
-  private void readMappingFromFile() {
-    myLock.writeLock().lock();
-    try {
-      LOG.debug("Parse mapping file " + myMappingFile.getAbsolutePath());
-      for (String line : readLines()) {
-        int separatorIndex = line.lastIndexOf(" = ");
-        if (separatorIndex == -1) {
-          if (!line.equals(""))
-            LOG.warn("Cannot parse mapping '" + line + "', skip it.");
-        } else {
-          String url = line.substring(0, separatorIndex);
-          String dirName = line.substring(separatorIndex + 3);
-          File repositoryDir = PathUtil.getCanonicalFile(new File(myRootDir, dirName));
-          if (isUsedForOtherUrl(repositoryDir, url)) {
-            LOG.error("Skip mapping " + line + ": " + dirName + " is used for url other than " + url);
-          } else {
-            myMirrors.put(url, PathUtil.getCanonicalFile(new File(myRootDir, dirName)));
-          }
-        }
-      }
-    } finally {
-      myLock.writeLock().unlock();
-    }
-  }
-
-  /*Should be called with myLock.writeLock() held*/
-  private List<String> readLines() {
-    if (myMappingFile.exists()) {
-      try {
-        return FileUtil.readFile(myMappingFile);
-      } catch (IOException e) {
-        LOG.error("Error while reading a mapping file at " + myMappingFile.getAbsolutePath() + " starting with empty mapping", e);
-        return new ArrayList<String>();
-      }
-    } else {
-      LOG.debug("No mapping file found at " + myMappingFile.getAbsolutePath() + " starting with empty mapping");
-      File parentDir = myMappingFile.getParentFile();
-      if (!parentDir.exists() && !parentDir.mkdirs()) {
-        LOG.error("Cannot create local mirrors dir at " + parentDir.getAbsolutePath());
-      } else {
-        try {
-          if (!myMappingFile.createNewFile())
-            LOG.warn("Someone else creates a mapping file " + myMappingFile.getAbsolutePath() + ", will use it");
-        } catch (IOException e) {
-          LOG.error("Cannot create a mapping file at " + myMappingFile.getAbsolutePath(), e);
-        }
-      }
-      return new ArrayList<String>();
-    }
-  }
-
-
-  private void saveMappingToFile() {
-    myLock.writeLock().lock();
-    try {
-      StringBuilder sb = new StringBuilder();
-      for (Map.Entry<String, File> mirror : myMirrors.entrySet()) {
-        String url = mirror.getKey();
-        String dir = mirror.getValue().getName();
-        sb.append(url).append(" = ").append(dir).append("\n");
-      }
-      FileUtil.writeFile(myMappingFile, sb.toString());
-    } finally {
-      myLock.writeLock().unlock();
-    }
-  }
-
-
-  final static class StandartHash implements HashCalculator {
-    public long calc(String value) {
-      return Hash.calc(value);
-    }
-  }
-
-  public static interface HashCalculator {
-    long calc(String value);
-  }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MirrorManagerImpl.java	Fri Jan 27 15:27:49 2012 +0400
@@ -0,0 +1,277 @@
+package jetbrains.buildServer.buildTriggers.vcs.mercurial;
+
+import com.intellij.openapi.diagnostic.Logger;
+import jetbrains.buildServer.util.FileUtil;
+import jetbrains.buildServer.util.Hash;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import static jetbrains.buildServer.util.FileUtil.isEmptyDir;
+
+/**
+ * Manages local mirrors of remote repositories.
+ * Each unique url get unique local mirror. Each mirror is used for one url only.
+ * @author dmitry.neverov
+ */
+public final class MirrorManagerImpl implements MirrorManager {
+
+  private static Logger LOG = Logger.getInstance(MirrorManagerImpl.class.getName());
+  private static final String MIRROR_DIR_PREFIX = "hg_";
+  private static final String MAPPING_FILE_NAME = "map";
+
+  private final ReadWriteLock myLock = new ReentrantReadWriteLock();
+  private final File myRootDir;
+  /*Only one thread read or write to this file, it is protected by myLock.writeLock()*/
+  private final File myMappingFile;
+  /*Protected by myLock*/
+  private final Map<String, File> myMirrors = new HashMap<String, File>();
+  private HashCalculator myHash = new StandartHash();
+
+  public MirrorManagerImpl(@NotNull PluginConfig config) {
+    myRootDir = config.getCachesDir();
+    myMappingFile = new File(myRootDir, MAPPING_FILE_NAME);
+    readMappingFromFile();
+  }
+
+
+  /**
+   * Get directory of local mirror repository for specified url, if directory is not exists it is created
+   * @param url url of interest
+   * @return see above
+   */
+  @NotNull
+  public File getMirrorDir(@NotNull final String url) {
+    File result = getMirrorDirWithLock(url);
+    if (result == null) {
+      result = createDirFor(url);
+    }
+    return result;
+  }
+
+
+  /**
+   * Get all local mirror repository dirs
+   * @return see above
+   */
+  @NotNull
+  public List<File> getMirrors() {
+    myLock.readLock().lock();
+    try {
+      return new ArrayList<File>(myMirrors.values());
+    } finally {
+      myLock.readLock().unlock();
+    }
+  }
+
+
+  /**
+   * Forget specified dir. After call to this method with non-empty dir,
+   * all urls which were mapped to this dir will be mapped to another.
+   * If dir is empty, subsequent call getMirrorDir(dir) will return the
+   * same dir.
+   *
+   * @param dir dir of interest
+   */
+  public void forgetDir(@NotNull final File dir) {
+    myLock.writeLock().lock();
+    try {
+      removeMappingsToDir(dir);
+      saveMappingToFile();
+    } finally {
+      myLock.writeLock().unlock();
+    }
+  }
+
+  private void removeMappingsToDir(@NotNull final File dir) {
+    Set<String> keysToRemove = getUrlsMappedToDir(dir);
+    for (String key : keysToRemove) {
+      myMirrors.remove(key);
+    }
+  }
+
+  private Set<String> getUrlsMappedToDir(@NotNull final File dir) {
+    Set<String> urlsMappedToDir = new HashSet<String>();
+    for (Map.Entry<String, File> entry : myMirrors.entrySet()) {
+      File f = entry.getValue();
+      if (f.equals(dir))
+        urlsMappedToDir.add(entry.getKey());
+    }
+    return urlsMappedToDir;
+  }
+
+
+  //for tests only
+  void setHashCalculator(HashCalculator hash) {
+    myHash = hash;
+  }
+
+
+  private File createDirFor(String url) {
+    File result;
+    myLock.writeLock().lock();
+    try {
+      File mirrorDir = getUniqueDir(url);
+      result = saveMappingIfAbsent(url, mirrorDir);
+    } finally {
+      myLock.writeLock().unlock();
+    }
+    if (!result.exists()) {
+      result.mkdirs();
+    }
+    return result;
+  }
+
+
+  private File getMirrorDirWithLock(String url) {
+    myLock.readLock().lock();
+    try {
+      return myMirrors.get(url);
+    } finally {
+      myLock.readLock().unlock();
+    }
+  }
+
+
+  //should be called with myLock.writeLock() held
+  private File saveMappingIfAbsent(String url, File mirrorDir) {
+    File existing = myMirrors.get(url);
+    if (existing != null) {
+      return existing;
+    } else {
+      myMirrors.put(url, mirrorDir);
+      saveMappingToFile();
+      return mirrorDir;
+    }
+  }
+
+
+  private File getUniqueDir(String url) {
+    myLock.readLock().lock();
+    try {
+      String dirName = MIRROR_DIR_PREFIX + hash(normalize(url));
+      File result = PathUtil.getCanonicalFile(new File(myRootDir, dirName));
+      while (isUsedForOtherUrl(result, url) || !isEmptyDir(result)) {
+        dirName = MIRROR_DIR_PREFIX + hash(result.getName());
+        result = PathUtil.getCanonicalFile(new File(myRootDir, dirName));
+      }
+      return result;
+    } finally {
+      myLock.readLock().unlock();
+    }
+  }
+
+
+  private boolean isUsedForOtherUrl(File repositoryDir, String url) {
+    myLock.readLock().lock();
+    try {
+      for (Map.Entry<String, File> mirror : myMirrors.entrySet()) {
+        String mirrorUrl = mirror.getKey();
+        File mirrorDir = mirror.getValue();
+        if (mirrorDir.equals(repositoryDir) && !mirrorUrl.equals(url)) {
+          return true;
+        }
+      }
+      return false;
+    } finally {
+      myLock.readLock().unlock();
+    }
+  }
+
+
+  private String hash(String value) {
+    return String.valueOf(myHash.calc(value));
+  }
+
+
+  private static String normalize(final String path) {
+    String normalized = PathUtil.normalizeSeparator(path);
+    if (path.endsWith("/")) {
+      return normalized.substring(0, normalized.length()-1);
+    }
+    return normalized;
+  }
+
+
+  private void readMappingFromFile() {
+    myLock.writeLock().lock();
+    try {
+      LOG.debug("Parse mapping file " + myMappingFile.getAbsolutePath());
+      for (String line : readLines()) {
+        int separatorIndex = line.lastIndexOf(" = ");
+        if (separatorIndex == -1) {
+          if (!line.equals(""))
+            LOG.warn("Cannot parse mapping '" + line + "', skip it.");
+        } else {
+          String url = line.substring(0, separatorIndex);
+          String dirName = line.substring(separatorIndex + 3);
+          File repositoryDir = PathUtil.getCanonicalFile(new File(myRootDir, dirName));
+          if (isUsedForOtherUrl(repositoryDir, url)) {
+            LOG.error("Skip mapping " + line + ": " + dirName + " is used for url other than " + url);
+          } else {
+            myMirrors.put(url, PathUtil.getCanonicalFile(new File(myRootDir, dirName)));
+          }
+        }
+      }
+    } finally {
+      myLock.writeLock().unlock();
+    }
+  }
+
+  /*Should be called with myLock.writeLock() held*/
+  private List<String> readLines() {
+    if (myMappingFile.exists()) {
+      try {
+        return FileUtil.readFile(myMappingFile);
+      } catch (IOException e) {
+        LOG.error("Error while reading a mapping file at " + myMappingFile.getAbsolutePath() + " starting with empty mapping", e);
+        return new ArrayList<String>();
+      }
+    } else {
+      LOG.debug("No mapping file found at " + myMappingFile.getAbsolutePath() + " starting with empty mapping");
+      File parentDir = myMappingFile.getParentFile();
+      if (!parentDir.exists() && !parentDir.mkdirs()) {
+        LOG.error("Cannot create local mirrors dir at " + parentDir.getAbsolutePath());
+      } else {
+        try {
+          if (!myMappingFile.createNewFile())
+            LOG.warn("Someone else creates a mapping file " + myMappingFile.getAbsolutePath() + ", will use it");
+        } catch (IOException e) {
+          LOG.error("Cannot create a mapping file at " + myMappingFile.getAbsolutePath(), e);
+        }
+      }
+      return new ArrayList<String>();
+    }
+  }
+
+
+  private void saveMappingToFile() {
+    myLock.writeLock().lock();
+    try {
+      StringBuilder sb = new StringBuilder();
+      for (Map.Entry<String, File> mirror : myMirrors.entrySet()) {
+        String url = mirror.getKey();
+        String dir = mirror.getValue().getName();
+        sb.append(url).append(" = ").append(dir).append("\n");
+      }
+      FileUtil.writeFile(myMappingFile, sb.toString());
+    } finally {
+      myLock.writeLock().unlock();
+    }
+  }
+
+
+  final static class StandartHash implements HashCalculator {
+    public long calc(String value) {
+      return Hash.calc(value);
+    }
+  }
+
+  public static interface HashCalculator {
+    long calc(String value);
+  }
+}
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java	Mon Jan 23 13:21:27 2012 +0400
+++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java	Fri Jan 27 15:27:49 2012 +0400
@@ -60,7 +60,7 @@
   private ConcurrentMap<String, Lock> myWorkDirLocks= new ConcurrentHashMap<String, Lock>();
   private VcsManager myVcsManager;
   private File myDefaultWorkFolderParent;
-  private MirrorManager myMirrorManager;
+  private final MirrorManager myMirrorManager;
   private final ServerPluginConfig myConfig;
   private final HgPathProvider myHgPathProvider;
   private final CommandFactory myCommandFactory;
@@ -76,7 +76,7 @@
     myVcsManager = vcsManager;
     myConfig = config;
     myDefaultWorkFolderParent = myConfig.getCachesDir();
-    myMirrorManager = new MirrorManager(myDefaultWorkFolderParent);
+    myMirrorManager = new MirrorManagerImpl(config);
     myHgPathProvider = hgPathProvider;
     myCommandFactory = commandFactory;
     dispatcher.addListener(new BuildServerAdapter() {
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MirrorManagerTest.java	Mon Jan 23 13:21:27 2012 +0400
+++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MirrorManagerTest.java	Fri Jan 27 15:27:49 2012 +0400
@@ -3,6 +3,7 @@
 import jetbrains.buildServer.TempFiles;
 import jetbrains.buildServer.util.Hash;
 import junit.framework.TestCase;
+import org.jetbrains.annotations.NotNull;
 import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
@@ -19,14 +20,19 @@
 
   private TempFiles myTempFiles;
   private File myRootDir;
-  private MirrorManager myManager;
+  private MirrorManagerImpl myManager;
 
 
   @BeforeMethod
   public void setUp() throws Exception {
     myTempFiles = new TempFiles();
     myRootDir = myTempFiles.createTempDir();
-    myManager = new MirrorManager(myRootDir);
+    myManager = new MirrorManagerImpl(new PluginConfig() {
+      @NotNull
+      public File getCachesDir() {
+        return myRootDir;
+      }
+    });
   }
 
   @AfterMethod
@@ -67,7 +73,7 @@
     final String url1 = "hg://some.com/repository.hg";
     final String url2 = "hg://other.com/repository.hg";
 
-    MirrorManager.HashCalculator hashWithCollision = new MirrorManager.HashCalculator() {
+    MirrorManagerImpl.HashCalculator hashWithCollision = new MirrorManagerImpl.HashCalculator() {
       public long calc(String value) {
         if (value.equals(url1) || value.equals(url2)) {
           return 0;//emulate collision
@@ -78,11 +84,23 @@
     };
 
     //alone they get dir with the same name:
-    MirrorManager mm1 = new MirrorManager(myTempFiles.createTempDir());
+    final File dir1 = myTempFiles.createTempDir();
+    MirrorManagerImpl mm1 = new MirrorManagerImpl(new PluginConfig() {
+      @NotNull
+      public File getCachesDir() {
+        return dir1;
+      }
+    });
     mm1.setHashCalculator(hashWithCollision);
     File separateMirrorDir1 = mm1.getMirrorDir(url1);
 
-    MirrorManager mm2 = new MirrorManager(myTempFiles.createTempDir());
+    final File dir2 = myTempFiles.createTempDir();
+    MirrorManagerImpl mm2 = new MirrorManagerImpl(new PluginConfig() {
+      @NotNull
+      public File getCachesDir() {
+        return dir2;
+      }
+    });
     mm2.setHashCalculator(hashWithCollision);
     File separateMirrorDir2 = mm2.getMirrorDir(url2);
 
@@ -102,7 +120,12 @@
     File mirrorDir2 = myManager.getMirrorDir(url2);
 
     //emulate restart by creating a new manager for the same rootDir
-    MirrorManager manager = new MirrorManager(myRootDir);
+    MirrorManagerImpl manager = new MirrorManagerImpl(new PluginConfig() {
+      @NotNull
+      public File getCachesDir() {
+        return myRootDir;
+      }
+    });
 
     assertEquals(2, manager.getMirrors().size());
     assertTrue(manager.getMirrors().contains(mirrorDir1));
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/SettingsTest.java	Mon Jan 23 13:21:27 2012 +0400
+++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/SettingsTest.java	Fri Jan 27 15:27:49 2012 +0400
@@ -15,14 +15,11 @@
  */
 package jetbrains.buildServer.buildTriggers.vcs.mercurial;
 
-import jetbrains.buildServer.TempFiles;
 import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.Settings;
 import jetbrains.buildServer.vcs.VcsRoot;
 import jetbrains.buildServer.vcs.impl.VcsRootImpl;
 import junit.framework.TestCase;
 import org.jetbrains.annotations.NotNull;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
 /**
@@ -31,21 +28,6 @@
 @Test
 public class SettingsTest extends TestCase {
 
-  private TempFiles myTempFiles = new TempFiles();
-  private MirrorManager myMirrorManager;
-
-  @Override
-  @BeforeMethod
-  public void setUp() throws Exception {
-    myMirrorManager = new MirrorManager(myTempFiles.createTempDir());
-  }
-
-  @Override
-  @AfterMethod
-  public void tearDown() throws Exception {
-    myTempFiles.cleanup();
-  }
-
   public void test_url_without_credentials() {
     VcsRootImpl vcsRoot = createVcsRoot("http://host.com/path");
     Settings settings = createSettings(vcsRoot);
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/BaseCommandTestCase.java	Mon Jan 23 13:21:27 2012 +0400
+++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/BaseCommandTestCase.java	Fri Jan 27 15:27:49 2012 +0400
@@ -69,11 +69,9 @@
     }
 
     TempFiles tf = new TempFiles();
-    File parentDir = tf.createTempDir();
-
-    MirrorManager mirrorManager = new MirrorManager(parentDir);
     VcsRoot vcsRoot = new VcsRootImpl(1, vcsRootProps);
-    ServerPluginConfig config = new ServerPluginConfigBuilder().build();
+    ServerPluginConfig config = new ServerPluginConfigBuilder().cachesDir(tf.createTempDir()).build();
+    MirrorManager mirrorManager = new MirrorManagerImpl(config);
     Settings settings = new Settings(new ServerHgPathProvider(config), vcsRoot);
     final File workingDir = mirrorManager.getMirrorDir(settings.getRepositoryUrlWithCredentials());
     settings.setCustomWorkingDir(workingDir);