Mercurial > hg4j
comparison 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 |
comparison
equal
deleted
inserted
replaced
511:122e0600799f | 512:10ca3ede8367 |
---|---|
16 */ | 16 */ |
17 package org.tmatesoft.hg.repo; | 17 package org.tmatesoft.hg.repo; |
18 | 18 |
19 import java.io.File; | 19 import java.io.File; |
20 import java.io.IOException; | 20 import java.io.IOException; |
21 import java.util.ConcurrentModificationException; | |
21 | 22 |
22 import org.tmatesoft.hg.core.Nodeid; | 23 import org.tmatesoft.hg.core.Nodeid; |
23 import org.tmatesoft.hg.core.SessionContext; | 24 import org.tmatesoft.hg.core.SessionContext; |
24 import org.tmatesoft.hg.internal.ByteArrayChannel; | 25 import org.tmatesoft.hg.internal.ByteArrayChannel; |
25 import org.tmatesoft.hg.internal.ByteArrayDataAccess; | 26 import org.tmatesoft.hg.internal.ByteArrayDataAccess; |
27 import org.tmatesoft.hg.internal.Callback; | |
26 import org.tmatesoft.hg.internal.DataAccess; | 28 import org.tmatesoft.hg.internal.DataAccess; |
27 import org.tmatesoft.hg.internal.DataAccessProvider; | 29 import org.tmatesoft.hg.internal.DataAccessProvider; |
28 import org.tmatesoft.hg.internal.DigestHelper; | 30 import org.tmatesoft.hg.internal.DigestHelper; |
29 import org.tmatesoft.hg.internal.Experimental; | 31 import org.tmatesoft.hg.internal.Experimental; |
30 import org.tmatesoft.hg.internal.InflaterDataAccess; | 32 import org.tmatesoft.hg.internal.InflaterDataAccess; |
33 import org.tmatesoft.hg.internal.Lifecycle; | |
31 import org.tmatesoft.hg.internal.Patch; | 34 import org.tmatesoft.hg.internal.Patch; |
32 import org.tmatesoft.hg.repo.HgChangelog.RawChangeset; | 35 import org.tmatesoft.hg.repo.HgChangelog.RawChangeset; |
36 import org.tmatesoft.hg.util.Adaptable; | |
33 import org.tmatesoft.hg.util.CancelledException; | 37 import org.tmatesoft.hg.util.CancelledException; |
34 | 38 |
35 /** | 39 /** |
36 * WORK IN PROGRESS | 40 * WORK IN PROGRESS |
37 * | 41 * |
44 public class HgBundle { | 48 public class HgBundle { |
45 | 49 |
46 private final File bundleFile; | 50 private final File bundleFile; |
47 private final DataAccessProvider accessProvider; | 51 private final DataAccessProvider accessProvider; |
48 // private final SessionContext sessionContext; | 52 // private final SessionContext sessionContext; |
53 private Lifecycle.BasicCallback flowControl; | |
49 | 54 |
50 HgBundle(SessionContext ctx, DataAccessProvider dap, File bundle) { | 55 HgBundle(SessionContext ctx, DataAccessProvider dap, File bundle) { |
51 // sessionContext = ctx; | 56 // sessionContext = ctx; |
52 accessProvider = dap; | 57 accessProvider = dap; |
53 bundleFile = bundle; | 58 bundleFile = bundle; |
184 }; | 189 }; |
185 inspectChangelog(bundleInsp); | 190 inspectChangelog(bundleInsp); |
186 } | 191 } |
187 | 192 |
188 // callback to minimize amount of Strings and Nodeids instantiated | 193 // callback to minimize amount of Strings and Nodeids instantiated |
194 @Callback | |
189 public interface Inspector { | 195 public interface Inspector { |
190 void changelogStart(); | 196 void changelogStart(); |
191 | 197 |
192 void changelogEnd(); | 198 void changelogEnd(); |
193 | 199 |
214 */ | 220 */ |
215 public void inspectChangelog(Inspector inspector) throws HgRuntimeException { | 221 public void inspectChangelog(Inspector inspector) throws HgRuntimeException { |
216 if (inspector == null) { | 222 if (inspector == null) { |
217 throw new IllegalArgumentException(); | 223 throw new IllegalArgumentException(); |
218 } | 224 } |
225 final Lifecycle lifecycle = lifecycleSetUp(inspector); | |
219 DataAccess da = null; | 226 DataAccess da = null; |
220 try { | 227 try { |
221 da = getDataStream(); | 228 da = getDataStream(); |
222 internalInspectChangelog(da, inspector); | 229 internalInspectChangelog(da, inspector); |
223 } catch (IOException ex) { | 230 } catch (IOException ex) { |
224 throw new HgInvalidFileException("Bundle.inspectChangelog failed", ex, bundleFile); | 231 throw new HgInvalidFileException("Bundle.inspectChangelog failed", ex, bundleFile); |
225 } finally { | 232 } finally { |
226 if (da != null) { | 233 if (da != null) { |
227 da.done(); | 234 da.done(); |
228 } | 235 } |
236 lifecycleTearDown(lifecycle); | |
229 } | 237 } |
230 } | 238 } |
231 | 239 |
232 /** | 240 /** |
233 * @param inspector callback to visit manifest entries | 241 * @param inspector callback to visit manifest entries |
236 */ | 244 */ |
237 public void inspectManifest(Inspector inspector) throws HgRuntimeException { | 245 public void inspectManifest(Inspector inspector) throws HgRuntimeException { |
238 if (inspector == null) { | 246 if (inspector == null) { |
239 throw new IllegalArgumentException(); | 247 throw new IllegalArgumentException(); |
240 } | 248 } |
249 final Lifecycle lifecycle = lifecycleSetUp(inspector); | |
241 DataAccess da = null; | 250 DataAccess da = null; |
242 try { | 251 try { |
243 da = getDataStream(); | 252 da = getDataStream(); |
244 if (da.isEmpty()) { | 253 if (da.isEmpty()) { |
245 return; | 254 return; |
250 throw new HgInvalidFileException("Bundle.inspectManifest failed", ex, bundleFile); | 259 throw new HgInvalidFileException("Bundle.inspectManifest failed", ex, bundleFile); |
251 } finally { | 260 } finally { |
252 if (da != null) { | 261 if (da != null) { |
253 da.done(); | 262 da.done(); |
254 } | 263 } |
264 lifecycleTearDown(lifecycle); | |
255 } | 265 } |
256 } | 266 } |
257 | 267 |
258 /** | 268 /** |
259 * @param inspector callback to visit file entries | 269 * @param inspector callback to visit file entries |
262 */ | 272 */ |
263 public void inspectFiles(Inspector inspector) throws HgRuntimeException { | 273 public void inspectFiles(Inspector inspector) throws HgRuntimeException { |
264 if (inspector == null) { | 274 if (inspector == null) { |
265 throw new IllegalArgumentException(); | 275 throw new IllegalArgumentException(); |
266 } | 276 } |
277 final Lifecycle lifecycle = lifecycleSetUp(inspector); | |
267 DataAccess da = null; | 278 DataAccess da = null; |
268 try { | 279 try { |
269 da = getDataStream(); | 280 da = getDataStream(); |
270 if (da.isEmpty()) { | 281 if (da.isEmpty()) { |
271 return; | 282 return; |
280 throw new HgInvalidFileException("Bundle.inspectFiles failed", ex, bundleFile); | 291 throw new HgInvalidFileException("Bundle.inspectFiles failed", ex, bundleFile); |
281 } finally { | 292 } finally { |
282 if (da != null) { | 293 if (da != null) { |
283 da.done(); | 294 da.done(); |
284 } | 295 } |
296 lifecycleTearDown(lifecycle); | |
285 } | 297 } |
286 } | 298 } |
287 | 299 |
288 /** | 300 /** |
289 * @param inspector visit complete bundle (changelog, manifest and file entries) | 301 * @param inspector visit complete bundle (changelog, manifest and file entries) |
292 */ | 304 */ |
293 public void inspectAll(Inspector inspector) throws HgRuntimeException { | 305 public void inspectAll(Inspector inspector) throws HgRuntimeException { |
294 if (inspector == null) { | 306 if (inspector == null) { |
295 throw new IllegalArgumentException(); | 307 throw new IllegalArgumentException(); |
296 } | 308 } |
309 final Lifecycle lifecycle = lifecycleSetUp(inspector); | |
297 DataAccess da = null; | 310 DataAccess da = null; |
298 try { | 311 try { |
299 da = getDataStream(); | 312 da = getDataStream(); |
300 internalInspectChangelog(da, inspector); | 313 internalInspectChangelog(da, inspector); |
301 internalInspectManifest(da, inspector); | 314 internalInspectManifest(da, inspector); |
304 throw new HgInvalidFileException("Bundle.inspectAll failed", ex, bundleFile); | 317 throw new HgInvalidFileException("Bundle.inspectAll failed", ex, bundleFile); |
305 } finally { | 318 } finally { |
306 if (da != null) { | 319 if (da != null) { |
307 da.done(); | 320 da.done(); |
308 } | 321 } |
309 } | 322 lifecycleTearDown(lifecycle); |
323 } | |
324 } | |
325 | |
326 // initialize flowControl, check for concurrent usage, starts lifecyle, if any | |
327 // return non-null only if inspector is interested in lifecycle events | |
328 private Lifecycle lifecycleSetUp(Inspector inspector) throws ConcurrentModificationException { | |
329 // Don't need flowControl in case Inspector doesn't implement Lifecycle, | |
330 // however is handy not to expect it == null inside internalInspect* | |
331 // XXX Once there's need to make this class thread-safe, | |
332 // shall move flowControl to thread-local state. | |
333 if (flowControl != null) { | |
334 throw new ConcurrentModificationException("HgBundle is in use and not thread-safe yet"); | |
335 } | |
336 flowControl = new Lifecycle.BasicCallback(); | |
337 final Lifecycle lifecycle = Adaptable.Factory.getAdapter(inspector, Lifecycle.class, null); | |
338 if (lifecycle != null) { | |
339 lifecycle.start(-1, flowControl, flowControl); | |
340 } | |
341 return lifecycle; | |
342 } | |
343 | |
344 private void lifecycleTearDown(Lifecycle lifecycle) { | |
345 if (lifecycle != null) { | |
346 lifecycle.finish(flowControl); | |
347 } | |
348 flowControl = null; | |
310 } | 349 } |
311 | 350 |
312 private void internalInspectChangelog(DataAccess da, Inspector inspector) throws IOException { | 351 private void internalInspectChangelog(DataAccess da, Inspector inspector) throws IOException { |
313 if (da.isEmpty()) { | 352 if (da.isEmpty()) { |
314 return; | 353 return; |