# HG changeset patch # User Dmitry Neverov # Date 1516827772 -3600 # Node ID 4a0ea921c2149527b7ce09315ac99a08ab94ebdb # Parent 64b5816390f9370eaf83051faf70270d7e53daf1# Parent 7bf4d943d5bbd725eea4e943ec50112e062b005b Merge back changes since 28.04.2017 diff -r 7bf4d943d5bb -r 4a0ea921c214 mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/Constants.java --- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/Constants.java Mon Jan 22 11:39:20 2018 +0100 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/Constants.java Wed Jan 24 22:02:52 2018 +0100 @@ -43,6 +43,7 @@ String SHOW_CUSTOM_CLONE_PATH = "teamcity.hg.showCustomClonePath"; String CUSTOM_CLONE_PATH_ENABLED = "teamcity.hg.customClonePathEnabled"; + String CUSTOM_CLONE_PATH_WHITELIST = "teamcity.hg.customClonePathWhitelist"; String CUSTOM_CACHES_DIR = "teamcity.hg.customCachesDir"; String CUSTOM_HG_PATH_ENABLED = "teamcity.hg.customHgPathEnabled"; String CUSTOM_HG_CONFIG_ENABLED = "teamcity.hg.customConfigEnabled"; diff -r 7bf4d943d5bb -r 4a0ea921c214 mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/HgVcsRoot.java --- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/HgVcsRoot.java Mon Jan 22 11:39:20 2018 +0100 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/HgVcsRoot.java Wed Jan 24 22:02:52 2018 +0100 @@ -25,6 +25,7 @@ import java.io.File; import java.util.HashMap; +import java.util.List; import java.util.Map; /** @@ -214,8 +215,11 @@ } private String readCustomClonePath() { - if (TeamCityProperties.getBooleanOrTrue(Constants.CUSTOM_CLONE_PATH_ENABLED)) - return getProperty(Constants.SERVER_CLONE_PATH_PROP); + String clonePath = getProperty(Constants.SERVER_CLONE_PATH_PROP); + if (TeamCityProperties.getBoolean(Constants.CUSTOM_CLONE_PATH_ENABLED)) + return clonePath; + if (isAllowedCustomClonePath(clonePath)) + return clonePath; return null; } @@ -256,4 +260,26 @@ PURGE_UNKNOWN, PURGE_ALL } + + + public static boolean hasCustomClonePathWhitelist() { + return StringUtil.isNotEmpty(TeamCityProperties.getProperty(Constants.CUSTOM_CLONE_PATH_WHITELIST)); + } + + public static boolean isAllowedCustomClonePath(@Nullable String path) { + if (StringUtil.isEmptyOrSpaces(path)) + return false; + String whitelist = TeamCityProperties.getProperty(Constants.CUSTOM_CLONE_PATH_WHITELIST); + if (StringUtil.isEmpty(whitelist)) + return false; + List paths = StringUtil.split(whitelist, ";"); + for (String p : paths) { + if (p.endsWith("/*")) { + return new File(path).getParentFile().equals(new File(p.substring(0, p.length() - 2))); + } else if (p.equals(path)) { + return true; + } + } + return false; + } } diff -r 7bf4d943d5bb -r 4a0ea921c214 mercurial-server/resources/buildServerResources/mercurialSettings.jsp --- a/mercurial-server/resources/buildServerResources/mercurialSettings.jsp Mon Jan 22 11:39:20 2018 +0100 +++ b/mercurial-server/resources/buildServerResources/mercurialSettings.jsp Wed Jan 24 22:02:52 2018 +0100 @@ -1,6 +1,8 @@ <%@ page import="jetbrains.buildServer.serverSide.TeamCityProperties" %> <%@ page import="jetbrains.buildServer.buildTriggers.vcs.mercurial.Constants" %> <%@ page import="jetbrains.buildServer.util.StringUtil" %> +<%@ page import="jetbrains.buildServer.buildTriggers.vcs.mercurial.ServerPluginConfigImpl" %> +<%@ page import="jetbrains.buildServer.buildTriggers.vcs.mercurial.command.HgVcsRoot" %> <%@include file="/include.jsp"%> <%@ taglib prefix="props" tagdir="/WEB-INF/tags/props" %> <%-- @@ -28,9 +30,10 @@ } - + diff -r 7bf4d943d5bb -r 4a0ea921c214 mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/BaseMercurialPatchTestCase.java --- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/BaseMercurialPatchTestCase.java Mon Jan 22 11:39:20 2018 +0100 +++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/BaseMercurialPatchTestCase.java Wed Jan 24 22:02:52 2018 +0100 @@ -20,10 +20,13 @@ import jetbrains.buildServer.vcs.impl.VcsRootImpl; import jetbrains.buildServer.vcs.patches.PatchTestCase; import org.jetbrains.annotations.NotNull; +import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import java.io.File; import java.io.IOException; +import java.util.HashSet; +import java.util.Set; import static jetbrains.buildServer.buildTriggers.vcs.mercurial.Util.copyRepository; @@ -32,11 +35,19 @@ * Date: 31.07.2008 */ public abstract class BaseMercurialPatchTestCase extends PatchTestCase { - @Override + private Set myPropertiesToClean; + @BeforeMethod protected void setUp() throws Exception { super.setUp(); new TeamCityProperties() {{ setModel(new BasePropertiesModel() {});}}; + myPropertiesToClean = new HashSet<>(); + } + + @AfterMethod + public void tearDown() { + cleanInternalProperties(); + myTempFiles.cleanup(); } protected VcsRootImpl createVcsRoot(@NotNull String repPath) throws IOException { @@ -52,4 +63,16 @@ protected String simpleRepo() { return new File("mercurial-tests/testData/rep1").getAbsolutePath(); } + + protected void setInternalProperty(@NotNull String propKey, @NotNull String value) { + System.setProperty(propKey, value); + myPropertiesToClean.add(propKey); + } + + private void cleanInternalProperties() { + for (String prop : myPropertiesToClean) { + System.getProperties().remove(prop); + } + myPropertiesToClean.clear(); + } } diff -r 7bf4d943d5bb -r 4a0ea921c214 mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/BaseMercurialTestCase.java --- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/BaseMercurialTestCase.java Mon Jan 22 11:39:20 2018 +0100 +++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/BaseMercurialTestCase.java Wed Jan 24 22:02:52 2018 +0100 @@ -25,20 +25,25 @@ import java.io.File; import java.io.IOException; +import java.util.HashSet; +import java.util.Set; import static jetbrains.buildServer.buildTriggers.vcs.mercurial.Util.copyRepository; public class BaseMercurialTestCase { protected TempFiles myTempFiles; + private Set myPropertiesToClean; @BeforeMethod public void setUp() throws Exception { new TeamCityProperties() {{ setModel(new BasePropertiesModel() {});}}; myTempFiles = new TempFiles(); + myPropertiesToClean = new HashSet<>(); } @AfterMethod public void tearDown() { + cleanInternalProperties(); myTempFiles.cleanup(); } @@ -49,4 +54,16 @@ copyRepository(new File(testRepoPath), result); return result; } + + protected void setInternalProperty(@NotNull String propKey, @NotNull String value) { + System.setProperty(propKey, value); + myPropertiesToClean.add(propKey); + } + + private void cleanInternalProperties() { + for (String prop : myPropertiesToClean) { + System.getProperties().remove(prop); + } + myPropertiesToClean.clear(); + } } diff -r 7bf4d943d5bb -r 4a0ea921c214 mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgVcsRootFactoryTest.java --- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgVcsRootFactoryTest.java Mon Jan 22 11:39:20 2018 +0100 +++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgVcsRootFactoryTest.java Wed Jan 24 22:02:52 2018 +0100 @@ -35,6 +35,7 @@ @TestFor(issues = "TW-25057") public void vcs_root_custom_clone_dir_should_not_contain_password() throws Exception { + setInternalProperty(Constants.CUSTOM_CLONE_PATH_ENABLED, "true"); TempFiles tmp = new TempFiles(); String urlWithoutPath = "http://only.host/"; String password = "pwd"; @@ -52,6 +53,7 @@ @TestFor(issues = "TW-32540") public void custom_clone_dir_should_contain_only_valid_characters() throws Exception { + setInternalProperty(Constants.CUSTOM_CLONE_PATH_ENABLED, "true"); TempFiles tmp = new TempFiles(); String urlWithoutPath = "http://acme:8000/"; VcsRoot root = vcsRoot() diff -r 7bf4d943d5bb -r 4a0ea921c214 mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgVcsRootTest.java --- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgVcsRootTest.java Mon Jan 22 11:39:20 2018 +0100 +++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgVcsRootTest.java Wed Jan 24 22:02:52 2018 +0100 @@ -16,29 +16,22 @@ package jetbrains.buildServer.buildTriggers.vcs.mercurial; import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.HgVcsRoot; -import jetbrains.buildServer.serverSide.BasePropertiesModel; -import jetbrains.buildServer.serverSide.TeamCityProperties; import jetbrains.buildServer.util.TestFor; import jetbrains.buildServer.vcs.VcsRoot; import jetbrains.buildServer.vcs.impl.VcsRootImpl; -import junit.framework.TestCase; -import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import java.io.File; import static jetbrains.buildServer.buildTriggers.vcs.mercurial.VcsRootBuilder.vcsRoot; +import static org.testng.Assert.*; +import static org.testng.AssertJUnit.assertEquals; /** * @author Pavel.Sher */ @Test -public class HgVcsRootTest extends TestCase { - - @BeforeMethod - public void setUp() throws Exception { - new TeamCityProperties() {{ setModel(new BasePropertiesModel() {});}}; - } +public class HgVcsRootTest extends BaseMercurialTestCase { public void test_url_without_credentials() { VcsRootImpl vcsRoot = createVcsRoot("http://host.com/path"); @@ -117,19 +110,35 @@ assertEquals("ssh://user:pwd@ourserver.com/mercurialrepo/", root.getRepositoryUrlWithCredentials()); } - @TestFor(issues = "TW-36401") + @TestFor(issues = {"TW-36401", "TW-50054"}) public void test_disabling_custom_clone_dirs() throws Exception { File cloneDir = new File(""); VcsRoot root = vcsRoot().withCloneRepositoryTo(cloneDir).withUrl("http://some.org/repo").build(); HgVcsRoot hgRoot1 = new HgVcsRoot(root); - assertEquals(cloneDir.getAbsolutePath(), hgRoot1.getCustomClonePath()); - try { - System.setProperty(Constants.CUSTOM_CLONE_PATH_ENABLED, "false"); - HgVcsRoot hgRoot2 = new HgVcsRoot(root); - assertNull(hgRoot2.getCustomClonePath()); - } finally { - System.getProperties().remove(Constants.CUSTOM_CLONE_PATH_ENABLED); - } + assertNull(hgRoot1.getCustomClonePath()); + setInternalProperty(Constants.CUSTOM_CLONE_PATH_ENABLED, "true"); + HgVcsRoot hgRoot2 = new HgVcsRoot(root); + assertEquals(cloneDir.getAbsolutePath(), hgRoot2.getCustomClonePath()); + } + + @TestFor(issues = {"TW-36401", "TW-50054"}) + public void custom_clone_path_whitelist() throws Exception { + assertFalse(HgVcsRoot.isAllowedCustomClonePath(null)); + assertFalse(HgVcsRoot.isAllowedCustomClonePath("/some/path")); + setInternalProperty(Constants.CUSTOM_CLONE_PATH_WHITELIST, "/some/path1;/some/path2/*"); + assertTrue(HgVcsRoot.isAllowedCustomClonePath("/some/path1")); + assertTrue(HgVcsRoot.isAllowedCustomClonePath("/some/path2/repo1")); + assertFalse(HgVcsRoot.isAllowedCustomClonePath("/some/path2/a/b/c")); + assertFalse(HgVcsRoot.isAllowedCustomClonePath("/other/path")); + assertFalse(HgVcsRoot.isAllowedCustomClonePath("/some/path21")); + + File tempDir = myTempFiles.createTempDir(); + VcsRoot root = vcsRoot().withCloneRepositoryTo(tempDir).withUrl("http://some.org/repo").build(); + HgVcsRoot hgRoot = new HgVcsRoot(root); + assertNull(hgRoot.getCustomClonePath()); + setInternalProperty(Constants.CUSTOM_CLONE_PATH_WHITELIST, tempDir.getCanonicalPath()); + hgRoot = new HgVcsRoot(root); + assertEquals(hgRoot.getCustomClonePath(), tempDir.getCanonicalPath()); } public void disable_custom_hg_path() throws Exception { diff -r 7bf4d943d5bb -r 4a0ea921c214 mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupportTest.java --- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupportTest.java Mon Jan 22 11:39:20 2018 +0100 +++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupportTest.java Wed Jan 24 22:02:52 2018 +0100 @@ -549,6 +549,7 @@ } public void build_patch_using_custom_clone_path() throws IOException, VcsException { + setInternalProperty(Constants.CUSTOM_CLONE_PATH_ENABLED, "true"); setName("cleanPatch1"); VcsRootImpl vcsRoot = createVcsRoot(simpleRepo()); File cloneDir = myTempFiles.createTempDir();