Mercurial > jhg
comparison src/org/tmatesoft/hg/core/HgCatCommand.java @ 427:31a89587eb04
FIXMEs: consistent names, throws for commands and their handlers. Use of checked exceptions in hi-level api
| author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
|---|---|
| date | Thu, 29 Mar 2012 17:14:35 +0200 |
| parents | 9c9c442b5f2e |
| children | 78a9e26e670d |
comparison
equal
deleted
inserted
replaced
| 426:063b0663495a | 427:31a89587eb04 |
|---|---|
| 22 | 22 |
| 23 import java.io.IOException; | 23 import java.io.IOException; |
| 24 import java.nio.ByteBuffer; | 24 import java.nio.ByteBuffer; |
| 25 | 25 |
| 26 import org.tmatesoft.hg.repo.HgDataFile; | 26 import org.tmatesoft.hg.repo.HgDataFile; |
| 27 import org.tmatesoft.hg.repo.HgInvalidControlFileException; | |
| 28 import org.tmatesoft.hg.repo.HgInvalidFileException; | |
| 29 import org.tmatesoft.hg.repo.HgInvalidRevisionException; | |
| 30 import org.tmatesoft.hg.repo.HgRepository; | 27 import org.tmatesoft.hg.repo.HgRepository; |
| 28 import org.tmatesoft.hg.repo.HgRuntimeException; | |
| 31 import org.tmatesoft.hg.util.Adaptable; | 29 import org.tmatesoft.hg.util.Adaptable; |
| 32 import org.tmatesoft.hg.util.ByteChannel; | 30 import org.tmatesoft.hg.util.ByteChannel; |
| 33 import org.tmatesoft.hg.util.CancelSupport; | 31 import org.tmatesoft.hg.util.CancelSupport; |
| 34 import org.tmatesoft.hg.util.CancelledException; | 32 import org.tmatesoft.hg.util.CancelledException; |
| 35 import org.tmatesoft.hg.util.Path; | 33 import org.tmatesoft.hg.util.Path; |
| 134 * Runs the command with current set of parameters and pipes data to provided sink. | 132 * Runs the command with current set of parameters and pipes data to provided sink. |
| 135 * | 133 * |
| 136 * @param sink output channel to write data to. | 134 * @param sink output channel to write data to. |
| 137 * | 135 * |
| 138 * @throws HgBadArgumentException if no target file node found | 136 * @throws HgBadArgumentException if no target file node found |
| 139 * @throws HgInvalidControlFileException if access to revlog index/data entry failed | 137 * @throws HgException subclass thereof to indicate specific issue with the command arguments or repository state |
| 140 * @throws HgInvalidFileException if access to file in working directory failed | 138 * @throws CancelledException if execution of the command was cancelled |
| 141 * @throws HgException in case of some other library issue | |
| 142 * @throws CancelledException if execution of the operation was cancelled | |
| 143 * @throws HgInvalidRevisionException if supplied argument doesn't represent revision index in this revlog (<em>runtime exception</em>) | |
| 144 * @throws IllegalArgumentException when command arguments are incomplete or wrong | 139 * @throws IllegalArgumentException when command arguments are incomplete or wrong |
| 145 */ | 140 */ |
| 146 public void execute(ByteChannel sink) throws HgException, CancelledException { | 141 public void execute(ByteChannel sink) throws HgException, CancelledException { |
| 147 // XXX perhaps, IAE together with HgBadArgumentException is not the best idea | 142 // XXX perhaps, IAE together with HgBadArgumentException is not the best idea |
| 148 if (revisionIndex == BAD_REVISION && revision == null && cset == null) { | 143 if (revisionIndex == BAD_REVISION && revision == null && cset == null) { |
| 152 throw new IllegalArgumentException("Name of the file is missing"); | 147 throw new IllegalArgumentException("Name of the file is missing"); |
| 153 } | 148 } |
| 154 if (sink == null) { | 149 if (sink == null) { |
| 155 throw new IllegalArgumentException("Need an output channel"); | 150 throw new IllegalArgumentException("Need an output channel"); |
| 156 } | 151 } |
| 157 HgDataFile dataFile = repo.getFileNode(file); | 152 try { |
| 158 if (!dataFile.exists()) { | 153 HgDataFile dataFile = repo.getFileNode(file); |
| 159 // TODO may benefit from repo.getStoragePath to print revlog location in addition to human-friendly file path | 154 if (!dataFile.exists()) { |
| 160 throw new HgBadArgumentException(String.format("File %s not found in the repository", file), null).setFileName(file); | 155 // TODO may benefit from repo.getStoragePath to print revlog location in addition to human-friendly file path |
| 161 } | 156 throw new HgPathNotFoundException(String.format("File %s not found in the repository", file), file); |
| 162 int revToExtract; | 157 } |
| 163 if (cset != null) { | 158 int revToExtract; |
| 164 int csetRev = repo.getChangelog().getRevisionIndex(cset); | 159 if (cset != null) { |
| 165 Nodeid toExtract = null; | 160 int csetRev = repo.getChangelog().getRevisionIndex(cset); |
| 166 do { | 161 Nodeid toExtract = null; |
| 167 // TODO post-1.0 perhaps, HgChangesetFileSneaker may come handy? | 162 do { |
| 168 toExtract = repo.getManifest().getFileRevision(csetRev, file); | 163 // TODO post-1.0 perhaps, HgChangesetFileSneaker may come handy? |
| 164 toExtract = repo.getManifest().getFileRevision(csetRev, file); | |
| 165 if (toExtract == null) { | |
| 166 if (dataFile.isCopy()) { | |
| 167 file = dataFile.getCopySourceName(); | |
| 168 dataFile = repo.getFileNode(file); | |
| 169 } else { | |
| 170 break; | |
| 171 } | |
| 172 } | |
| 173 } while (toExtract == null); | |
| 169 if (toExtract == null) { | 174 if (toExtract == null) { |
| 170 if (dataFile.isCopy()) { | 175 String m = String.format("File %s nor its origins were known at repository's %s revision", file, cset.shortNotation()); |
| 171 file = dataFile.getCopySourceName(); | 176 throw new HgPathNotFoundException(m, file).setRevision(cset); |
| 172 dataFile = repo.getFileNode(file); | |
| 173 } else { | |
| 174 break; | |
| 175 } | |
| 176 } | 177 } |
| 177 } while (toExtract == null); | 178 revToExtract = dataFile.getRevisionIndex(toExtract); |
| 178 if (toExtract == null) { | 179 } else if (revision != null) { |
| 179 // TODO explicit FileNotFoundException? | 180 revToExtract = dataFile.getRevisionIndex(revision); |
| 180 throw new HgBadArgumentException(String.format("File %s nor its origins were not known at repository %s revision", file, cset.shortNotation()), null); | 181 } else { |
| 181 } | 182 revToExtract = revisionIndex; |
| 182 revToExtract = dataFile.getRevisionIndex(toExtract); | 183 } |
| 183 } else if (revision != null) { | 184 ByteChannel sinkWrap; |
| 184 revToExtract = dataFile.getRevisionIndex(revision); | 185 if (getCancelSupport(null, false) == null) { |
| 185 } else { | 186 // no command-specific cancel helper, no need for extra proxy |
| 186 revToExtract = revisionIndex; | 187 // sink itself still may supply CS |
| 187 } | 188 sinkWrap = sink; |
| 188 ByteChannel sinkWrap; | 189 } else { |
| 189 if (getCancelSupport(null, false) == null) { | 190 // try CS from sink, if any. at least there is CS from command |
| 190 // no command-specific cancel helper, no need for extra proxy | 191 CancelSupport cancelHelper = getCancelSupport(sink, true); |
| 191 // sink itself still may supply CS | 192 cancelHelper.checkCancelled(); |
| 192 sinkWrap = sink; | 193 sinkWrap = new ByteChannelProxy(sink, cancelHelper); |
| 193 } else { | 194 } |
| 194 // try CS from sink, if any. at least there is CS from command | 195 dataFile.contentWithFilters(revToExtract, sinkWrap); |
| 195 CancelSupport cancelHelper = getCancelSupport(sink, true); | 196 } catch (HgRuntimeException ex) { |
| 196 cancelHelper.checkCancelled(); | 197 throw new HgLibraryFailureException(ex); |
| 197 sinkWrap = new ByteChannelProxy(sink, cancelHelper); | 198 } |
| 198 } | |
| 199 dataFile.contentWithFilters(revToExtract, sinkWrap); | |
| 200 } | 199 } |
| 201 | 200 |
| 202 private static class ByteChannelProxy implements ByteChannel, Adaptable { | 201 private static class ByteChannelProxy implements ByteChannel, Adaptable { |
| 203 private final ByteChannel delegate; | 202 private final ByteChannel delegate; |
| 204 private final CancelSupport cancelHelper; | 203 private final CancelSupport cancelHelper; |
