Mercurial > jhg
comparison src/org/tmatesoft/hg/core/HgCloneCommand.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 | b3c16d1aede0 |
children | a41d955dc360 |
comparison
equal
deleted
inserted
replaced
511:122e0600799f | 512:10ca3ede8367 |
---|---|
31 import java.util.zip.DeflaterOutputStream; | 31 import java.util.zip.DeflaterOutputStream; |
32 | 32 |
33 import org.tmatesoft.hg.internal.ByteArrayDataAccess; | 33 import org.tmatesoft.hg.internal.ByteArrayDataAccess; |
34 import org.tmatesoft.hg.internal.DataAccess; | 34 import org.tmatesoft.hg.internal.DataAccess; |
35 import org.tmatesoft.hg.internal.DigestHelper; | 35 import org.tmatesoft.hg.internal.DigestHelper; |
36 import org.tmatesoft.hg.internal.Lifecycle; | |
36 import org.tmatesoft.hg.internal.RepoInitializer; | 37 import org.tmatesoft.hg.internal.RepoInitializer; |
37 import org.tmatesoft.hg.repo.HgBundle; | 38 import org.tmatesoft.hg.repo.HgBundle; |
38 import org.tmatesoft.hg.repo.HgBundle.GroupElement; | 39 import org.tmatesoft.hg.repo.HgBundle.GroupElement; |
39 import org.tmatesoft.hg.repo.HgInvalidControlFileException; | 40 import org.tmatesoft.hg.repo.HgInvalidControlFileException; |
40 import org.tmatesoft.hg.repo.HgInvalidFileException; | 41 import org.tmatesoft.hg.repo.HgInvalidFileException; |
41 import org.tmatesoft.hg.repo.HgInvalidStateException; | 42 import org.tmatesoft.hg.repo.HgInvalidStateException; |
42 import org.tmatesoft.hg.repo.HgLookup; | 43 import org.tmatesoft.hg.repo.HgLookup; |
43 import org.tmatesoft.hg.repo.HgRemoteRepository; | 44 import org.tmatesoft.hg.repo.HgRemoteRepository; |
44 import org.tmatesoft.hg.repo.HgRepository; | 45 import org.tmatesoft.hg.repo.HgRepository; |
45 import org.tmatesoft.hg.repo.HgRuntimeException; | 46 import org.tmatesoft.hg.repo.HgRuntimeException; |
47 import org.tmatesoft.hg.util.CancelSupport; | |
46 import org.tmatesoft.hg.util.CancelledException; | 48 import org.tmatesoft.hg.util.CancelledException; |
47 import org.tmatesoft.hg.util.PathRewrite; | 49 import org.tmatesoft.hg.util.PathRewrite; |
50 import org.tmatesoft.hg.util.ProgressSupport; | |
48 | 51 |
49 /** | 52 /** |
50 * WORK IN PROGRESS, DO NOT USE | 53 * WORK IN PROGRESS, DO NOT USE |
51 * | 54 * |
52 * @author Artem Tikhomirov | 55 * @author Artem Tikhomirov |
99 throw new HgBadArgumentException(String.format("% shall be empty", destination), null); | 102 throw new HgBadArgumentException(String.format("% shall be empty", destination), null); |
100 } | 103 } |
101 } else { | 104 } else { |
102 destination.mkdirs(); | 105 destination.mkdirs(); |
103 } | 106 } |
107 ProgressSupport progress = getProgressSupport(null); | |
108 CancelSupport cancel = getCancelSupport(null, true); | |
109 cancel.checkCancelled(); | |
104 // if cloning remote repo, which can stream and no revision is specified - | 110 // if cloning remote repo, which can stream and no revision is specified - |
105 // can use 'stream_out' wireproto | 111 // can use 'stream_out' wireproto |
106 // | 112 // |
107 // pull all changes from the very beginning | 113 // pull all changes from the very beginning |
108 // XXX consult getContext() if by any chance has a bundle ready, if not, then read and register | 114 // XXX consult getContext() if by any chance has a bundle ready, if not, then read and register |
109 HgBundle completeChanges = srcRepo.getChanges(Collections.singletonList(NULL)); | 115 HgBundle completeChanges = srcRepo.getChanges(Collections.singletonList(NULL)); |
110 WriteDownMate mate = new WriteDownMate(srcRepo.getSessionContext(), destination); | 116 cancel.checkCancelled(); |
117 WriteDownMate mate = new WriteDownMate(srcRepo.getSessionContext(), destination, progress, cancel); | |
111 try { | 118 try { |
112 // instantiate new repo in the destdir | 119 // instantiate new repo in the destdir |
113 mate.initEmptyRepository(); | 120 mate.initEmptyRepository(); |
114 // pull changes | 121 // pull changes |
115 completeChanges.inspectAll(mate); | 122 completeChanges.inspectAll(mate); |
123 mate.checkFailure(); | |
116 mate.complete(); | 124 mate.complete(); |
117 } catch (IOException ex) { | 125 } catch (IOException ex) { |
118 throw new HgInvalidFileException(getClass().getName(), ex); | 126 throw new HgInvalidFileException(getClass().getName(), ex); |
119 } finally { | 127 } finally { |
120 completeChanges.unlink(); | 128 completeChanges.unlink(); |
129 progress.done(); | |
121 } | 130 } |
122 return new HgLookup().detect(destination); | 131 return new HgLookup().detect(destination); |
123 } | 132 } |
124 | 133 |
125 | 134 |
126 // 1. process changelog, memorize nodeids to index | 135 // 1. process changelog, memorize nodeids to index |
127 // 2. process manifest, using map from step 3, collect manifest nodeids | 136 // 2. process manifest, using map from step 3, collect manifest nodeids |
128 // 3. process every file, using map from 3, and consult set from step 4 to ensure repo is correct | 137 // 3. process every file, using map from 3, and consult set from step 4 to ensure repo is correct |
129 private static class WriteDownMate implements HgBundle.Inspector { | 138 private static class WriteDownMate implements HgBundle.Inspector, Lifecycle { |
130 private final File hgDir; | 139 private final File hgDir; |
131 private final PathRewrite storagePathHelper; | 140 private final PathRewrite storagePathHelper; |
141 private final ProgressSupport progressSupport; | |
142 private final CancelSupport cancelSupport; | |
132 private FileOutputStream indexFile; | 143 private FileOutputStream indexFile; |
133 private String filename; // human-readable name of the file being written, for log/exception purposes | 144 private String filename; // human-readable name of the file being written, for log/exception purposes |
134 | 145 |
135 private final TreeMap<Nodeid, Integer> changelogIndexes = new TreeMap<Nodeid, Integer>(); | 146 private final TreeMap<Nodeid, Integer> changelogIndexes = new TreeMap<Nodeid, Integer>(); |
136 private boolean collectChangelogIndexes = false; | 147 private boolean collectChangelogIndexes = false; |
141 private final DigestHelper dh = new DigestHelper(); | 152 private final DigestHelper dh = new DigestHelper(); |
142 private final ArrayList<Nodeid> revisionSequence = new ArrayList<Nodeid>(); // last visited nodes first | 153 private final ArrayList<Nodeid> revisionSequence = new ArrayList<Nodeid>(); // last visited nodes first |
143 | 154 |
144 private final LinkedList<String> fncacheFiles = new LinkedList<String>(); | 155 private final LinkedList<String> fncacheFiles = new LinkedList<String>(); |
145 private RepoInitializer repoInit; | 156 private RepoInitializer repoInit; |
146 | 157 private Lifecycle.Callback lifecycleCallback; |
147 public WriteDownMate(SessionContext ctx, File destDir) { | 158 private CancelledException cancelException; |
159 | |
160 public WriteDownMate(SessionContext ctx, File destDir, ProgressSupport progress, CancelSupport cancel) { | |
148 hgDir = new File(destDir, ".hg"); | 161 hgDir = new File(destDir, ".hg"); |
149 repoInit = new RepoInitializer(); | 162 repoInit = new RepoInitializer(); |
150 repoInit.setRequires(STORE | FNCACHE | DOTENCODE); | 163 repoInit.setRequires(STORE | FNCACHE | DOTENCODE); |
151 storagePathHelper = repoInit.buildDataFilesHelper(ctx); | 164 storagePathHelper = repoInit.buildDataFilesHelper(ctx); |
165 progressSupport = progress; | |
166 cancelSupport = cancel; | |
152 } | 167 } |
153 | 168 |
154 public void initEmptyRepository() throws IOException { | 169 public void initEmptyRepository() throws IOException { |
155 repoInit.initEmptyRepository(hgDir); | 170 repoInit.initEmptyRepository(hgDir); |
156 } | 171 } |
345 String m = String.format("Failed to write revision %s of file %s", ge.node().shortNotation(), filename); | 360 String m = String.format("Failed to write revision %s of file %s", ge.node().shortNotation(), filename); |
346 throw new HgInvalidControlFileException(m, ex, new File(filename)); | 361 throw new HgInvalidControlFileException(m, ex, new File(filename)); |
347 } | 362 } |
348 return true; | 363 return true; |
349 } | 364 } |
350 } | 365 |
351 | 366 public void start(int count, Callback callback, Object token) { |
367 progressSupport.start(count); | |
368 lifecycleCallback = callback; | |
369 } | |
370 | |
371 public void finish(Object token) { | |
372 progressSupport.done(); | |
373 lifecycleCallback = null; | |
374 } | |
375 | |
376 public void checkFailure() throws CancelledException { | |
377 if (cancelException != null) { | |
378 throw cancelException; | |
379 } | |
380 } | |
381 | |
382 private void stopIfCancelled() { | |
383 try { | |
384 cancelSupport.checkCancelled(); | |
385 return; | |
386 } catch (CancelledException ex) { | |
387 cancelException = ex; | |
388 lifecycleCallback.stop(); | |
389 } | |
390 } | |
391 } | |
352 } | 392 } |