Mercurial > jhg
comparison src/org/tmatesoft/hg/core/HgCloneCommand.java @ 423:9c9c442b5f2e
Major refactoring of exception handling. Low-level API uses RuntimeExceptions, while checked are left for higher level
| author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
|---|---|
| date | Fri, 23 Mar 2012 22:51:18 +0100 |
| parents | 528b6780a8bd |
| children | 12f668401613 |
comparison
equal
deleted
inserted
replaced
| 422:5d1cc7366d04 | 423:9c9c442b5f2e |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (c) 2011 TMate Software Ltd | 2 * Copyright (c) 2011-2012 TMate Software Ltd |
| 3 * | 3 * |
| 4 * This program is free software; you can redistribute it and/or modify | 4 * This program is free software; you can redistribute it and/or modify |
| 5 * it under the terms of the GNU General Public License as published by | 5 * it under the terms of the GNU General Public License as published by |
| 6 * the Free Software Foundation; version 2 of the License. | 6 * the Free Software Foundation; version 2 of the License. |
| 7 * | 7 * |
| 35 import org.tmatesoft.hg.internal.DataAccess; | 35 import org.tmatesoft.hg.internal.DataAccess; |
| 36 import org.tmatesoft.hg.internal.DigestHelper; | 36 import org.tmatesoft.hg.internal.DigestHelper; |
| 37 import org.tmatesoft.hg.internal.Internals; | 37 import org.tmatesoft.hg.internal.Internals; |
| 38 import org.tmatesoft.hg.repo.HgBundle; | 38 import org.tmatesoft.hg.repo.HgBundle; |
| 39 import org.tmatesoft.hg.repo.HgBundle.GroupElement; | 39 import org.tmatesoft.hg.repo.HgBundle.GroupElement; |
| 40 import org.tmatesoft.hg.repo.HgInvalidControlFileException; | |
| 41 import org.tmatesoft.hg.repo.HgInvalidFileException; | |
| 42 import org.tmatesoft.hg.repo.HgInvalidStateException; | |
| 40 import org.tmatesoft.hg.repo.HgLookup; | 43 import org.tmatesoft.hg.repo.HgLookup; |
| 41 import org.tmatesoft.hg.repo.HgRemoteRepository; | 44 import org.tmatesoft.hg.repo.HgRemoteRepository; |
| 42 import org.tmatesoft.hg.repo.HgRepository; | 45 import org.tmatesoft.hg.repo.HgRepository; |
| 46 import org.tmatesoft.hg.repo.HgRuntimeException; | |
| 43 import org.tmatesoft.hg.util.CancelledException; | 47 import org.tmatesoft.hg.util.CancelledException; |
| 44 import org.tmatesoft.hg.util.PathRewrite; | 48 import org.tmatesoft.hg.util.PathRewrite; |
| 45 | 49 |
| 46 /** | 50 /** |
| 47 * WORK IN PROGRESS, DO NOT USE | 51 * WORK IN PROGRESS, DO NOT USE |
| 48 * | 52 * |
| 49 * @author Artem Tikhomirov | 53 * @author Artem Tikhomirov |
| 50 * @author TMate Software Ltd. | 54 * @author TMate Software Ltd. |
| 51 */ | 55 */ |
| 52 public class HgCloneCommand { | 56 public class HgCloneCommand extends HgAbstractCommand<HgCloneCommand> { |
| 53 | 57 |
| 54 private File destination; | 58 private File destination; |
| 55 private HgRemoteRepository srcRepo; | 59 private HgRemoteRepository srcRepo; |
| 56 | 60 |
| 57 public HgCloneCommand() { | 61 public HgCloneCommand() { |
| 70 public HgCloneCommand source(HgRemoteRepository hgRemote) { | 74 public HgCloneCommand source(HgRemoteRepository hgRemote) { |
| 71 srcRepo = hgRemote; | 75 srcRepo = hgRemote; |
| 72 return this; | 76 return this; |
| 73 } | 77 } |
| 74 | 78 |
| 75 public HgRepository execute() throws HgBadArgumentException, HgRemoteConnectionException, HgInvalidFileException, CancelledException { | 79 /** |
| 80 * | |
| 81 * @return | |
| 82 * @throws HgBadArgumentException | |
| 83 * @throws HgRemoteConnectionException | |
| 84 * @throws HgRepositoryNotFoundException | |
| 85 * @throws HgException | |
| 86 * @throws CancelledException | |
| 87 * @throws HgRuntimeException subclass thereof to indicate issues with the library. <em>Runtime exception</em> | |
| 88 */ | |
| 89 public HgRepository execute() throws HgException, CancelledException { | |
| 76 if (destination == null) { | 90 if (destination == null) { |
| 77 throw new IllegalArgumentException("Destination not set", null); | 91 throw new IllegalArgumentException("Destination not set", null); |
| 78 } | 92 } |
| 79 if (srcRepo == null || srcRepo.isInvalid()) { | 93 if (srcRepo == null || srcRepo.isInvalid()) { |
| 80 throw new HgBadArgumentException("Bad source repository", null); | 94 throw new HgBadArgumentException("Bad source repository", null); |
| 157 offset = 0; | 171 offset = 0; |
| 158 revisionSequence.clear(); | 172 revisionSequence.clear(); |
| 159 indexFile = new FileOutputStream(new File(hgDir, filename = "store/00changelog.i")); | 173 indexFile = new FileOutputStream(new File(hgDir, filename = "store/00changelog.i")); |
| 160 collectChangelogIndexes = true; | 174 collectChangelogIndexes = true; |
| 161 } catch (IOException ex) { | 175 } catch (IOException ex) { |
| 162 throw new HgBadStateException(ex); | 176 throw new HgInvalidControlFileException("Failed to write changelog", ex, new File(filename)); |
| 163 } | 177 } |
| 164 } | 178 } |
| 165 | 179 |
| 166 public void changelogEnd() { | 180 public void changelogEnd() { |
| 167 try { | 181 try { |
| 172 collectChangelogIndexes = false; | 186 collectChangelogIndexes = false; |
| 173 indexFile.close(); | 187 indexFile.close(); |
| 174 indexFile = null; | 188 indexFile = null; |
| 175 filename = null; | 189 filename = null; |
| 176 } catch (IOException ex) { | 190 } catch (IOException ex) { |
| 177 throw new HgBadStateException(ex); | 191 throw new HgInvalidControlFileException("Failed to write changelog", ex, new File(filename)); |
| 178 } | 192 } |
| 179 } | 193 } |
| 180 | 194 |
| 181 public void manifestStart() { | 195 public void manifestStart() { |
| 182 try { | 196 try { |
| 183 base = -1; | 197 base = -1; |
| 184 offset = 0; | 198 offset = 0; |
| 185 revisionSequence.clear(); | 199 revisionSequence.clear(); |
| 186 indexFile = new FileOutputStream(new File(hgDir, filename = "store/00manifest.i")); | 200 indexFile = new FileOutputStream(new File(hgDir, filename = "store/00manifest.i")); |
| 187 } catch (IOException ex) { | 201 } catch (IOException ex) { |
| 188 throw new HgBadStateException(ex); | 202 throw new HgInvalidControlFileException("Failed to write manifest", ex, new File(filename)); |
| 189 } | 203 } |
| 190 } | 204 } |
| 191 | 205 |
| 192 public void manifestEnd() { | 206 public void manifestEnd() { |
| 193 try { | 207 try { |
| 197 } | 211 } |
| 198 indexFile.close(); | 212 indexFile.close(); |
| 199 indexFile = null; | 213 indexFile = null; |
| 200 filename = null; | 214 filename = null; |
| 201 } catch (IOException ex) { | 215 } catch (IOException ex) { |
| 202 throw new HgBadStateException(ex); | 216 throw new HgInvalidControlFileException("Failed to write changelog", ex, new File(filename)); |
| 203 } | 217 } |
| 204 } | 218 } |
| 205 | 219 |
| 206 public void fileStart(String name) { | 220 public void fileStart(String name) { |
| 207 try { | 221 try { |
| 212 // need to investigate more how filenames are kept in fncache | 226 // need to investigate more how filenames are kept in fncache |
| 213 File file = new File(hgDir, filename = storagePathHelper.rewrite(name).toString()); | 227 File file = new File(hgDir, filename = storagePathHelper.rewrite(name).toString()); |
| 214 file.getParentFile().mkdirs(); | 228 file.getParentFile().mkdirs(); |
| 215 indexFile = new FileOutputStream(file); | 229 indexFile = new FileOutputStream(file); |
| 216 } catch (IOException ex) { | 230 } catch (IOException ex) { |
| 217 throw new HgBadStateException(ex); | 231 String m = String.format("Failed to write file %s", filename); |
| 232 throw new HgInvalidControlFileException(m, ex, new File(filename)); | |
| 218 } | 233 } |
| 219 } | 234 } |
| 220 | 235 |
| 221 public void fileEnd(String name) { | 236 public void fileEnd(String name) { |
| 222 try { | 237 try { |
| 226 } | 241 } |
| 227 indexFile.close(); | 242 indexFile.close(); |
| 228 indexFile = null; | 243 indexFile = null; |
| 229 filename = null; | 244 filename = null; |
| 230 } catch (IOException ex) { | 245 } catch (IOException ex) { |
| 231 throw new HgBadStateException(ex); | 246 String m = String.format("Failed to write file %s", filename); |
| 247 throw new HgInvalidControlFileException(m, ex, new File(filename)); | |
| 232 } | 248 } |
| 233 } | 249 } |
| 234 | 250 |
| 235 private int knownRevision(Nodeid p) { | 251 private int knownRevision(Nodeid p) { |
| 236 if (p.isNull()) { | 252 if (p.isNull()) { |
| 240 if (revisionSequence.get(i).equals(p)) { | 256 if (revisionSequence.get(i).equals(p)) { |
| 241 return i; | 257 return i; |
| 242 } | 258 } |
| 243 } | 259 } |
| 244 } | 260 } |
| 245 throw new HgBadStateException(String.format("Can't find index of %s for file %s", p.shortNotation(), filename)); | 261 String m = String.format("Can't find index of %s for file %s", p.shortNotation(), filename); |
| 262 throw new HgInvalidControlFileException(m, null, null).setRevision(p); | |
| 246 } | 263 } |
| 247 | 264 |
| 248 public boolean element(GroupElement ge) { | 265 public boolean element(GroupElement ge) { |
| 249 try { | 266 try { |
| 250 assert indexFile != null; | 267 assert indexFile != null; |
| 257 } | 274 } |
| 258 byte[] content = ge.apply(prevRevContent.byteArray()); | 275 byte[] content = ge.apply(prevRevContent.byteArray()); |
| 259 byte[] calculated = dh.sha1(p1, p2, content).asBinary(); | 276 byte[] calculated = dh.sha1(p1, p2, content).asBinary(); |
| 260 final Nodeid node = ge.node(); | 277 final Nodeid node = ge.node(); |
| 261 if (!node.equalsTo(calculated)) { | 278 if (!node.equalsTo(calculated)) { |
| 262 throw new HgBadStateException(String.format("Checksum failed: expected %s, calculated %s. File %s", node, calculated, filename)); | 279 // TODO post-1.0 custom exception ChecksumCalculationFailed? |
| 280 throw new HgInvalidStateException(String.format("Checksum failed: expected %s, calculated %s. File %s", node, calculated, filename)); | |
| 263 } | 281 } |
| 264 final int link; | 282 final int link; |
| 265 if (collectChangelogIndexes) { | 283 if (collectChangelogIndexes) { |
| 266 changelogIndexes.put(node, revisionSequence.size()); | 284 changelogIndexes.put(node, revisionSequence.size()); |
| 267 link = revisionSequence.size(); | 285 link = revisionSequence.size(); |
| 268 } else { | 286 } else { |
| 269 Integer csRev = changelogIndexes.get(ge.cset()); | 287 Integer csRev = changelogIndexes.get(ge.cset()); |
| 270 if (csRev == null) { | 288 if (csRev == null) { |
| 271 throw new HgBadStateException(String.format("Changelog doesn't contain revision %s of %s", ge.cset().shortNotation(), filename)); | 289 throw new HgInvalidStateException(String.format("Changelog doesn't contain revision %s of %s", ge.cset().shortNotation(), filename)); |
| 272 } | 290 } |
| 273 link = csRev.intValue(); | 291 link = csRev.intValue(); |
| 274 } | 292 } |
| 275 final int p1Rev = knownRevision(p1), p2Rev = knownRevision(p2); | 293 final int p1Rev = knownRevision(p1), p2Rev = knownRevision(p2); |
| 276 byte[] patchContent = ge.rawDataByteArray(); | 294 byte[] patchContent = ge.rawDataByteArray(); |
| 323 offset += compressedLen; | 341 offset += compressedLen; |
| 324 revisionSequence.add(node); | 342 revisionSequence.add(node); |
| 325 prevRevContent.done(); | 343 prevRevContent.done(); |
| 326 prevRevContent = new ByteArrayDataAccess(content); | 344 prevRevContent = new ByteArrayDataAccess(content); |
| 327 } catch (IOException ex) { | 345 } catch (IOException ex) { |
| 328 throw new HgBadStateException(ex); | 346 String m = String.format("Failed to write revision %s of file %s", ge.node().shortNotation(), filename); |
| 347 throw new HgInvalidControlFileException(m, ex, new File(filename)); | |
| 329 } | 348 } |
| 330 return true; | 349 return true; |
| 331 } | 350 } |
| 332 } | 351 } |
| 333 | 352 |
