changeset 982:4a0ea921c214 Indore-2017.2.x

Merge back changes since 28.04.2017
author Dmitry Neverov <dmitry.neverov@gmail.com>
date Wed, 24 Jan 2018 22:02:52 +0100
parents 64b5816390f9 (current diff) 7bf4d943d5bb (diff)
children ea7a543ecf2f
files README.txt mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/Constants.java mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgRepo.java mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgVersion.java mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/HgVcsRoot.java mercurial-dsl/HgVcsRoot.xml mercurial-server/resources/buildServerResources/mercurialSettings.jsp mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialUrlSupport.java mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerHgPathProvider.java mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerHgRepo.java mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/BaseMercurialPatchTestCase.java mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgRepoTest.java mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgVcsRootTest.java mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupportTest.java mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerHgPathProviderTest.java mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/VcsRootBuilder.java
diffstat 18 files changed, 148 insertions(+), 97 deletions(-) [+]
line wrap: on
line diff
--- a/README.txt	Wed Jan 24 21:19:56 2018 +0100
+++ b/README.txt	Wed Jan 24 22:02:52 2018 +0100
@@ -5,4 +5,5 @@
 
 TeamCity 4.x and later
 
-Download mercurial-server.zip and put it into the .BuildServer/plugins folder. Restart server.
\ No newline at end of file
+Download mercurial-server.zip and put it into the .BuildServer/plugins folder. Restart server.
+
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/Constants.java	Wed Jan 24 21:19:56 2018 +0100
+++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/Constants.java	Wed Jan 24 22:02:52 2018 +0100
@@ -45,5 +45,6 @@
   String CUSTOM_CLONE_PATH_ENABLED = "teamcity.hg.customClonePathEnabled";
   String CUSTOM_CLONE_PATH_WHITELIST = "teamcity.hg.customClonePathWhitelist";
   String CUSTOM_CACHES_DIR = "teamcity.hg.customCachesDir";
-  String HG_PATH_WHITELIST = "teamcity.hg.hgPathWhitelist";
+  String CUSTOM_HG_PATH_ENABLED = "teamcity.hg.customHgPathEnabled";
+  String CUSTOM_HG_CONFIG_ENABLED = "teamcity.hg.customConfigEnabled";
 }
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgRepo.java	Wed Jan 24 21:19:56 2018 +0100
+++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgRepo.java	Wed Jan 24 22:02:52 2018 +0100
@@ -242,6 +242,8 @@
   }
 
   public void setDefaultPath(@NotNull String defaultPath) throws VcsException {
+    if (defaultPath.contains("\n") || defaultPath.contains("\r"))
+      throw new VcsException("Newline in repository url '" + defaultPath + "'");
     try {
       File hgrc = new File(new File(myWorkingDir, ".hg"), "hgrc");
       String content = "%include " + Constants.TEAMCITY_HG_CONFIG_FILE_NAME + "\n\n[paths]\ndefault = " + defaultPath;
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgVersion.java	Wed Jan 24 21:19:56 2018 +0100
+++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgVersion.java	Wed Jan 24 22:02:52 2018 +0100
@@ -55,6 +55,11 @@
   }
 
 
+  public boolean isLessThan(@NotNull HgVersion other) {
+    return compareTo(other) < 0;
+  }
+
+
   @Override
   public String toString() {
     return myMajor + "." + myMinor + "." + myThird;
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/HgVcsRoot.java	Wed Jan 24 21:19:56 2018 +0100
+++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/HgVcsRoot.java	Wed Jan 24 22:02:52 2018 +0100
@@ -59,7 +59,7 @@
   public HgVcsRoot(@NotNull Map<String, String> vcsRootProperties) {
     myVcsRootProperties = vcsRootProperties;
     myRepository = getProperty(Constants.REPOSITORY_PROP);
-    myHgCommandPath = getProperty(Constants.HG_COMMAND_PATH_PROP);
+    myHgCommandPath = readHgCommandPath();
     myBranchName = getProperty(Constants.BRANCH_NAME_PROP);
     myCustomClonePath = readCustomClonePath();
     myUncompressedTransfer = "true".equals(getProperty(Constants.UNCOMPRESSED_TRANSFER));
@@ -71,10 +71,27 @@
     myUseArchiveForPatch = Boolean.parseBoolean(getProperty(Constants.USE_ARCHIVE_FOR_PATCH));
     myPurgePolicy = readPurgePolicy(vcsRootProperties);
     myIgnoreMissingDefaultBranch = Boolean.valueOf(getProperty(Constants.IGNORE_MISSING_DEFAULT_BRANCH, "false"));
-    myCustomHgConfig = getProperty(Constants.CUSTOM_HG_CONFIG_PROP, "");
+    myCustomHgConfig = readCustomHgConfig();
     myUseAgentMirrors = readUseSharedMirrors();
   }
 
+  private String readHgCommandPath() {
+    if (TeamCityProperties.getBooleanOrTrue(Constants.CUSTOM_HG_PATH_ENABLED)) {
+      return getProperty(Constants.HG_COMMAND_PATH_PROP, "hg");
+    } else {
+      return "hg";
+    }
+  }
+
+  @NotNull
+  private String readCustomHgConfig() {
+    if (TeamCityProperties.getBooleanOrTrue(Constants.CUSTOM_HG_CONFIG_ENABLED)) {
+      return getProperty(Constants.CUSTOM_HG_CONFIG_PROP, "");
+    } else {
+      return "";
+    }
+  }
+
   @Nullable
   private Boolean readUseSharedMirrors() {
     String prop = getProperty(Constants.USE_AGENT_MIRRORS);
@@ -265,18 +282,4 @@
     }
     return false;
   }
-
-  public static boolean isAllowedHgPath(@Nullable String path) {
-    if (StringUtil.isEmptyOrSpaces(path))
-      return false;
-    String whitelist = TeamCityProperties.getProperty(Constants.HG_PATH_WHITELIST);
-    if (StringUtil.isEmpty(whitelist))
-      return false;
-    List<String> paths = StringUtil.split(whitelist, ";");
-    for (String p : paths) {
-      if (p.equals(path))
-        return true;
-    }
-    return false;
-  }
 }
