Mercurial > hg4j
diff src/org/tmatesoft/hg/repo/HgBundle.java @ 512:10ca3ede8367
Issue 39: Progress and Cancel support for Clone command
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Fri, 14 Dec 2012 20:10:15 +0100 |
parents | 51d682cf9cdc |
children | a41d955dc360 |
line wrap: on
line diff
--- a/src/org/tmatesoft/hg/repo/HgBundle.java Fri Dec 14 15:39:49 2012 +0100 +++ b/src/org/tmatesoft/hg/repo/HgBundle.java Fri Dec 14 20:10:15 2012 +0100 @@ -18,18 +18,22 @@ import java.io.File; import java.io.IOException; +import java.util.ConcurrentModificationException; import org.tmatesoft.hg.core.Nodeid; import org.tmatesoft.hg.core.SessionContext; import org.tmatesoft.hg.internal.ByteArrayChannel; import org.tmatesoft.hg.internal.ByteArrayDataAccess; +import org.tmatesoft.hg.internal.Callback; import org.tmatesoft.hg.internal.DataAccess; import org.tmatesoft.hg.internal.DataAccessProvider; import org.tmatesoft.hg.internal.DigestHelper; import org.tmatesoft.hg.internal.Experimental; import org.tmatesoft.hg.internal.InflaterDataAccess; +import org.tmatesoft.hg.internal.Lifecycle; import org.tmatesoft.hg.internal.Patch; import org.tmatesoft.hg.repo.HgChangelog.RawChangeset; +import org.tmatesoft.hg.util.Adaptable; import org.tmatesoft.hg.util.CancelledException; /** @@ -46,6 +50,7 @@ private final File bundleFile; private final DataAccessProvider accessProvider; // private final SessionContext sessionContext; + private Lifecycle.BasicCallback flowControl; HgBundle(SessionContext ctx, DataAccessProvider dap, File bundle) { // sessionContext = ctx; @@ -186,6 +191,7 @@ } // callback to minimize amount of Strings and Nodeids instantiated + @Callback public interface Inspector { void changelogStart(); @@ -216,6 +222,7 @@ if (inspector == null) { throw new IllegalArgumentException(); } + final Lifecycle lifecycle = lifecycleSetUp(inspector); DataAccess da = null; try { da = getDataStream(); @@ -226,6 +233,7 @@ if (da != null) { da.done(); } + lifecycleTearDown(lifecycle); } } @@ -238,6 +246,7 @@ if (inspector == null) { throw new IllegalArgumentException(); } + final Lifecycle lifecycle = lifecycleSetUp(inspector); DataAccess da = null; try { da = getDataStream(); @@ -252,6 +261,7 @@ if (da != null) { da.done(); } + lifecycleTearDown(lifecycle); } } @@ -264,6 +274,7 @@ if (inspector == null) { throw new IllegalArgumentException(); } + final Lifecycle lifecycle = lifecycleSetUp(inspector); DataAccess da = null; try { da = getDataStream(); @@ -282,6 +293,7 @@ if (da != null) { da.done(); } + lifecycleTearDown(lifecycle); } } @@ -294,6 +306,7 @@ if (inspector == null) { throw new IllegalArgumentException(); } + final Lifecycle lifecycle = lifecycleSetUp(inspector); DataAccess da = null; try { da = getDataStream(); @@ -306,8 +319,34 @@ if (da != null) { da.done(); } + lifecycleTearDown(lifecycle); } } + + // initialize flowControl, check for concurrent usage, starts lifecyle, if any + // return non-null only if inspector is interested in lifecycle events + private Lifecycle lifecycleSetUp(Inspector inspector) throws ConcurrentModificationException { + // Don't need flowControl in case Inspector doesn't implement Lifecycle, + // however is handy not to expect it == null inside internalInspect* + // XXX Once there's need to make this class thread-safe, + // shall move flowControl to thread-local state. + if (flowControl != null) { + throw new ConcurrentModificationException("HgBundle is in use and not thread-safe yet"); + } + flowControl = new Lifecycle.BasicCallback(); + final Lifecycle lifecycle = Adaptable.Factory.getAdapter(inspector, Lifecycle.class, null); + if (lifecycle != null) { + lifecycle.start(-1, flowControl, flowControl); + } + return lifecycle; + } + + private void lifecycleTearDown(Lifecycle lifecycle) { + if (lifecycle != null) { + lifecycle.finish(flowControl); + } + flowControl = null; + } private void internalInspectChangelog(DataAccess da, Inspector inspector) throws IOException { if (da.isEmpty()) {