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;