--- a/mercurial-common/src/python/load-commands-command.py	Wed Jan 24 21:19:56 2018 +0100
+++ b/mercurial-common/src/python/load-commands-command.py	Wed Jan 24 22:02:52 2018 +0100
@@ -52,5 +52,5 @@
 commands.norepo += " CMD"
 
 testedwith = '2.2.2'
-buglink = "@jonnyzzz"
+buglink = "upsource-support@jetbrains.com"
 
--- a/mercurial-common/src/python/load-substates-command.py	Wed Jan 24 21:19:56 2018 +0100
+++ b/mercurial-common/src/python/load-substates-command.py	Wed Jan 24 22:02:52 2018 +0100
@@ -143,6 +143,10 @@
     "load-substates": (load_substates_command, [ ], " [options] OUTPUT_FILE")
 }
 
-testedwith = '2.2.2'
-buglink = "@jonnyzzz"
+load_substates_command.norepo = False
+load_substates_command.optionalrepo = False
+load_substates_command.inferrepo = False
 
+testedwith = '4.2.1'
+buglink = "upsource-support@jetbrains.com"
+
--- a/mercurial-dsl/HgVcsRoot.xml	Wed Jan 24 21:19:56 2018 +0100
+++ b/mercurial-dsl/HgVcsRoot.xml	Wed Jan 24 22:02:52 2018 +0100
@@ -22,7 +22,7 @@
     </description>
   </class>
   <params>
-    <param name="repositoryPath" dslName="url">
+    <param name="repositoryPath" dslName="url" mandatory="true">
       <description>
         Mercurial repository URL
       </description>
--- a/mercurial-server/resources/buildServerResources/mercurialSettings.jsp	Wed Jan 24 21:19:56 2018 +0100
+++ b/mercurial-server/resources/buildServerResources/mercurialSettings.jsp	Wed Jan 24 22:02:52 2018 +0100
@@ -92,7 +92,6 @@
     <td>
       <props:textProperty name="hgCommandPath" className="longField" />
       <span class="error" id="error_hgCommandPath"></span>
