# HG changeset patch # User Dmitry Neverov # Date 1420197861 -3600 # Node ID ed4ae4bfd6918dccfdde8736a2460277187816d8 # Parent 15fce0c26e181b4552096794ba7c775b01bf65ec TW-39482 recover from abandoned transaction error in local mirror diff -r 15fce0c26e18 -r ed4ae4bfd691 mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialIncludeRuleUpdater.java --- a/mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialIncludeRuleUpdater.java Tue Dec 16 20:45:00 2014 +0100 +++ b/mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialIncludeRuleUpdater.java Fri Jan 02 12:24:21 2015 +0100 @@ -21,6 +21,8 @@ import jetbrains.buildServer.agent.vcs.IncludeRuleUpdater; import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.AuthSettings; import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.HgVcsRoot; +import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.PullCommand; +import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.exception.AbandonedTransactionFound; import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.exception.UnrelatedRepositoryException; import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.exception.WrongSubrepoUrlException; import jetbrains.buildServer.buildTriggers.vcs.mercurial.ext.BeforeWorkingDirUpdateExtension; @@ -124,11 +126,17 @@ if (mirrorRepo.containsRevision(revision)) { myLogger.message("Local mirror is already up-to-date"); } else { - mirrorRepo.pull().fromRepository(repositoryUrl) + PullCommand pull = mirrorRepo.pull().fromRepository(repositoryUrl) .withTraceback(myUseTraceback) .withProfile(myProfile) - .withTimeout(myPullTimeout) - .call(); + .withTimeout(myPullTimeout); + try { + pull.call(); + } catch (AbandonedTransactionFound e) { + myLogger.message("Abandoned transaction found, trying to recover"); + mirrorRepo.recover().call(); + pull.call(); + } } } diff -r 15fce0c26e18 -r ed4ae4bfd691 mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgRepo.java --- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgRepo.java Tue Dec 16 20:45:00 2014 +0100 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgRepo.java Fri Jan 02 12:24:21 2015 +0100 @@ -159,6 +159,10 @@ return new AddRemoveCommand(myCommandSettingsFactory.create(), myHgPath, myWorkingDir); } + public RecoverCommand recover() { + return new RecoverCommand(myCommandSettingsFactory.create(), myHgPath, myWorkingDir); + } + public String path() { return myWorkingDir.getAbsolutePath(); } diff -r 15fce0c26e18 -r ed4ae4bfd691 mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/RecoverCommand.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/RecoverCommand.java Fri Jan 02 12:24:21 2015 +0100 @@ -0,0 +1,42 @@ +/* + * Copyright 2000-2015 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.command; + +import jetbrains.buildServer.vcs.VcsException; +import org.jetbrains.annotations.NotNull; + +import java.io.File; + +public class RecoverCommand extends BaseCommand { + public RecoverCommand(@NotNull CommandSettings commandSettings, + @NotNull String hgPath, + @NotNull File workingDir) { + super(commandSettings, hgPath, workingDir); + } + + public void call() throws VcsException { + MercurialCommandLine cmd = createCommandLine(); + cmd.addParameter("recover"); + runCommand(cmd); + } + + @NotNull + @Override + protected String getDescription() { + return "hg recover"; + } +} diff -r 15fce0c26e18 -r ed4ae4bfd691 mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentSideCheckoutWithSharedMirrorsTest.java --- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentSideCheckoutWithSharedMirrorsTest.java Tue Dec 16 20:45:00 2014 +0100 +++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentSideCheckoutWithSharedMirrorsTest.java Fri Jan 02 12:24:21 2015 +0100 @@ -20,12 +20,10 @@ import jetbrains.buildServer.agent.BuildAgentConfiguration; import jetbrains.buildServer.agent.BuildProgressLogger; import jetbrains.buildServer.agent.FlowLogger; -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.buildTriggers.vcs.mercurial.command.*; import jetbrains.buildServer.buildTriggers.vcs.mercurial.ext.MercurialExtensionManager; import jetbrains.buildServer.util.FileUtil; +import jetbrains.buildServer.util.TestFor; import jetbrains.buildServer.vcs.CheckoutRules; import jetbrains.buildServer.vcs.IncludeRule; import jetbrains.buildServer.vcs.VcsException; @@ -47,6 +45,7 @@ @Test public class AgentSideCheckoutWithSharedMirrorsTest extends BaseMercurialPatchTestCase { + private MirrorManager myMirrorManager; private File myOriginalRepositoriesParentDir; private MercurialAgentSideVcsSupport myVcsSupport; private File myWorkDir; @@ -73,8 +72,9 @@ }}); final AgentPluginConfigImpl pluginConfig = new AgentPluginConfigImpl(agentConfig); + myMirrorManager = new MirrorManagerImpl(pluginConfig); myVcsSupport = new MercurialAgentSideVcsSupport(pluginConfig, - new MirrorManagerImpl(pluginConfig), + myMirrorManager, new AgentRepoFactory(pluginConfig, new CommandSettingsForRootImpl(new TestCommandSettingsFactory(), new ExtensionsWeaver(), new CommandlineViaFileWrapperWeaver()), new AgentHgPathProvider(agentConfig)), new MercurialExtensionManager()); @@ -133,6 +133,28 @@ } + @TestFor(issues = "TW-39482") + public void should_recover_from_abandoned_transaction() throws Exception { + File remoteRepo = myTempFiles.createTempDir(); + Util.copyRepository(new File("mercurial-tests/testData/bookmarks/1"), remoteRepo); + VcsRootImpl root = vcsRoot().withUrl(remoteRepo).build(); + + //checkout sources, so that shared mirror is created + update(root, "5:e052c89b1159"); + + //make next pull fail + File mirror = myMirrorManager.getMirrorDir(new HgVcsRoot(root).getRepository()); + FileUtil.writeFile(new File(new File(new File(mirror, ".hg"), "store"), "journal"), "", "UTF-8"); + + //update remote repo so that next build requires pull + FileUtil.delete(remoteRepo); + Util.copyRepository(new File("mercurial-tests/testData/bookmarks/2"), remoteRepo); + + //run build which require pull + update(root, "6:7597a4da7195"); + } + + @NotNull private File[] listFiles(@NotNull File dir) { File[] files = dir.listFiles();