/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * See LICENSE.txt included in this distribution for the specific * language governing permissions and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at LICENSE.txt. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ package org.opensolaris.opengrok.history; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.logging.Level; import org.apache.commons.jrcs.diff.PatchFailedException; import org.apache.commons.jrcs.rcs.Archive; import org.apache.commons.jrcs.rcs.InvalidFileFormatException; import org.apache.commons.jrcs.rcs.Node; import org.apache.commons.jrcs.rcs.ParseException; import org.apache.commons.jrcs.rcs.Version; import org.opensolaris.opengrok.OpenGrokLogger; /** * Access to an RCS repository. */ public class RCSRepository extends Repository { private static final long serialVersionUID = 1L; public RCSRepository() { working = Boolean.TRUE; type = "RCS"; } @Override boolean fileHasHistory(File file) { return getRCSFile(file) != null; } @Override InputStream getHistoryGet(String parent, String basename, String rev) { try { File file = new File(parent, basename); File rcsFile = getRCSFile(file); return new RCSget(rcsFile.getPath(), rev); } catch (IOException ioe) { OpenGrokLogger.getLogger().log(Level.SEVERE, "Failed to retrieve revision " + rev + " of " + basename, ioe); return null; } } @Override boolean fileHasAnnotation(File file) { return fileHasHistory(file); } @Override Annotation annotate(File file, String revision) throws IOException { File rcsFile = getRCSFile(file); return rcsFile == null ? null : annotate(file, revision, rcsFile); } static Annotation annotate(File file, String revision, File rcsFile) throws IOException { try { Archive archive = new Archive(rcsFile.getPath()); // If revision is null, use current revision Version version = revision == null ? archive.getRevisionVersion() : archive.getRevisionVersion(revision); // Get the revision with annotation archive.getRevision(version, true); Annotation a = new Annotation(file.getName()); // A comment in Archive.getRevisionNodes() says that it is not // considered public API anymore, but it works. for (Node n : archive.getRevisionNodes()) { String rev = n.getVersion().toString(); String author = n.getAuthor(); a.addLine(rev, author, true); } return a; } catch (ParseException pe) { throw wrapInIOException( "Parse exception annotating RCS repository", pe); } catch (InvalidFileFormatException iffe) { throw wrapInIOException( "File format exception annotating RCS repository", iffe); } catch (PatchFailedException pfe) { throw wrapInIOException( "Patch failed exception annotating RCS repository", pfe); } } /** * Wrap a {@code Throwable} in an {@code IOException} and return it. */ static IOException wrapInIOException(String message, Throwable t) { // IOException's constructor takes a Throwable, but only in JDK 6 IOException ioe = new IOException(message + ": " + t.getMessage()); ioe.initCause(t); return ioe; } @Override void update() throws IOException { throw new IOException("Not supported yet."); } @Override boolean isRepositoryFor(File file) { File rcsDir = new File(file, "RCS"); return rcsDir.isDirectory(); } /** * Get a {@code File} object that points to the file that contains * RCS history for the specified file. * * @param file the file whose corresponding RCS file should be found * @return the file which contains the RCS history, or {@code null} if it * cannot be found */ File getRCSFile(File file) { File dir = new File(file.getParentFile(), "RCS"); String baseName = file.getName(); File rcsFile = new File(dir, baseName + ",v"); return rcsFile.exists() ? rcsFile : null; } @Override boolean hasHistoryForDirectories() { return false; } @Override History getHistory(File file) throws HistoryException { return new RCSHistoryParser().parse(file, this); } }