-      <div class="smallNote" style="margin: 0;">The path will be used on TeamCity server only if it is included into whitelist.<bs:help file="Mercurial" anchor="Pathtohgexecutabledetection"/></div>
     </td>
   </tr>
   <tr class="advancedSetting">
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialUrlSupport.java	Wed Jan 24 21:19:56 2018 +0100
+++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialUrlSupport.java	Wed Jan 24 22:02:52 2018 +0100
@@ -97,9 +97,10 @@
     }
 
     HttpClient client = HttpUtil.createHttpClient(30);
-    GetMethod get = new GetMethod(capabilitiesUrl);
+    GetMethod get = null;
 
     try {
+      get = new GetMethod(capabilitiesUrl);
       if (credentials != null) {
         URL url = new URL(fetchUrl);
         HttpState state = new HttpState();
@@ -129,7 +130,8 @@
     } catch (Exception e) {
       Loggers.VCS.debug("Got error while sending HTTP request to " + capabilitiesUrl, e);
     } finally {
-      get.releaseConnection();
+      if (get != null)
+        get.releaseConnection();
     }
 
     return false;
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java	Wed Jan 24 21:19:56 2018 +0100
+++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java	Wed Jan 24 22:02:52 2018 +0100
@@ -708,14 +708,26 @@
       syncRepository(hgRoot);
       HgRepo repo = createRepo(hgRoot);
       String branchName = getCommitBranch(repo, version);
-      repo.update().branch(branchName).call();
+      HgVersion hgVersion = repo.version().call();
+      if (hgVersion.isEqualsOrGreaterThan(ServerHgRepo.REVSET_HG_VERSION)) {
+        repo.update().branch("branch('" + branchName + "') and head()").call();
+      } else {
+        repo.update().branch(branchName).call();
+      }
 
       String fixedTagname = fixTagName(label);
-      repo.tag().revision(version)
-              .tagName(fixedTagname)
-              .byUser(hgRoot.getUserForTag())
-              .call();
-
+      try {
+        repo.tag().revision(version)
+                .tagName(fixedTagname)
+                .byUser(hgRoot.getUserForTag())
+                .call();
+      } catch (VcsException e) {
+        String msg = e.getMessage();
+        if (msg != null && msg.contains("not at a branch head") && hgVersion.isLessThan(ServerHgRepo.REVSET_HG_VERSION)) {
+          Loggers.VCS.warn("Please upgrade mercurial to the version supporting revsets(" + ServerHgRepo.REVSET_HG_VERSION + "+), current version: " + hgVersion);
+        }
+        throw e;
+      }
       repo.push().toRepository(hgRoot.getRepository()).call();
       return fixedTagname;
     } finally {
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerHgPathProvider.java	Wed Jan 24 21:19:56 2018 +0100
+++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerHgPathProvider.java	Wed Jan 24 22:02:52 2018 +0100
@@ -33,12 +33,17 @@
 
 
   public String getHgPath(@NotNull final HgVcsRoot root) {
-    String pathFromRoot = root.getHgPath();
-    if (HgVcsRoot.isAllowedHgPath(pathFromRoot)) {
-      return pathFromRoot;
+    String serverWideHgPath = myConfig.getHgPath();
+    if (serverWideHgPath != null) {
+      return serverWideHgPath;
     } else {
-      String serverWideHgPath = myConfig.getHgPath();
-      return serverWideHgPath != null ? serverWideHgPath : "hg";
+      String pathFromRoot = root.getHgPath();
+      if (pathFromRoot.equals(unresolvedAgentHgPath())) {
+        //try to use hg from the PATH:
+        return "hg";
+      } else {
+        return pathFromRoot;
+      }
     }
   }
 
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerHgRepo.java	Wed Jan 24 21:19:56 2018 +0100
+++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerHgRepo.java	Wed Jan 24 22:02:52 2018 +0100
@@ -36,7 +36,7 @@
  */
 public class ServerHgRepo extends HgRepo {
 
-  private final static HgVersion REVSET_HG_VERSION = new HgVersion(1, 7, 0);
+  public final static HgVersion REVSET_HG_VERSION = new HgVersion(1, 7, 0);
   private final CommandSettingsFactory myCommandSettingsFactory;
   private final ServerPluginConfig myConfig;
   protected final MercurialClasspathTemplate myLogTemplate = new MercurialClasspathTemplate("/buildServerResources/log.template", "hg.log.template");
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgRepoTest.java	Wed Jan 24 21:19:56 2018 +0100
+++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgRepoTest.java	Wed Jan 24 22:02:52 2018 +0100
@@ -16,19 +16,19 @@
 
 package jetbrains.buildServer.buildTriggers.vcs.mercurial;
 
-import com.intellij.openapi.diagnostic.Logger;
-import jetbrains.buildServer.TempFiles;
 import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.AuthSettings;
 import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.TestCommandSettingsFactory;
+import jetbrains.buildServer.util.TestFor;
+import jetbrains.buildServer.vcs.VcsException;
+import org.jetbrains.annotations.NotNull;
+import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
 import java.io.File;
 import java.util.List;
 
 import static jetbrains.buildServer.buildTriggers.vcs.mercurial.Util.copyRepository;
-import static org.testng.AssertJUnit.assertEquals;
-import static org.testng.AssertJUnit.assertNull;
-import static org.testng.AssertJUnit.assertTrue;
+import static org.testng.AssertJUnit.*;
 
 @Test
 public class HgRepoTest extends BaseMercurialTestCase {
@@ -58,4 +58,29 @@
     assertEquals(1, changes.size());
   }
 
+
+  @DataProvider(name = "urlsWithNewLines")
+  public static Object[][] urlsWithNewLines() {
+    return new Object[][] {
+            new Object[] { "http://some.org/repo\n" },
+            new Object[] { "http://some.org/repo\r" },
+            new Object[] { "http://some.org/repo\n[section]" },
+            new Object[] { "http://some.org/repo\r[section]" },
+            new Object[] { "http://some.org/repo\r\n[section]" },
+    };
+  }
+
+  @TestFor(issues = "TW-50043")//TW-50043 is about git, but hg suffers from the same problem
+  @Test(dataProvider = "urlsWithNewLines")
+  public void newline_in_url(@NotNull String url) throws Exception {
+    File repository = myTempFiles.createTempDir();
+    HgRepo repo = new HgRepo(new TestCommandSettingsFactory(), repository, Util.getHgPath(), new AuthSettings());
+    repo.init().call();
+    try {
+      repo.setDefaultPath(url);
+      fail("no error for url '" + url + "'");
+    } catch (VcsException e) {
+      //expected
+    }
+  }
 }
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgVcsRootTest.java	Wed Jan 24 21:19:56 2018 +0100
+++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgVcsRootTest.java	Wed Jan 24 22:02:52 2018 +0100
@@ -141,28 +141,27 @@
     assertEquals(hgRoot.getCustomClonePath(), tempDir.getCanonicalPath());
   }
 
-  public void hg_path_whitelist() throws Exception {
-    assertFalse(HgVcsRoot.isAllowedHgPath(null));
-    assertFalse(HgVcsRoot.isAllowedHgPath("/some/path"));
-    setInternalProperty(Constants.HG_PATH_WHITELIST, "/some/path1;/some/path2");
-    assertTrue(HgVcsRoot.isAllowedHgPath("/some/path1"));
-    assertTrue(HgVcsRoot.isAllowedHgPath("/some/path2"));
-    assertFalse(HgVcsRoot.isAllowedHgPath("/some/other/path"));
-    assertFalse(HgVcsRoot.isAllowedHgPath("/some/path11"));
-    assertFalse(HgVcsRoot.isAllowedHgPath("/some/path1/hg"));
+  public void disable_custom_hg_path() throws Exception {
+    VcsRoot root = vcsRoot().withUrl("http://some.org/repo").withHgPath("/some/path").build();
+    assertEquals("/some/path", new HgVcsRoot(root).getHgPath());
+    try {
+      System.setProperty(Constants.CUSTOM_HG_PATH_ENABLED, "false");
+      assertEquals("hg", new HgVcsRoot(root).getHgPath());
+    } finally {
+      System.getProperties().remove(Constants.CUSTOM_HG_PATH_ENABLED);
+    }
+  }
 
-    ServerHgPathProvider serverHgPathProvider = new ServerHgPathProvider(new ServerPluginConfigBuilder().build());
-    HgVcsRoot root = new HgVcsRoot(vcsRoot().withHgPath("/some/other/path").withUrl("http://some.org/repo").build());
-    assertEquals("hg", serverHgPathProvider.getHgPath(root));
-
-    serverHgPathProvider = new ServerHgPathProvider(new ServerPluginConfigBuilder().hgPath("/server/hg/path").build());
-    root = new HgVcsRoot(vcsRoot().withHgPath("/some/other/path").withUrl("http://some.org/repo").build());
-    assertEquals("/server/hg/path", serverHgPathProvider.getHgPath(root));
-
-    root = new HgVcsRoot(vcsRoot().withHgPath("/some/path1").withUrl("http://some.org/repo").build());
-    assertEquals("/some/path1", serverHgPathProvider.getHgPath(root));
-    root = new HgVcsRoot(vcsRoot().withHgPath("/some/path2").withUrl("http://some.org/repo").build());
-    assertEquals("/some/path2", serverHgPathProvider.getHgPath(root));
+  public void disable_custom_hg_config() throws Exception {
+    String customConfig = "[extensions]\nsome.ext =";
+    VcsRoot root = vcsRoot().withUrl("http://some.org/repo").withCustomConfig(customConfig).build();
+    assertEquals(customConfig, new HgVcsRoot(root).getCustomHgConfig());
+    try {
+      System.setProperty(Constants.CUSTOM_HG_CONFIG_ENABLED, "false");
+      assertEquals("", new HgVcsRoot(root).getCustomHgConfig());
+    } finally {
+      System.getProperties().remove(Constants.CUSTOM_HG_CONFIG_ENABLED);
+    }
   }
 
   private VcsRootImpl createVcsRoot(String url) {
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupportTest.java	Wed Jan 24 21:19:56 2018 +0100
+++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupportTest.java	Wed Jan 24 22:02:52 2018 +0100
@@ -308,6 +308,21 @@
   }
 
 
+  @TestFor(issues = "TW-50033")
+  public void labeling_with_branch_tag_clash() throws Exception {
+    VcsRootImpl vcsRoot = createVcsRoot(new File("mercurial-tests/testData/rep2").getAbsolutePath(), "default");
+    RepositoryStateData s1 = myVcs.getCollectChangesPolicy().getCurrentState(vcsRoot);
+    //repository contains the 'topic' branch, create tag on non-last revision in this branch
+    myVcs.label("topic", "26:27184c50d7ef", vcsRoot, CheckoutRules.DEFAULT);
+    RepositoryStateData s2 = myVcs.getCollectChangesPolicy().getCurrentState(vcsRoot);
+    //retrieve tag into local clone
+    myVcs.getCollectChangesPolicy().collectChanges(vcsRoot, s1, s2, CheckoutRules.DEFAULT);
+
+    //tag another commit from the 'topic' branch
+    myVcs.label("v1", "27:2a368008e4d9", vcsRoot, CheckoutRules.DEFAULT);
+  }
+
+
   public void tag_should_be_created_in_branch_to_which_tagged_revision_belongs() throws Exception {
     File remoteRepo = copyRepository(myTempFiles, myRep2Path);
     VcsRoot root = vcsRoot().withUrl(remoteRepo.getCanonicalPath()).withBranch("default").build();
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerHgPathProviderTest.java	Wed Jan 24 21:19:56 2018 +0100
+++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerHgPathProviderTest.java	Wed Jan 24 22:02:52 2018 +0100
@@ -26,22 +26,20 @@
  * @author dmitry.neverov
  */
 @Test
-public class ServerHgPathProviderTest extends BaseMercurialTestCase {
+public class ServerHgPathProviderTest {
 
   private String myServerWideHgPath;
   private String myVcsRootHgPath;
 
 
   @BeforeMethod
-  public void setUp() throws Exception {
-    super.setUp();
+  public void setUp() {
     myServerWideHgPath = null;
     myVcsRootHgPath = "/vcs/root/hg/path";
   }
 
 
-  public void server_should_use_settings_from_vcs_root_if_server_wide_path_is_not_set_and_path_is_in_whitelist() throws Exception {
-    setInternalProperty(Constants.HG_PATH_WHITELIST, myVcsRootHgPath);
+  public void server_should_use_settings_from_vcs_root_if_server_wide_path_is_not_set() throws Exception {
     myServerWideHgPath = null;
     HgPathProvider provider = createHgPathProvider();
     HgVcsRoot root = createHgRoot();
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/VcsRootBuilder.java	Wed Jan 24 21:19:56 2018 +0100
+++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/VcsRootBuilder.java	Wed Jan 24 22:02:52 2018 +0100
@@ -18,11 +18,8 @@
 
 import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.HgVcsRoot;
 import jetbrains.buildServer.util.StringUtil;
-import jetbrains.buildServer.vcs.SVcsRoot;
 import jetbrains.buildServer.vcs.impl.VcsRootImpl;
 import org.jetbrains.annotations.NotNull;
-import org.jmock.Expectations;
-import org.jmock.Mockery;
 
 import java.io.File;
 import java.io.IOException;
@@ -47,6 +44,7 @@
   private boolean myIncludeSubreposInPatch = true;
   private boolean myUseArchiveForPatch = false;
   private HgVcsRoot.PurgePolicy myPurgePolicy;
+  private String myCustomConfig;
 
   public static VcsRootBuilder vcsRoot() {
     return new VcsRootBuilder();
@@ -70,36 +68,12 @@
     vcsRoot.addProperty(Constants.USE_TAGS_AS_BRANCHES, String.valueOf(myTagsAsBranches));
     if (myPurgePolicy != null)
       vcsRoot.addProperty(Constants.PURGE_POLICY, myPurgePolicy.name());
+    if (myCustomConfig != null)
+      vcsRoot.addProperty(Constants.CUSTOM_HG_CONFIG_PROP, myCustomConfig);
     return vcsRoot;
   }
 
 
-  public SVcsRoot build(Mockery context) {
-    final SVcsRoot root = context.mock(SVcsRoot.class, "SVcsRoot" + myRootId);
-    context.checking(new Expectations() {{
-      allowing(root).describe(false); will(returnValue("toString"));
-      allowing(root).getVcsName(); will(returnValue(Constants.VCS_NAME));
-      allowing(root).getProperty(with(Constants.REPOSITORY_PROP)); will(returnValue(myRepository));
-      allowing(root).getProperty(with(Constants.HG_COMMAND_PATH_PROP)); will(returnValue(myHgPath));
-      allowing(root).getProperty(with(Constants.BRANCH_NAME_PROP)); will(returnValue(myBranch));
-      allowing(root).getProperty(with(Constants.SERVER_CLONE_PATH_PROP)); will(returnValue(null));
-      allowing(root).getProperty(with(Constants.USERNAME)); will(returnValue(myUsername));
-      allowing(root).getProperty(with(Constants.PASSWORD)); will(returnValue(myPassword));
-      allowing(root).getProperty(with(Constants.UNCOMPRESSED_TRANSFER)); will(returnValue(null));
-      allowing(root).getProperty(with(Constants.USER_FOR_TAG)); will(returnValue(myUserForTag));
-      allowing(root).getProperty(with(Constants.DETECT_SUBREPO_CHANGES)); will(returnValue(String.valueOf(myDetectSubrepoChanges)));
-      allowing(root).getProperty(with(Constants.USE_TAGS_AS_BRANCHES)); will(returnValue(String.valueOf(myTagsAsBranches)));
-      allowing(root).getProperty(with(Constants.HG_EXTENSIONS)); will(returnValue(myExtensions));
-    }});
-    if (myCloneRepositoryTo != null) {
-      context.checking(new Expectations() {{
-        allowing(root).getProperty(with(Constants.SERVER_CLONE_PATH_PROP)); will(returnValue(myCloneRepositoryTo.getAbsolutePath()));
-      }});
-    }
-    return root;
-  }
-
-
   public VcsRootBuilder withUrl(@NotNull String repository) {
     myRepository = repository;
     return this;
@@ -193,4 +167,10 @@
     myPurgePolicy = policy;
     return this;
   }
+
+
+  public VcsRootBuilder withCustomConfig(String customConfig) {
+    myCustomConfig = customConfig;
+    return this;
+  }
 }