blob: 37c3264c9a93797f3b43f0fbf7a7b5c369995875 [file] [log] [blame]
package org.eclipse.team.internal.ccvs.core.client.listeners;
/*
* (c) Copyright IBM Corp. 2000, 2002.
* All Rights Reserved.
*/
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.team.internal.ccvs.core.CVSProviderPlugin;
import org.eclipse.team.internal.ccvs.core.CVSStatus;
import org.eclipse.team.internal.ccvs.core.CVSTag;
import org.eclipse.team.internal.ccvs.core.DateUtil;
import org.eclipse.team.internal.ccvs.core.ICVSFolder;
import org.eclipse.team.internal.ccvs.core.Policy;
import org.eclipse.team.internal.ccvs.core.resources.RemoteFile;
public class LogListener implements ICommandOutputListener {
private List entries;
private RemoteFile file;
// state
private final int BEGIN = 0, SYMBOLIC_NAMES = 1, REVISION = 2, COMMENT = 3, DONE = 4;
private List tagNames = new ArrayList(5);
private List tagRevisions = new ArrayList(5);
private int state = BEGIN; // current state
private String creationDate;
private String author;
private String revision; // revision number
private String fileState; //
private StringBuffer comment; // comment
public LogListener(RemoteFile file, List entries) {
this.file = file;
this.entries = entries;
}
public IStatus messageLine(String line, ICVSFolder commandRoot,
IProgressMonitor monitor) {
// Fields we will find in the log for a file
// keys = String (tag name), values = String (tag revision number) */
switch (state) {
case BEGIN:
if (line.startsWith("symbolic names:")) { //$NON-NLS-1$
state = SYMBOLIC_NAMES;
} else if (line.startsWith("revision ")) { //$NON-NLS-1$
revision = line.substring(9);
state = REVISION;
}
break;
case SYMBOLIC_NAMES:
if (line.startsWith("keyword substitution:")) { //$NON-NLS-1$
state = BEGIN;
} else {
int firstColon = line.indexOf(':');
String tagName = line.substring(1, firstColon);
String tagRevision = line.substring(firstColon + 2);
tagNames.add(tagName);
tagRevisions.add(tagRevision);
}
break;
case REVISION:
// date: 2000/06/19 04:56:21; author: somebody; state: Exp; lines: +114 -45
// get the creation date
int endOfDateIndex = line.indexOf(';', 6);
creationDate = line.substring(6, endOfDateIndex) + " GMT"; //$NON-NLS-1$
// get the author name
int endOfAuthorIndex = line.indexOf(';', endOfDateIndex + 1);
author = line.substring(endOfDateIndex + 11, endOfAuthorIndex);
// get the file state (because this revision might be "dead")
fileState = line.substring(endOfAuthorIndex + 10, line.indexOf(';', endOfAuthorIndex + 1));
comment = new StringBuffer();
state = COMMENT;
break;
case COMMENT:
// skip next line (info about branches) if it exists, if not then it is a comment line.
if (line.startsWith("branches:")) break; //$NON-NLS-1$
if (line.equals("=============================================================================") //$NON-NLS-1$
|| line.equals("----------------------------")) { //$NON-NLS-1$
state = DONE;
break;
}
if (comment.length() != 0) comment.append('\n');
comment.append(line);
break;
}
if (state == DONE) {
// we are only interested in tag names for this revision, remove all others.
List thisRevisionTags = new ArrayList(3);
for (int i = 0; i < tagNames.size(); i++) {
String tagName = (String) tagNames.get(i);
String tagRevision = (String) tagRevisions.get(i);
// If this is a branch tag then only include this tag with the revision
// that is the root of this branch (e.g. 1.1 is root of branch 1.1.2).
boolean isBranch = isBranchTag(tagRevision);
if (isBranch) {
int lastDot = tagRevision.lastIndexOf('.');
if (lastDot == -1) {
CVSProviderPlugin.log(new CVSStatus(IStatus.ERROR,
Policy.bind("LogListener.invalidRevisionFormat", tagName, tagRevision)));
} else {
if (tagRevision.charAt(lastDot - 1) == '0' && tagRevision.charAt(lastDot - 2) == '.') {
lastDot = lastDot - 2;
}
tagRevision = tagRevision.substring(0, lastDot);
}
}
if (tagRevision.equals(revision)) {
int type = isBranch ? CVSTag.BRANCH : CVSTag.VERSION;
thisRevisionTags.add(new CVSTag(tagName, type));
}
}
Date date = DateUtil.convertFromLogTime(creationDate);
LogEntry entry = new LogEntry(file, revision, author, date,
comment.toString(), fileState, (CVSTag[]) thisRevisionTags.toArray(new CVSTag[0]));
entries.add(entry);
state = BEGIN;
// XXX should we reset the tagNames and tagRevisions stuff?
}
return OK;
}
public IStatus errorLine(String line, ICVSFolder commandRoot,
IProgressMonitor monitor) {
return OK;
}
/** branch tags have odd number of segments or have
* an even number with a zero as the second last segment
* e.g: 1.1.1, 1.26.0.2 are branch revision numbers */
protected boolean isBranchTag(String tagName) {
// First check if we have an odd number of segments (i.e. even number of dots)
int numberOfDots = 0;
int lastDot = 0;
for (int i = 0; i < tagName.length(); i++) {
if (tagName.charAt(i) == '.') {
numberOfDots++;
lastDot = i;
}
}
if ((numberOfDots % 2) == 0) return true;
if (numberOfDots == 1) return false;
// If not, check if the second lat segment is a zero
if (tagName.charAt(lastDot - 1) == '0' && tagName.charAt(lastDot - 2) == '.') return true;
return false;
}
}