/*
* 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
*/
package org.opensolaris.opengrok.history;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.opensolaris.opengrok.logger.LoggerFactory;
import org.opensolaris.opengrok.util.Executor;
/**
* BitKeeperHistoryParser handles parsing the output of `bk log` into a history object.
*
* @author James Service {@literal <jas2701@googlemail.com>}
*/
class BitKeeperHistoryParser implements Executor.StreamHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(BitKeeperHistoryParser.class);
/**
* Parses dates.
*/
private final SimpleDateFormat dateFormat;
/**
* Store entries processed from executor output
*/
private final List<HistoryEntry> entries = new ArrayList<HistoryEntry>();
/**
* Store renamed files processed from executor output
*/
private final Set<String> renamedFiles = new TreeSet<String>();
/**
* Constructor to construct the thing to be constructed.
*
* @param datePattern a simple date format string
*/
public BitKeeperHistoryParser(String datePattern) {
dateFormat = new SimpleDateFormat(datePattern);
}
/**
* Returns the history that has been created.
*
* @return history a history object
*/
History getHistory() {
return new History(entries, new ArrayList<String>(renamedFiles));
}
/**
* Process the output of a `bk log` command.
*
* Each input line should be in the following format:
* either
* D FILE\tREVISION\tDATE\tUSER(\tRENAMED_FROM)?
* or
* C COMMIT_MESSAGE_LINE
*
* BitKeeper always outputs the file name relative to its root directory, which is nice for us since that's what
* History expects.
*
* @param input the executor input stream
* @throws IOException if the stream reader throws an IOException
*/
@Override
public void processStream(InputStream input) throws IOException {
HistoryEntry entry = null;
final BufferedReader in = new BufferedReader(new InputStreamReader(input));
for (String line = in.readLine(); line != null; line = in.readLine()) {
if (line.startsWith("D ")) {
if (entry != null) {
entries.add(entry);
entry = null;
}
final String fields[] = line.substring(2).split("\t");
final HistoryEntry newEntry = new HistoryEntry();
try {
if (fields[0].equals("ChangeSet")) {
continue;
}
newEntry.addFile(fields[0]);
newEntry.setRevision(fields[1]);
newEntry.setDate(dateFormat.parse(fields[2]));
newEntry.setAuthor(fields[3]);
newEntry.setActive(true);
} catch (final Exception e) {
LOGGER.log(Level.SEVERE, "Error: malformed BitKeeper log output {0}", line);
continue;
}
entry = newEntry;
if (fields.length == 5) {
renamedFiles.add(fields[4]);
}
} else if (line.startsWith("C ")) {
if (entry != null) {
final String messageLine = line.substring(2);
entry.appendMessage(messageLine);
}
}
}
if (entry != null) {
entries.add(entry);
}
}
}