| 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))); //$NON-NLS-1$ |
| } 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; |
| } |
| } |