# HG changeset patch # User Artem Tikhomirov # Date 1373560900 -7200 # Node ID d25f0324a27ad670fbcc4d077bf3c73720fc8875 # Parent fba85bc1dfb81125b12c8b45e8add65eda221927 Delete bundle with push/pull changes once command completes successfully. Test for bundle generator diff -r fba85bc1dfb8 -r d25f0324a27a build.xml --- a/build.xml Thu Jul 11 17:54:08 2013 +0200 +++ b/build.xml Thu Jul 11 18:41:40 2013 +0200 @@ -97,6 +97,7 @@ + diff -r fba85bc1dfb8 -r d25f0324a27a src/org/tmatesoft/hg/core/HgPullCommand.java --- a/src/org/tmatesoft/hg/core/HgPullCommand.java Thu Jul 11 17:54:08 2013 +0200 +++ b/src/org/tmatesoft/hg/core/HgPullCommand.java Thu Jul 11 18:41:40 2013 +0200 @@ -109,6 +109,7 @@ phaseHelper.synchronizeWithRemote(remotePhases, rsCommon.union(added)); } progress.worked(5); + incoming.unlink(); // keep the file only in case of failure } catch (HgRuntimeException ex) { throw new HgLibraryFailureException(ex); } finally { diff -r fba85bc1dfb8 -r d25f0324a27a src/org/tmatesoft/hg/core/HgPushCommand.java --- a/src/org/tmatesoft/hg/core/HgPushCommand.java Thu Jul 11 17:54:08 2013 +0200 +++ b/src/org/tmatesoft/hg/core/HgPushCommand.java Thu Jul 11 18:41:40 2013 +0200 @@ -135,6 +135,7 @@ } // XXX WTF is obsolete in namespaces key?? progress.worked(5); + b.unlink(); // keep the file only in case of failure } catch (IOException ex) { throw new HgIOException(ex.getMessage(), null); // XXX not a nice idea to throw IOException from BundleGenerator#create } catch (HgRepositoryNotFoundException ex) { diff -r fba85bc1dfb8 -r d25f0324a27a src/org/tmatesoft/hg/internal/BundleGenerator.java --- a/src/org/tmatesoft/hg/internal/BundleGenerator.java Thu Jul 11 17:54:08 2013 +0200 +++ b/src/org/tmatesoft/hg/internal/BundleGenerator.java Thu Jul 11 18:41:40 2013 +0200 @@ -35,15 +35,11 @@ import org.tmatesoft.hg.core.Nodeid; import org.tmatesoft.hg.internal.DataSerializer.OutputStreamSerializer; import org.tmatesoft.hg.internal.Patch.PatchDataSource; -import org.tmatesoft.hg.repo.HgBundle; import org.tmatesoft.hg.repo.HgChangelog; import org.tmatesoft.hg.repo.HgChangelog.RawChangeset; import org.tmatesoft.hg.repo.HgDataFile; -import org.tmatesoft.hg.repo.HgInternals; import org.tmatesoft.hg.repo.HgInvalidControlFileException; -import org.tmatesoft.hg.repo.HgLookup; import org.tmatesoft.hg.repo.HgManifest; -import org.tmatesoft.hg.repo.HgRepository; import org.tmatesoft.hg.repo.HgRuntimeException; /** @@ -143,20 +139,6 @@ return files; } - - public static void main(String[] args) throws Exception { - final HgLookup hgLookup = new HgLookup(); - HgRepository hgRepo = hgLookup.detectFromWorkingDir(); - BundleGenerator bg = new BundleGenerator(HgInternals.getImplementationRepo(hgRepo)); - ArrayList l = new ArrayList(); - l.add(Nodeid.fromAscii("9ef1fab9f5e3d51d70941121dc27410e28069c2d")); // 640 - l.add(Nodeid.fromAscii("2f33f102a8fa59274a27ebbe1c2903cecac6c5d5")); // 639 - l.add(Nodeid.fromAscii("d074971287478f69ab0a64176ce2284d8c1e91c3")); // 638 - File bundleFile = bg.create(l); - HgBundle b = hgLookup.loadBundle(bundleFile); -// Bundle.dump(b); // FIXME dependency from dependant code - } - private static class ChunkGenerator implements RevlogStream.Inspector { private final DataSerializer ds; @@ -222,7 +204,6 @@ int len = pds.serializeLength() + 84; ds.writeInt(len); ds.write(nodeid, 0, Nodeid.SIZE); - // TODO assert parents match those in previous group elements if (parent1Revision != NO_REVISION) { ds.writeByte(parentMap.get(parent1Revision).toByteArray()); } else { diff -r fba85bc1dfb8 -r d25f0324a27a src/org/tmatesoft/hg/repo/HgParentChildMap.java --- a/src/org/tmatesoft/hg/repo/HgParentChildMap.java Thu Jul 11 17:54:08 2013 +0200 +++ b/src/org/tmatesoft/hg/repo/HgParentChildMap.java Thu Jul 11 18:41:40 2013 +0200 @@ -50,6 +50,9 @@ * List immediateChildren = pw.directChildren(me); * * + *

Note, this map represents a snapshot of repository state at specific point, and is not automatically + * updated/refreshed along with repository changes. I.e. any revision committed after this map was initialized + * won't be recognized as known. * *

