Mercurial > hg > mercurial
changeset 834:80ae3dc66685
TW-18605 add support for 'hg purge'
line wrap: on
line diff
--- a/mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialIncludeRuleUpdater.java Fri May 30 18:42:53 2014 +0200 +++ b/mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialIncludeRuleUpdater.java Sun Jun 01 22:16:18 2014 +0200 @@ -31,6 +31,8 @@ import java.io.File; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import static com.intellij.openapi.util.io.FileUtil.delete; @@ -152,11 +154,29 @@ private void updateWorkingDir(@NotNull File workingDir, @NotNull String toVersion, @NotNull String repositoryUrl) throws VcsException, IOException { HgRepo repo = myRepoFactory.createRepo(myRoot, workingDir); - updateSubrepositories(repo, toVersion, repositoryUrl); + List<File> repos = new ArrayList<File>(); + updateSubrepositories(repo, toVersion, repositoryUrl, repos); doUpdateWorkingDir(repo, toVersion); + purge(repos); } - private void updateSubrepositories(@NotNull HgRepo repo, @NotNull String toVersion, @NotNull String parentRepositoryUrl) throws VcsException, IOException { + private void purge(@NotNull List<File> dirs) throws VcsException { + HgVcsRoot.PurgePolicy purgePolicy = myRoot.getPurgePolicy(); + if (purgePolicy == HgVcsRoot.PurgePolicy.DONT_RUN) + return; + for (File dir : dirs) { + myLogger.message("Run purge in " + dir.getAbsolutePath()); + HgRepo repo = myRepoFactory.createRepo(myRoot, dir); + repo.purge().withPolicy(purgePolicy).call(); + myLogger.message("Purge in " + dir.getAbsolutePath() + " is finished"); + } + } + + private void updateSubrepositories(@NotNull HgRepo repo, + @NotNull String toVersion, + @NotNull String parentRepositoryUrl, + @NotNull List<File> repoAccumulator) throws VcsException, IOException { + repoAccumulator.add(repo.getWorkingDir()); if (!repo.hasSubreposAtRevision(toVersion)) return; myLogger.message("Process subrepos of " + parentRepositoryUrl); @@ -183,7 +203,7 @@ Loggers.VCS.warn("Failed to resolve subrepo url '" + subrepoConfig.url() + "'", e); subrepoUrl = subrepoConfig.url(); } - updateSubrepositories(subrepository, subrepoConfig.revision(), subrepoUrl); + updateSubrepositories(subrepository, subrepoConfig.revision(), subrepoUrl, repoAccumulator); } }
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/Constants.java Fri May 30 18:42:53 2014 +0200 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/Constants.java Sun Jun 01 22:16:18 2014 +0200 @@ -34,6 +34,6 @@ String USE_ARCHIVE_FOR_PATCH = "useArchiveForPatch"; String HG_EXTENSIONS = "hg.extensions"; String HG_COMMANDLINE_VIA_FILE = "hg.pass.commandline.via.file"; - + String PURGE_POLICY = "purgePolicy"; String GLOBAL_DETECT_SUBREPO_CHANGES = "teamcity.hg.detectSubrepoChanges"; }
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgRepo.java Fri May 30 18:42:53 2014 +0200 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgRepo.java Sun Jun 01 22:16:18 2014 +0200 @@ -166,6 +166,10 @@ FileUtil.delete(new File(dotHg, "bookmarks.current")); } + public PurgeCommand purge() { + return new PurgeCommand(myCommandSettingsFactory.create(), myHgPath, myWorkingDir); + } + public String getHgPath() { return myHgPath; }
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/HgVcsRoot.java Fri May 30 18:42:53 2014 +0200 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/HgVcsRoot.java Sun Jun 01 22:16:18 2014 +0200 @@ -45,6 +45,7 @@ private final boolean myUseTagsAsBranches; private final boolean myIncludeSubreposInPatch; private final boolean myUseArchiveForPatch; + private final PurgePolicy myPurgePolicy; public HgVcsRoot(@NotNull final VcsRoot vcsRoot) { this(vcsRoot.getProperties()); @@ -64,6 +65,15 @@ String includeSubreposProp = getProperty(Constants.INCLUDE_SUBREPOS_IN_PATCH); myIncludeSubreposInPatch = includeSubreposProp == null ? true : Boolean.parseBoolean(includeSubreposProp);//true by default myUseArchiveForPatch = Boolean.parseBoolean(getProperty(Constants.USE_ARCHIVE_FOR_PATCH)); + myPurgePolicy = readPurgePolicy(vcsRootProperties); + } + + @NotNull + private PurgePolicy readPurgePolicy(@NotNull Map<String, String> properties) { + String policy = properties.get(Constants.PURGE_POLICY); + if (StringUtil.isEmpty(policy)) + return PurgePolicy.DONT_RUN; + return PurgePolicy.valueOf(policy); } public HgVcsRoot withUrl(@NotNull String repositoryUrl) { @@ -171,7 +181,19 @@ } @NotNull + public PurgePolicy getPurgePolicy() { + return myPurgePolicy; + } + + @NotNull public Map<String, String> getProperties() { return myVcsRootProperties; } + + + public static enum PurgePolicy { + DONT_RUN, + PURGE_UNKNOWN, + PURGE_ALL + } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/PurgeCommand.java Sun Jun 01 22:16:18 2014 +0200 @@ -0,0 +1,50 @@ +/* + * 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.command; + +import jetbrains.buildServer.vcs.VcsException; +import org.jetbrains.annotations.NotNull; + +import java.io.File; + +public class PurgeCommand extends BaseCommand { + + private HgVcsRoot.PurgePolicy myPolicy; + + public PurgeCommand(@NotNull CommandSettings commandSettings, + @NotNull String hgPath, + @NotNull File workingDir) { + super(commandSettings, hgPath, workingDir); + } + + @NotNull + public PurgeCommand withPolicy(@NotNull HgVcsRoot.PurgePolicy policy) { + myPolicy = policy; + return this; + } + + public void call() throws VcsException { + if (myPolicy == null || myPolicy == HgVcsRoot.PurgePolicy.DONT_RUN) + return; + MercurialCommandLine cmd = createCommandLine(); + cmd.addParameters("--config", "extensions.purge="); + cmd.addParameter("purge"); + if (myPolicy == HgVcsRoot.PurgePolicy.PURGE_ALL) + cmd.addParameter("--all"); + runCommand(cmd); + } +}
--- a/mercurial-server/resources/buildServerResources/mercurialSettings.jsp Fri May 30 18:42:53 2014 +0200 +++ b/mercurial-server/resources/buildServerResources/mercurialSettings.jsp Sun Jun 01 22:16:18 2014 +0200 @@ -101,5 +101,21 @@ </td> </tr> </l:settingsGroup> - + <l:settingsGroup title="Agent Settings" className="advancedSetting"> + <tr class="advancedSetting"> + <td colspan="2">Agent-specific settings that are used in case of agent checkout.</td> + </tr> + <tr class="advancedSetting"> + <th> + <label for="purgePolicy">Purge settings:</label> + </th> + <td> + <props:selectProperty name="purgePolicy" enableFilter="true" className="mediumField"> + <props:option value="">Don't run purge</props:option> + <props:option value="PURGE_UNKNOWN">Purge unknown files</props:option> + <props:option value="PURGE_ALL">Purge ignored & unknown files</props:option> + </props:selectProperty> + </td> + </tr> + </l:settingsGroup> </table>
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentSideCheckoutTest.java Fri May 30 18:42:53 2014 +0200 +++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentSideCheckoutTest.java Sun Jun 01 22:16:18 2014 +0200 @@ -130,7 +130,7 @@ return future.get(); } - private File doUpdate(@NotNull VcsRoot root, @NotNull String version) throws VcsException { + protected File doUpdate(@NotNull VcsRoot root, @NotNull String version) throws VcsException { return doUpdate(root, version, IncludeRule.createDefaultInstance()); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/BaseAgentSideCheckoutTestCase.java Sun Jun 01 22:16:18 2014 +0200 @@ -0,0 +1,89 @@ +/* + * 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.agent.vcs.UpdateByIncludeRules2; +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.vcs.CheckoutRules; +import jetbrains.buildServer.vcs.IncludeRule; +import jetbrains.buildServer.vcs.VcsException; +import jetbrains.buildServer.vcs.VcsRoot; +import org.jetbrains.annotations.NotNull; +import org.jmock.Expectations; +import org.jmock.Mockery; +import org.testng.annotations.BeforeMethod; + +import java.io.File; +import java.util.HashMap; + +public abstract class BaseAgentSideCheckoutTestCase extends BaseMercurialTestCase { + + protected Mockery myContext; + protected BuildProgressLogger myLogger; + protected UpdateByIncludeRules2 myVcsSupport; + private int myBuildCounter = 0; + protected File myWorkDir; + + @Override + @BeforeMethod + public void setUp() throws Exception { + super.setUp(); + + myContext = new Mockery(); + + final BuildAgentConfiguration agentConfig = myContext.mock(BuildAgentConfiguration.class); + myContext.checking(new Expectations() {{ + allowing(agentConfig).getCacheDirectory("mercurial"); will(returnValue(myTempFiles.createTempDir())); + allowing(agentConfig).getParametersResolver(); will(returnValue(new HgPathResolver())); + }}); + + final AgentPluginConfigImpl pluginConfig = new AgentPluginConfigImpl(agentConfig); + MirrorManager mirrorManager = new MirrorManagerImpl(pluginConfig); + CommandSettingsForRootImpl commandSettingsFactory = new CommandSettingsForRootImpl(new TestCommandSettingsFactory(), new ExtensionsWeaver(), new CommandlineViaFileWrapperWeaver()); + myVcsSupport = new MercurialAgentSideVcsSupport(pluginConfig, mirrorManager, new AgentRepoFactory(commandSettingsFactory, new AgentHgPathProvider(agentConfig))); + + myLogger = myContext.mock(BuildProgressLogger.class); + myContext.checking(new Expectations() {{ + allowing(myLogger).message(with(any(String.class))); + allowing(myLogger).warning(with(any(String.class))); + }}); + + myWorkDir = myTempFiles.createTempDir(); + } + + + protected void checkout(@NotNull VcsRoot vcsRoot, @NotNull String toVersion) throws VcsException { + checkout(vcsRoot, toVersion, false); + } + + protected void checkout(@NotNull VcsRoot vcsRoot, @NotNull String toVersion, final boolean useLocalMirrors) throws VcsException { + final AgentRunningBuild build = myContext.mock(AgentRunningBuild.class, "build" + myBuildCounter++); + myContext.checking(new Expectations() {{ + allowing(build).getBuildLogger(); will(returnValue(myLogger)); + allowing(build).getSharedConfigParameters(); will(returnValue(new HashMap<String, String>() {{ + put("teamcity.hg.use.local.mirrors", useLocalMirrors ? "true" : "false"); + }})); + }}); + myVcsSupport.getUpdater(vcsRoot, CheckoutRules.DEFAULT, toVersion, myWorkDir, build, false).process(IncludeRule.createDefaultInstance(), myWorkDir); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/PurgeTest.java Sun Jun 01 22:16:18 2014 +0200 @@ -0,0 +1,127 @@ +/* + * 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.buildTriggers.vcs.mercurial.command.HgVcsRoot; +import jetbrains.buildServer.util.FileUtil; +import jetbrains.buildServer.vcs.VcsRoot; +import org.jetbrains.annotations.NotNull; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.IOException; + +import static jetbrains.buildServer.buildTriggers.vcs.mercurial.Util.copyRepository; +import static jetbrains.buildServer.buildTriggers.vcs.mercurial.VcsRootBuilder.vcsRoot; +import static org.testng.AssertJUnit.assertFalse; +import static org.testng.AssertJUnit.assertTrue; + +@Test +public class PurgeTest extends BaseAgentSideCheckoutTestCase { + + private String myRemoteRepository; + + @Override + @BeforeMethod + public void setUp() throws Exception { + super.setUp(); + + File tmp = myTempFiles.createTempDir(); + File remoteRepo = new File(tmp, "testPurge"); + copyRepository(new File("mercurial-tests/testData/testPurge"), remoteRepo); + myRemoteRepository = remoteRepo.getAbsolutePath(); + } + + + public void purge_unknown() throws Exception { + VcsRoot vcsRoot = vcsRoot().withUrl(myRemoteRepository).withPurgePolicy(HgVcsRoot.PurgePolicy.PURGE_UNKNOWN).build(); + checkout(vcsRoot, "1:80a857d1f74b"); + + File unknownFile = createUnknownFile(myWorkDir); + File ignoredFile = createIgnoredFile(myWorkDir); + + checkout(vcsRoot, "1:80a857d1f74b"); + + assertFalse(unknownFile.exists()); + assertTrue(ignoredFile.exists()); + } + + + public void purge_all() throws Exception { + VcsRoot vcsRoot = vcsRoot().withUrl(myRemoteRepository).withPurgePolicy(HgVcsRoot.PurgePolicy.PURGE_ALL).build(); + checkout(vcsRoot, "1:80a857d1f74b"); + + File unknownFile = createUnknownFile(myWorkDir); + File ignoredFile = createIgnoredFile(myWorkDir); + + checkout(vcsRoot, "1:80a857d1f74b"); + + assertFalse(unknownFile.exists()); + assertFalse(ignoredFile.exists()); + } + + + public void purge_unknown_subrepos() throws Exception { + VcsRoot vcsRoot = vcsRoot().withUrl(myRemoteRepository).withPurgePolicy(HgVcsRoot.PurgePolicy.PURGE_UNKNOWN).build(); + checkout(vcsRoot, "2:5998f41141bc"); + + File unknownFile = createUnknownFile(myWorkDir); + File ignoredFile = createIgnoredFile(myWorkDir); + File unknownFileSubrepo = createUnknownFile(new File(myWorkDir, "self")); + File ignoredFileSubrepo = createIgnoredFile(new File(myWorkDir, "self")); + + checkout(vcsRoot, "2:5998f41141bc"); + + assertFalse(unknownFile.exists()); + assertFalse(unknownFileSubrepo.exists()); + assertTrue(ignoredFile.exists()); + assertTrue(ignoredFileSubrepo.exists()); + } + + + public void purge_all_subrepos() throws Exception { + VcsRoot vcsRoot = vcsRoot().withUrl(myRemoteRepository).withPurgePolicy(HgVcsRoot.PurgePolicy.PURGE_ALL).build(); + checkout(vcsRoot, "2:5998f41141bc"); + + File unknownFile = createUnknownFile(myWorkDir); + File ignoredFile = createIgnoredFile(myWorkDir); + File unknownFileSubrepo = createUnknownFile(new File(myWorkDir, "self")); + File ignoredFileSubrepo = createIgnoredFile(new File(myWorkDir, "self")); + + checkout(vcsRoot, "2:5998f41141bc"); + + assertFalse(unknownFile.exists()); + assertFalse(unknownFileSubrepo.exists()); + assertFalse(ignoredFile.exists()); + assertFalse(ignoredFileSubrepo.exists()); + } + + + private File createUnknownFile(@NotNull File parentDir) throws IOException { + File unknownFile = new File(parentDir, "unknownFile"); + FileUtil.writeFile(unknownFile, "some data", "UTF-8"); + return unknownFile; + } + + + private File createIgnoredFile(@NotNull File parentDir) throws IOException { + File ignoredFile = new File(parentDir, "ignoredFile"); + FileUtil.writeFile(ignoredFile, "some data", "UTF-8"); + return ignoredFile; + } +}
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/VcsRootBuilder.java Fri May 30 18:42:53 2014 +0200 +++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/VcsRootBuilder.java Sun Jun 01 22:16:18 2014 +0200 @@ -16,6 +16,7 @@ package jetbrains.buildServer.buildTriggers.vcs.mercurial; +import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.HgVcsRoot; import jetbrains.buildServer.util.StringUtil; import jetbrains.buildServer.vcs.SVcsRoot; import jetbrains.buildServer.vcs.impl.VcsRootImpl; @@ -45,6 +46,7 @@ private boolean myTagsAsBranches = false; private boolean myIncludeSubreposInPatch = true; private boolean myUseArchiveForPatch = false; + private HgVcsRoot.PurgePolicy myPurgePolicy; public static VcsRootBuilder vcsRoot() { return new VcsRootBuilder(); @@ -66,6 +68,8 @@ if (myCloneRepositoryTo != null) vcsRoot.addProperty(Constants.SERVER_CLONE_PATH_PROP, String.valueOf(myCloneRepositoryTo.getAbsolutePath())); vcsRoot.addProperty(Constants.USE_TAGS_AS_BRANCHES, String.valueOf(myTagsAsBranches)); + if (myPurgePolicy != null) + vcsRoot.addProperty(Constants.PURGE_POLICY, myPurgePolicy.name()); return vcsRoot; } @@ -183,4 +187,10 @@ myTagsAsBranches = useTagsAsBranches; return this; } + + + public VcsRootBuilder withPurgePolicy(HgVcsRoot.PurgePolicy policy) { + myPurgePolicy = policy; + return this; + } }
--- a/mercurial-tests/src/testng.xml Fri May 30 18:42:53 2014 +0200 +++ b/mercurial-tests/src/testng.xml Sun Jun 01 22:16:18 2014 +0200 @@ -54,6 +54,7 @@ <class name="jetbrains.buildServer.buildTriggers.vcs.mercurial.MercurialModificationInfoBuilderTest"/> <class name="jetbrains.buildServer.buildTriggers.vcs.mercurial.MercurialUrlSupportTest"/> <class name="jetbrains.buildServer.buildTriggers.vcs.mercurial.command.CommitsAndMountPointsCommandParserTest"/> + <class name="jetbrains.buildServer.buildTriggers.vcs.mercurial.PurgeTest"/> </classes> </test> </suite>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-tests/testData/testPurge/README Sun Jun 01 22:16:18 2014 +0200 @@ -0,0 +1,5 @@ +o changeset: 2:5998f41141bc //add same repo as a subrepo at path self +| +o changeset: 1:80a857d1f74b //ignores ignoredFile +| +o changeset: 0:8a9ae2d32de0 //contains file a
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-tests/testData/testPurge/hg/branch Sun Jun 01 22:16:18 2014 +0200 @@ -0,0 +1,1 @@ +default
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-tests/testData/testPurge/hg/cache/branchheads-served Sun Jun 01 22:16:18 2014 +0200 @@ -0,0 +1,2 @@ +5998f41141bcbe2fa5cd423902ddb75deb5ce4a6 2 +5998f41141bcbe2fa5cd423902ddb75deb5ce4a6 default
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-tests/testData/testPurge/hg/cache/tags Sun Jun 01 22:16:18 2014 +0200 @@ -0,0 +1,2 @@ +2 5998f41141bcbe2fa5cd423902ddb75deb5ce4a6 +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-tests/testData/testPurge/hg/last-message.txt Sun Jun 01 22:16:18 2014 +0200 @@ -0,0 +1,1 @@ +Add same repo in rev 1 as subrepo at path self \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-tests/testData/testPurge/hg/requires Sun Jun 01 22:16:18 2014 +0200 @@ -0,0 +1,4 @@ +dotencode +fncache +revlogv1 +store
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-tests/testData/testPurge/hg/store/fncache Sun Jun 01 22:16:18 2014 +0200 @@ -0,0 +1,4 @@ +data/.hgsubstate.i +data/.hgignore.i +data/.hgsub.i +data/a.i
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-tests/testData/testPurge/hg/store/phaseroots Sun Jun 01 22:16:18 2014 +0200 @@ -0,0 +1,1 @@ +1 8a9ae2d32de0d0c80124f88ec18e376587b0ecdb
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-tests/testData/testPurge/hg/store/undo.phaseroots Sun Jun 01 22:16:18 2014 +0200 @@ -0,0 +1,1 @@ +1 8a9ae2d32de0d0c80124f88ec18e376587b0ecdb
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-tests/testData/testPurge/hg/undo.branch Sun Jun 01 22:16:18 2014 +0200 @@ -0,0 +1,1 @@ +default \ No newline at end of file