212N/A/*
212N/A * CDDL HEADER START
212N/A *
212N/A * The contents of this file are subject to the terms of the
212N/A * Common Development and Distribution License (the "License").
212N/A * You may not use this file except in compliance with the License.
212N/A *
212N/A * See LICENSE.txt included in this distribution for the specific
212N/A * language governing permissions and limitations under the License.
212N/A *
212N/A * When distributing Covered Code, include this CDDL HEADER in each
212N/A * file and include the License file at LICENSE.txt.
212N/A * If applicable, add the following below this CDDL HEADER, with the
212N/A * fields enclosed by brackets "[]" replaced with your own identifying
212N/A * information: Portions Copyright [yyyy] [name of copyright owner]
212N/A *
212N/A * CDDL HEADER END
212N/A */
212N/A
212N/A/*
1248N/A * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
212N/A */
212N/Apackage org.opensolaris.opengrok.history;
212N/A
212N/Aimport java.io.BufferedReader;
212N/Aimport java.io.File;
212N/Aimport java.io.FileNotFoundException;
212N/Aimport java.io.IOException;
212N/Aimport java.io.InputStream;
212N/Aimport java.io.InputStreamReader;
212N/Aimport java.util.ArrayList;
212N/Aimport java.util.HashMap;
212N/Aimport java.util.Map;
416N/Aimport java.util.logging.Level;
212N/Aimport java.util.regex.Matcher;
212N/Aimport java.util.regex.Pattern;
416N/Aimport org.opensolaris.opengrok.OpenGrokLogger;
1195N/Aimport org.opensolaris.opengrok.util.IOUtils;
212N/A
212N/A/**
329N/A * This class gives access to repositories built on top of SCCS (including
329N/A * TeamWare).
212N/A */
329N/Apublic class SCCSRepository extends Repository {
815N/A private static final long serialVersionUID = 1L;
1182N/A /** The property name used to obtain the client command for this repository. */
1190N/A public static final String CMD_PROPERTY_KEY =
1182N/A "org.opensolaris.opengrok.history.SCCS";
1182N/A /** The command to use to access the repository if none was given explicitly */
1182N/A public static final String CMD_FALLBACK = "sccs";
435N/A
212N/A private Map<String, String> authors_cache;
664N/A
664N/A public SCCSRepository() {
664N/A type = "SCCS";
749N/A datePattern = "yy/MM/dd";
664N/A }
664N/A
815N/A @Override
212N/A public InputStream getHistoryGet(String parent, String basename, String rev) {
212N/A try {
212N/A File history = SCCSHistoryParser.getSCCSFile(parent, basename);
1182N/A ensureCommand(CMD_PROPERTY_KEY, CMD_FALLBACK);
1182N/A return SCCSget.getRevision(cmd, history, rev);
212N/A } catch (FileNotFoundException ex) {
212N/A return null;
212N/A } catch (IOException ex) {
1190N/A OpenGrokLogger.getLogger().log(Level.WARNING,
1183N/A "An error occured while getting revision", ex);
212N/A return null;
212N/A }
212N/A }
1190N/A
212N/A /** Pattern used to extract revision from sccs get */
1238N/A private static final Pattern AUTHOR_PATTERN =
212N/A Pattern.compile("^([\\d.]+)\\s+(\\S+)");
1190N/A
212N/A private void getAuthors(File file) throws IOException {
212N/A //System.out.println("Alloc Authors cache");
212N/A authors_cache = new HashMap<String, String>();
212N/A
212N/A ArrayList<String> argv = new ArrayList<String>();
1182N/A ensureCommand(CMD_PROPERTY_KEY, CMD_FALLBACK);
1182N/A argv.add(cmd);
212N/A argv.add("prs");
212N/A argv.add("-e");
212N/A argv.add("-d");
212N/A argv.add(":I: :P:");
212N/A argv.add(file.getCanonicalPath());
212N/A
212N/A ProcessBuilder pb = new ProcessBuilder(argv);
212N/A pb.directory(file.getCanonicalFile().getParentFile());
357N/A Process process = null;
357N/A BufferedReader in = null;
212N/A try {
357N/A process = pb.start();
357N/A in = new BufferedReader(new InputStreamReader(process.getInputStream()));
347N/A String line;
347N/A int lineno = 0;
347N/A while ((line = in.readLine()) != null) {
347N/A ++lineno;
347N/A Matcher matcher = AUTHOR_PATTERN.matcher(line);
347N/A if (matcher.find()) {
347N/A String rev = matcher.group(1);
347N/A String auth = matcher.group(2);
347N/A authors_cache.put(rev, auth);
347N/A } else {
1190N/A OpenGrokLogger.getLogger().log(Level.SEVERE,
1190N/A "Error: did not find authors in line {0}: [{1}]",
1183N/A new Object[]{lineno, line});
212N/A }
212N/A }
212N/A } finally {
1195N/A IOUtils.close(in);
357N/A
357N/A if (process != null) {
357N/A try {
357N/A process.exitValue();
357N/A } catch (IllegalThreadStateException e) {
357N/A process.destroy();
357N/A }
212N/A }
212N/A }
212N/A }
212N/A
212N/A /** Pattern used to extract revision from sccs get */
1238N/A private static final Pattern ANNOTATION_PATTERN =
212N/A Pattern.compile("^([\\d.]+)\\s+");
212N/A
212N/A /**
212N/A * Annotate the specified file/revision.
212N/A *
212N/A * @param file file to annotate
212N/A * @param revision revision to annotate
212N/A * @return file annotation
212N/A */
815N/A @Override
459N/A public Annotation annotate(File file, String revision) throws IOException {
1190N/A
212N/A //System.out.println("annotating " + file.getCanonicalPath());
212N/A getAuthors(file);
1190N/A
212N/A ArrayList<String> argv = new ArrayList<String>();
1182N/A ensureCommand(CMD_PROPERTY_KEY, CMD_FALLBACK);
1182N/A argv.add(cmd);
212N/A argv.add("get");
212N/A argv.add("-m");
212N/A argv.add("-p");
212N/A if (revision != null) {
212N/A argv.add("-r" + revision);
212N/A }
212N/A argv.add(file.getCanonicalPath());
212N/A ProcessBuilder pb = new ProcessBuilder(argv);
212N/A pb.directory(file.getCanonicalFile().getParentFile());
357N/A Process process = null;
357N/A BufferedReader in = null;
212N/A try {
357N/A process = pb.start();
357N/A in = new BufferedReader(new InputStreamReader(process.getInputStream()));
347N/A Annotation a = new Annotation(file.getName());
347N/A String line;
347N/A int lineno = 0;
347N/A while ((line = in.readLine()) != null) {
347N/A ++lineno;
347N/A Matcher matcher = ANNOTATION_PATTERN.matcher(line);
347N/A if (matcher.find()) {
347N/A String rev = matcher.group(1);
347N/A String author = authors_cache.get(rev);
357N/A if (author == null) {
347N/A author = "unknown";
357N/A }
1190N/A
347N/A a.addLine(rev, author, true);
347N/A } else {
1190N/A OpenGrokLogger.getLogger().log(Level.SEVERE,
1190N/A "Error: did not find annotations in line {0}: [{1}]",
1183N/A new Object[]{lineno, line});
212N/A }
212N/A }
212N/A return a;
212N/A } finally {
1195N/A IOUtils.close(in);
357N/A if (process != null) {
357N/A try {
357N/A process.exitValue();
357N/A } catch (IllegalThreadStateException e) {
357N/A process.destroy();
357N/A }
212N/A }
212N/A }
212N/A }
212N/A
815N/A @Override
298N/A public boolean fileHasAnnotation(File file) {
212N/A return true;
212N/A }
212N/A
815N/A @Override
459N/A public void update() {
212N/A throw new UnsupportedOperationException("Not supported yet.");
212N/A }
212N/A
815N/A @Override
212N/A public boolean fileHasHistory(File file) {
212N/A String parent = file.getParent();
212N/A String name = file.getName();
212N/A File f = new File(parent + "/SCCS/s." + name);
212N/A if (f.exists()) {
212N/A return true;
212N/A }
212N/A return false;
212N/A }
459N/A
314N/A @Override
329N/A boolean isRepositoryFor(File file) {
1022N/A if (file.isDirectory()) {
1022N/A File f = new File(file, "codemgr_wsdata");
1022N/A if (f.isDirectory()) {
1022N/A return true;
1022N/A }
1022N/A f = new File(file, "Codemgr_wsdata");
1022N/A if (f.isDirectory()) {
1022N/A return true;
1022N/A }
1022N/A return new File(file, "SCCS").isDirectory();
1182N/A }
1182N/A return false;
314N/A }
435N/A
435N/A @Override
592N/A public boolean isWorking() {
1182N/A if (working == null) {
1182N/A ensureCommand(CMD_PROPERTY_KEY, CMD_FALLBACK);
1248N/A working = checkCmd(cmd, "help", "help");
1182N/A if (!working.booleanValue()) {
1248N/A working = checkCmd(cmd, "--version");
1182N/A }
1182N/A }
1182N/A return working.booleanValue();
435N/A }
765N/A
765N/A @Override
765N/A boolean hasHistoryForDirectories() {
765N/A return false;
765N/A }
765N/A
765N/A @Override
765N/A History getHistory(File file) throws HistoryException {
765N/A return new SCCSHistoryParser().parse(file, this);
765N/A }
212N/A}
212N/A