Perhaps, later may add alternative way to access (and reuse) map instance, Revlog#getParentWalker(), * that instantiates and initializes ParentWalker, and keep SoftReference to allow its reuse. diff -r fba85bc1dfb8 -r d25f0324a27a test/org/tmatesoft/hg/test/TestBundle.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/org/tmatesoft/hg/test/TestBundle.java Thu Jul 11 18:41:40 2013 +0200 @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2013 TMate Software Ltd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * For information on how to redistribute this software under + * the terms of a license other than GNU General Public License + * contact TMate Software at support@hg4j.com + */ +package org.tmatesoft.hg.test; + +import static org.junit.Assert.*; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.junit.Rule; +import org.junit.Test; +import org.tmatesoft.hg.core.Nodeid; +import org.tmatesoft.hg.internal.BundleGenerator; +import org.tmatesoft.hg.repo.HgBundle; +import org.tmatesoft.hg.repo.HgBundle.GroupElement; +import org.tmatesoft.hg.repo.HgInternals; +import org.tmatesoft.hg.repo.HgLookup; +import org.tmatesoft.hg.repo.HgRepository; +import org.tmatesoft.hg.repo.HgRuntimeException; + +/** + * + * @author Artem Tikhomirov + * @author TMate Software Ltd. + */ +public class TestBundle { + @Rule + public ErrorCollectorExt errorCollector = new ErrorCollectorExt(); + + @Test + public void testCreateBundle() throws Exception { + final HgRepository hgRepo = Configuration.get().own(); + BundleGenerator bg = new BundleGenerator(HgInternals.getImplementationRepo(hgRepo)); + ArrayList l = new ArrayList(); + l.add(Nodeid.fromAscii("9ef1fab9f5e3d51d70941121dc27410e28069c2d")); // 640 + l.add(Nodeid.fromAscii("2f33f102a8fa59274a27ebbe1c2903cecac6c5d5")); // 639 + l.add(Nodeid.fromAscii("d074971287478f69ab0a64176ce2284d8c1e91c3")); // 638 + File bundleFile = bg.create(l); + HgBundle b = new HgLookup().loadBundle(bundleFile); + // + DumbInspector insp = new DumbInspector(); + b.inspectChangelog(insp); + errorCollector.assertTrue(insp.clogEnter && insp.clogExit); + errorCollector.assertFalse(insp.csets.isEmpty()); + errorCollector.assertFalse(insp.manifestEnter || insp.manifestExit); + Collections.sort(l); + Collections.sort(insp.csets); + errorCollector.assertEquals(l, insp.csets); + errorCollector.assertEquals(0, insp.filesEnter); + errorCollector.assertEquals(0, insp.filesExit); + errorCollector.assertTrue(insp.manifests == null || insp.manifests.isEmpty()); + errorCollector.assertTrue(insp.files.isEmpty()); + // + insp = new DumbInspector(); + b.inspectFiles(insp); + errorCollector.assertFalse(insp.clogEnter && insp.clogExit); + errorCollector.assertFalse(insp.manifestEnter || insp.manifestExit); + // $ hg log -r 638:640 --debug | grep files + List affectedFiles = Arrays.asList("src/org/tmatesoft/hg/repo/HgDataFile.java", "COPYING", "build.gradle", ".hgtags"); + // "src/org/tmatesoft/hg/repo/HgBlameInspector.java" was deleted in r638 and hence not part of the bundle + ArrayList foundFiles = new ArrayList(insp.files.keySet()); + Collections.sort(affectedFiles); + Collections.sort(foundFiles); + errorCollector.assertEquals(affectedFiles, foundFiles); + errorCollector.assertEquals(affectedFiles.size(), insp.filesEnter); + errorCollector.assertEquals(affectedFiles.size(), insp.filesExit); + b.unlink(); + } + + private static class DumbInspector implements HgBundle.Inspector { + public boolean clogEnter, clogExit, manifestEnter, manifestExit; + public int filesEnter, filesExit; + public List csets, manifests; + public Map> files = new HashMap>(); + private List actual; + + public void changelogStart() throws HgRuntimeException { + assertFalse(clogEnter); + assertFalse(clogExit); + clogEnter = true; + actual = csets = new ArrayList(); + } + + public void changelogEnd() throws HgRuntimeException { + assertTrue(clogEnter); + assertFalse(clogExit); + clogExit = true; + actual = null; + } + + public void manifestStart() throws HgRuntimeException { + assertFalse(manifestEnter); + assertFalse(manifestExit); + manifestEnter = true; + actual = manifests = new ArrayList(); + } + + public void manifestEnd() throws HgRuntimeException { + assertTrue(manifestEnter); + assertFalse(manifestExit); + manifestExit = true; + actual = null; + } + + public void fileStart(String name) throws HgRuntimeException { + assertEquals(filesEnter, filesExit); + filesEnter++; + files.put(name, actual = new ArrayList()); + } + + public void fileEnd(String name) throws HgRuntimeException { + assertEquals(filesEnter, 1 + filesExit); + filesExit++; + actual = null; + } + + public boolean element(GroupElement element) throws HgRuntimeException { + actual.add(element.node()); + return true; + } + } +}