Mercurial > hg > mercurial
changeset 847:fbd8e6725fe5
Support sharing subrepo mirrors + tests
author | Dmitry Neverov <dmitry.neverov@jetbrains.com> |
---|---|
date | Mon, 30 Jun 2014 22:27:43 +0200 |
parents | cea91fa66d3b |
children | e3fd75845c5d |
files | mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialIncludeRuleUpdater.java mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/SharingMercurialUpdater.java mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentSideCheckoutWithSharedMirrorsTest.java mercurial-tests/src/testng.xml |
diffstat | 4 files changed, 225 insertions(+), 11 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialIncludeRuleUpdater.java Mon Jun 30 21:02:29 2014 +0200 +++ b/mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialIncludeRuleUpdater.java Mon Jun 30 22:27:43 2014 +0200 @@ -24,6 +24,7 @@ import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.exception.UnrelatedRepositoryException; import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.exception.WrongSubrepoUrlException; import jetbrains.buildServer.log.Loggers; +import jetbrains.buildServer.util.FileUtil; import jetbrains.buildServer.vcs.IncludeRule; import jetbrains.buildServer.vcs.VcsException; import jetbrains.buildServer.vcs.VcsRoot; @@ -87,7 +88,7 @@ } - private void updateLocalMirror(@NotNull String repositoryUrl, @NotNull String revision) throws VcsException, IOException { + protected void updateLocalMirror(@NotNull String repositoryUrl, @NotNull String revision) throws VcsException, IOException { File mirrorDir = myMirrorManager.getMirrorDir(repositoryUrl); HgRepo mirrorRepo = myRepoFactory.createRepo(myRoot, mirrorDir); if (!mirrorRepo.isValidRepository()) { @@ -120,6 +121,7 @@ String repositoryUrl = getDefaultPullUrl(myRoot, myUseLocalMirrors); HgRepo repo = myRepoFactory.createRepo(myRoot, workingDir); myLogger.message("Update repository " + workingDir.getAbsolutePath()); + disableSharing(workingDir); if (repo.isEmpty()) {//can do clone only in empty dir myLogger.message("Start cloning from " + (myUseLocalMirrors ? "local mirror " : "") + myAuthSettings.getRepositoryUrlWithHiddenPassword(repositoryUrl)); repo.doClone().fromRepository(repositoryUrl) @@ -152,6 +154,14 @@ } + private void disableSharing(@NotNull File workingDir) { + File dotHg = new File(workingDir, ".hg"); + File sharedpath = new File(dotHg, "sharedpath"); + if (sharedpath.exists()) + FileUtil.delete(sharedpath); + } + + private void updateWorkingDir(@NotNull File workingDir, @NotNull String toVersion, @NotNull String repositoryUrl) throws VcsException, IOException { HgRepo repo = myRepoFactory.createRepo(myRoot, workingDir); List<File> repos = new ArrayList<File>(); @@ -211,10 +221,11 @@ return url.startsWith("."); } - private void syncSubrepo(@NotNull HgRepo subrepository, @NotNull String url, @NotNull String revision) throws VcsException, IOException { - if (!subrepository.isValidRepository() || !subrepository.containsRevision(revision)) { - updateLocalMirror(url, revision); - File mirrorDir = myMirrorManager.getMirrorDir(url); + protected void syncSubrepo(@NotNull HgRepo subrepository, @NotNull String subrepoUrl, @NotNull String subrepoRevision) throws VcsException, IOException { + disableSharing(subrepository.getWorkingDir()); + if (!subrepository.isValidRepository() || !subrepository.containsRevision(subrepoRevision)) { + updateLocalMirror(subrepoUrl, subrepoRevision); + File mirrorDir = myMirrorManager.getMirrorDir(subrepoUrl); if (subrepository.isValidRepository()) { myLogger.message("Pull from local mirror"); subrepository.pull().fromRepository(mirrorDir) @@ -229,7 +240,7 @@ .setUpdateWorkingDir(false) .setUsePullProtocol(false) .call(); - subrepository.setDefaultPath(url); + subrepository.setDefaultPath(subrepoUrl); myLogger.message("done"); } }
--- a/mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/SharingMercurialUpdater.java Mon Jun 30 21:02:29 2014 +0200 +++ b/mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/SharingMercurialUpdater.java Mon Jun 30 22:27:43 2014 +0200 @@ -43,17 +43,34 @@ repo.init().call(); repo.setDefaultPath(myRoot.getRepository()); - File mirrorDir = myMirrorManager.getMirrorDir(myRoot.getRepository()); - File mirrorHg = new File(mirrorDir, ".hg"); + File mirrorHg = getMirrorHg(myRoot.getRepository()); String sharedPath = readSharedPath(workingDir); if (mirrorHg.getCanonicalPath().equals(sharedPath)) { writeRequires(mirrorHg, workingDir); } else { writeRequires(mirrorHg, workingDir); - writeSharedPath(workingDir, mirrorDir); + writeSharedPath(mirrorHg, workingDir); } } + @Override + protected void syncSubrepo(@NotNull HgRepo subrepository, @NotNull String subrepoUrl, @NotNull String subrepoRevision) throws VcsException, IOException { + if (subrepository.isEmpty() || !subrepository.isValidRepository()) + subrepository.init().call(); + subrepository.setDefaultPath(subrepoUrl); + + if (!subrepository.containsRevision(subrepoRevision)) { + updateLocalMirror(subrepoUrl, subrepoRevision); + File mirrorHg = getMirrorHg(subrepoUrl); + String sharedPath = readSharedPath(subrepository.getWorkingDir()); + if (mirrorHg.getCanonicalPath().equals(sharedPath)) { + writeRequires(mirrorHg, subrepository.getWorkingDir()); + } else { + writeRequires(mirrorHg, subrepository.getWorkingDir()); + writeSharedPath(mirrorHg, subrepository.getWorkingDir()); + } + } + } @Nullable private String readSharedPath(@NotNull File workingDir) throws IOException { @@ -63,8 +80,8 @@ return FileUtil.readText(sharedPath); } - private void writeSharedPath(@NotNull File workingDir, @NotNull File mirrorDir) throws IOException { - FileUtil.writeToFile(getSharedPath(workingDir), (new File(mirrorDir, ".hg").getCanonicalPath() + "\n").getBytes("UTF-8")); + private void writeSharedPath(@NotNull File mirrorHg, @NotNull File workingDir) throws IOException { + FileUtil.writeToFile(getSharedPath(workingDir), (mirrorHg.getCanonicalPath() + "\n").getBytes("UTF-8")); } private void writeRequires(@NotNull File mirrorHg, @NotNull File workingDir) throws IOException { @@ -82,4 +99,10 @@ private File getSharedPath(File workingDir) { return new File(new File(workingDir, ".hg"), "sharedpath"); } + + @NotNull + private File getMirrorHg(@NotNull String repositoryUrl) { + File mirrorDir = myMirrorManager.getMirrorDir(repositoryUrl); + return new File(mirrorDir, ".hg"); + } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentSideCheckoutWithSharedMirrorsTest.java Mon Jun 30 22:27:43 2014 +0200 @@ -0,0 +1,179 @@ +/* + * 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.agent.AgentRunningBuild; +import jetbrains.buildServer.agent.BuildAgentConfiguration; +import jetbrains.buildServer.agent.BuildProgressLogger; +import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.CommandSettingsForRootImpl; +import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.CommandlineViaFileWrapperWeaver; +import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.ExtensionsWeaver; +import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.TestCommandSettingsFactory; +import jetbrains.buildServer.util.FileUtil; +import jetbrains.buildServer.vcs.CheckoutRules; +import jetbrains.buildServer.vcs.IncludeRule; +import jetbrains.buildServer.vcs.VcsException; +import jetbrains.buildServer.vcs.VcsRoot; +import jetbrains.buildServer.vcs.impl.VcsRootImpl; +import org.jetbrains.annotations.NotNull; +import org.jmock.Expectations; +import org.jmock.Mockery; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.IOException; +import java.util.Map; + +import static jetbrains.buildServer.buildTriggers.vcs.mercurial.VcsRootBuilder.vcsRoot; +import static jetbrains.buildServer.util.Util.map; + +@Test +public class AgentSideCheckoutWithSharedMirrorsTest extends BaseMercurialPatchTestCase { + + private File myOriginalRepositoriesParentDir; + private MercurialAgentSideVcsSupport myVcsSupport; + private File myWorkDir; + private File myMirrorsRootDir; + private Mockery myContext; + private BuildProgressLogger myLogger; + private int myBuildCounter = 0; + + @Override + @BeforeMethod + protected void setUp() throws Exception { + super.setUp(); + + myOriginalRepositoriesParentDir = myTempFiles.createTempDir(); + myContext = new Mockery(); + + myMirrorsRootDir = myTempFiles.createTempDir(); + + final BuildAgentConfiguration agentConfig = myContext.mock(BuildAgentConfiguration.class); + myContext.checking(new Expectations() {{ + allowing(agentConfig).getCacheDirectory("mercurial"); will(returnValue(myMirrorsRootDir)); + allowing(agentConfig).getTempDirectory(); will(returnValue(myTempFiles.createTempDir())); + allowing(agentConfig).getParametersResolver(); will(returnValue(new HgPathResolver())); + }}); + + final AgentPluginConfigImpl pluginConfig = new AgentPluginConfigImpl(agentConfig); + myVcsSupport = new MercurialAgentSideVcsSupport(pluginConfig, + new MirrorManagerImpl(pluginConfig), + new AgentRepoFactory(new CommandSettingsForRootImpl(new TestCommandSettingsFactory(), new ExtensionsWeaver(), + new CommandlineViaFileWrapperWeaver()), new AgentHgPathProvider(agentConfig))); + + myLogger = myContext.mock(BuildProgressLogger.class); + myContext.checking(new Expectations() {{ + allowing(myLogger).message(with(any(String.class))); + }}); + + myWorkDir = myTempFiles.createTempDir(); + } + + + public void working_dir_store_should_be_empty() throws Exception { + VcsRoot root = createVcsRoot(simpleRepo()); + String version = "4:b06a290a363b"; + update(root, version); + File workingDirStore = new File(new File(myWorkDir, ".hg"), "store"); + assertTrue(!workingDirStore.exists() || listFiles(workingDirStore).length == 0); + checkWorkingDir("patch1/after", myWorkDir); + } + + + public void subrepos_store_should_be_empty() throws Exception { + File myR1Dir = copy(new File("mercurial-tests/testData/subrepos/r1")); + copy(new File("mercurial-tests/testData/subrepos/r2")); + copy(new File("mercurial-tests/testData/subrepos/r3")); + VcsRootImpl root = vcsRoot().withUrl(myR1Dir.getAbsolutePath()).build(); + update(root, "34017377d9c3"); + + File subrepoStore = new File(new File(new File(myWorkDir, "r2"), ".hg"), "store"); + assertTrue(!subrepoStore.exists() || listFiles(subrepoStore).length == 0); + } + + + public void turn_off_sharing() throws Exception { + File myR1Dir = copy(new File("mercurial-tests/testData/subrepos/r1")); + copy(new File("mercurial-tests/testData/subrepos/r2")); + copy(new File("mercurial-tests/testData/subrepos/r3")); + VcsRootImpl root = vcsRoot().withUrl(myR1Dir.getAbsolutePath()).build(); + update(root, "34017377d9c3"); + + update(root, "34017377d9c3", false); + File workingDirSharedPath = new File(new File(myWorkDir, ".hg"), "sharedpath"); + File subrepoSharedPath = new File(new File(new File(myWorkDir, "r2"), ".hg"), "sharedpath"); + File workingDirStore = new File(new File(myWorkDir, ".hg"), "store"); + File subrepoStore = new File(new File(new File(myWorkDir, "r2"), ".hg"), "store"); + + assertFalse(workingDirSharedPath.exists()); + assertFalse(subrepoSharedPath.exists()); + assertTrue(listFiles(workingDirStore).length > 0); + assertTrue(listFiles(subrepoStore).length > 0); + } + + + @NotNull + private File[] listFiles(@NotNull File dir) { + File[] files = dir.listFiles(); + if (files == null) + return new File[0]; + return files; + } + + + private void update(@NotNull VcsRoot root, @NotNull String version) throws VcsException { + update(root, version, true); + } + + private void update(@NotNull VcsRoot root, @NotNull String version, boolean share) throws VcsException { + AgentRunningBuild build = createBuild(share); + myVcsSupport.getUpdater(root, CheckoutRules.DEFAULT, version, myWorkDir, build, false) + .process(IncludeRule.createDefaultInstance(), myWorkDir); + } + + + private void checkWorkingDir(final String expected, final File workDir) throws IOException { + FileUtil.delete(new File(workDir, ".hg")); + checkDirectoriesAreEqual(new File(getTestDataPath(), expected), workDir); + } + + + private AgentRunningBuild createBuild(boolean share) { + final Map<String, String> sharedConfigParameters = map("teamcity.hg.use.local.mirrors", "true", "teamcity.hg.shareLocalMirrors", String.valueOf(share)); + final AgentRunningBuild build = myContext.mock(AgentRunningBuild.class, "build" + myBuildCounter++); + myContext.checking(new Expectations() {{ + allowing(build).getBuildLogger(); will(returnValue(myLogger)); + allowing(build).getSharedConfigParameters(); will(returnValue(sharedConfigParameters)); + }}); + return build; + } + + protected String getTestDataPath() { + return "mercurial-tests/testData"; + } + + private File copy(@NotNull File originalRepositoryDir) throws IOException { + String dirName = originalRepositoryDir.getName(); + File copyDir = new File(myOriginalRepositoriesParentDir, dirName); + FileUtil.copyDir(originalRepositoryDir, copyDir); + if (new File(copyDir, "hg").isDirectory()) { + FileUtil.rename(new File(copyDir, "hg"), new File(copyDir, ".hg")); + } + return copyDir; + } +}
--- a/mercurial-tests/src/testng.xml Mon Jun 30 21:02:29 2014 +0200 +++ b/mercurial-tests/src/testng.xml Mon Jun 30 22:27:43 2014 +0200 @@ -29,6 +29,7 @@ <class name="jetbrains.buildServer.buildTriggers.vcs.mercurial.MercurialVcsSupportTest"/> <class name="jetbrains.buildServer.buildTriggers.vcs.mercurial.AgentSideCheckoutTest"/> <class name="jetbrains.buildServer.buildTriggers.vcs.mercurial.AgentSideCheckoutWithSubreposTest"/> + <class name="jetbrains.buildServer.buildTriggers.vcs.mercurial.AgentSideCheckoutWithSharedMirrorsTest"/> <class name="jetbrains.buildServer.buildTriggers.vcs.mercurial.HgVcsRootTest"/> <class name="jetbrains.buildServer.buildTriggers.vcs.mercurial.MirrorManagerTest"/> <class name="jetbrains.buildServer.buildTriggers.vcs.mercurial.HgVersionTest"/>