changeset 668:d25f0324a27a

Delete bundle with push/pull changes once command completes successfully. Test for bundle generator
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Thu, 11 Jul 2013 18:41:40 +0200
parents fba85bc1dfb8
children b1a3a056d7e6
files build.xml src/org/tmatesoft/hg/core/HgPullCommand.java src/org/tmatesoft/hg/core/HgPushCommand.java src/org/tmatesoft/hg/internal/BundleGenerator.java src/org/tmatesoft/hg/repo/HgParentChildMap.java test/org/tmatesoft/hg/test/TestBundle.java
diffstat 6 files changed, 147 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- 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 @@
 			<test name="org.tmatesoft.hg.test.TestBranches" />
 			<test name="org.tmatesoft.hg.test.TestByteChannel" />
 			<test name="org.tmatesoft.hg.test.TestSubrepo" />
+			<test name="org.tmatesoft.hg.test.TestBundle" />
 			<test name="org.tmatesoft.hg.test.TestClone" />
 			<test name="org.tmatesoft.hg.test.TestIncoming" />
 			<test name="org.tmatesoft.hg.test.TestOutgoing" />
--- 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 {
--- 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) {
--- 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<Nodeid> l = new ArrayList<Nodeid>();
-		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 {
--- 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<Nodei> immediateChildren = pw.directChildren(me);
  * </pre>
  * 
+ * <p>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.
  * 
  * <p> 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.
--- /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<Nodeid> l = new ArrayList<Nodeid>();
+		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<String> 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<String> foundFiles = new ArrayList<String>(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<Nodeid> csets, manifests;
+		public Map<String, List<Nodeid>> files = new HashMap<String, List<Nodeid>>();
+		private List<Nodeid> actual;
+
+		public void changelogStart() throws HgRuntimeException {
+			assertFalse(clogEnter);
+			assertFalse(clogExit);
+			clogEnter = true;
+			actual = csets = new ArrayList<Nodeid>();
+		}
+
+		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<Nodeid>();
+		}
+
+		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<Nodeid>());
+		}
+
+		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;
+		}
+	}
+}