tikhomirov@107: /* tikhomirov@107: * Copyright (c) 2011 TMate Software Ltd tikhomirov@107: * tikhomirov@107: * This program is free software; you can redistribute it and/or modify tikhomirov@107: * it under the terms of the GNU General Public License as published by tikhomirov@107: * the Free Software Foundation; version 2 of the License. tikhomirov@107: * tikhomirov@107: * This program is distributed in the hope that it will be useful, tikhomirov@107: * but WITHOUT ANY WARRANTY; without even the implied warranty of tikhomirov@107: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the tikhomirov@107: * GNU General Public License for more details. tikhomirov@107: * tikhomirov@107: * For information on how to redistribute this software under tikhomirov@107: * the terms of a license other than GNU General Public License tikhomirov@130: * contact TMate Software at support@hg4j.com tikhomirov@107: */ tikhomirov@107: package org.tmatesoft.hg.core; tikhomirov@107: tikhomirov@148: import static org.tmatesoft.hg.repo.HgInternals.wrongLocalRevision; tikhomirov@107: import static org.tmatesoft.hg.repo.HgRepository.BAD_REVISION; tikhomirov@107: import static org.tmatesoft.hg.repo.HgRepository.TIP; tikhomirov@107: tikhomirov@107: import java.io.FileNotFoundException; tikhomirov@148: import java.io.IOException; tikhomirov@107: tikhomirov@107: import org.tmatesoft.hg.repo.HgDataFile; tikhomirov@107: import org.tmatesoft.hg.repo.HgRepository; tikhomirov@115: import org.tmatesoft.hg.util.ByteChannel; tikhomirov@148: import org.tmatesoft.hg.util.CancelledException; tikhomirov@133: import org.tmatesoft.hg.util.Path; tikhomirov@107: tikhomirov@107: /** tikhomirov@131: * Command to obtain content of a file, 'hg cat' counterpart. tikhomirov@107: * tikhomirov@107: * @author Artem Tikhomirov tikhomirov@107: * @author TMate Software Ltd. tikhomirov@107: */ tikhomirov@131: public class HgCatCommand { tikhomirov@107: tikhomirov@107: private final HgRepository repo; tikhomirov@107: private Path file; tikhomirov@107: private int localRevision = TIP; tikhomirov@107: private Nodeid revision; tikhomirov@107: tikhomirov@131: public HgCatCommand(HgRepository hgRepo) { tikhomirov@107: repo = hgRepo; tikhomirov@107: } tikhomirov@107: tikhomirov@148: /** tikhomirov@148: * File to read, required parameter tikhomirov@148: * @param fname path to a repository file, can't be null tikhomirov@148: * @return this for convenience tikhomirov@148: * @throws IllegalArgumentException if supplied fname is null or points to directory tikhomirov@148: */ tikhomirov@131: public HgCatCommand file(Path fname) { tikhomirov@148: if (fname == null || fname.isDirectory()) { tikhomirov@148: throw new IllegalArgumentException(String.valueOf(fname)); tikhomirov@148: } tikhomirov@107: file = fname; tikhomirov@107: return this; tikhomirov@107: } tikhomirov@107: tikhomirov@148: /** tikhomirov@148: * Invocation of this method clears revision set with {@link #revision(Nodeid)} or {@link #revision(int)} earlier. tikhomirov@148: * XXX rev can't be WORKING_COPY (if allowed, need to implement in #execute()) tikhomirov@148: * @param rev local revision number, non-negative, or one of predefined constants. Note, use of {@link HgRepository#BAD_REVISION}, tikhomirov@148: * although possible, makes little sense (command would fail if executed). tikhomirov@148: * @return this for convenience tikhomirov@148: */ tikhomirov@131: public HgCatCommand revision(int rev) { tikhomirov@148: if (wrongLocalRevision(rev)) { tikhomirov@148: throw new IllegalArgumentException(String.valueOf(rev)); tikhomirov@148: } tikhomirov@107: localRevision = rev; tikhomirov@107: revision = null; tikhomirov@107: return this; tikhomirov@107: } tikhomirov@107: tikhomirov@148: /** tikhomirov@148: * Select revision to read. Invocation of this method clears revision set with {@link #revision(int)} or {@link #revision(Nodeid)} earlier. tikhomirov@148: * tikhomirov@148: * @param nodeid - unique revision identifier, Note, use of null or {@link Nodeid#NULL} is senseless tikhomirov@148: * @return this for convenience tikhomirov@148: */ tikhomirov@131: public HgCatCommand revision(Nodeid nodeid) { tikhomirov@148: if (nodeid != null && nodeid.isNull()) { tikhomirov@148: nodeid = null; tikhomirov@148: } tikhomirov@107: revision = nodeid; tikhomirov@107: localRevision = BAD_REVISION; tikhomirov@107: return this; tikhomirov@107: } tikhomirov@107: tikhomirov@148: /** tikhomirov@148: * Runs the command with current set of parameters and pipes data to provided sink. tikhomirov@148: * tikhomirov@148: * @param sink output channel to write data to. tikhomirov@148: * @throws HgDataStreamException tikhomirov@148: * @throws IllegalArgumentException when command arguments are incomplete or wrong tikhomirov@148: */ tikhomirov@148: public void execute(ByteChannel sink) throws HgDataStreamException, IOException, CancelledException { tikhomirov@107: if (localRevision == BAD_REVISION && revision == null) { tikhomirov@107: throw new IllegalArgumentException("Either local file revision number or nodeid shall be specified"); tikhomirov@107: } tikhomirov@107: if (file == null) { tikhomirov@107: throw new IllegalArgumentException("Name of the file is missing"); tikhomirov@107: } tikhomirov@115: if (sink == null) { tikhomirov@148: throw new IllegalArgumentException("Need an output channel"); tikhomirov@107: } tikhomirov@107: HgDataFile dataFile = repo.getFileNode(file); tikhomirov@107: if (!dataFile.exists()) { tikhomirov@148: throw new HgDataStreamException(file.toString(), new FileNotFoundException(file.toString())); tikhomirov@107: } tikhomirov@115: int revToExtract; tikhomirov@107: if (revision != null) { tikhomirov@115: revToExtract = dataFile.getLocalRevision(revision); tikhomirov@107: } else { tikhomirov@115: revToExtract = localRevision; tikhomirov@107: } tikhomirov@157: dataFile.contentWithFilters(revToExtract, sink); tikhomirov@107: } tikhomirov@107: }