blob: 8227f8eba212f9f07dba309be7dc0baf6350cd14 [file] [log] [blame]
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Created by IntelliJ IDEA.
* User: yole
* Date: 28.11.2006
* Time: 20:44:46
*/
package com.intellij.cvsSupport2.changeBrowser;
import com.intellij.cvsSupport2.CvsVcs2;
import com.intellij.cvsSupport2.connections.CvsEnvironment;
import com.intellij.cvsSupport2.cvsoperations.dateOrRevision.SimpleRevision;
import com.intellij.cvsSupport2.history.CvsRevisionNumber;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.AbstractVcs;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.ContentRevision;
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeListImpl;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.io.IOUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.netbeans.lib.cvsclient.command.log.Revision;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
public class CvsChangeList implements CommittedChangeList {
private long myDate;
private long myFinishDate;
private long myNumber;
@NotNull private String myDescription;
private final VirtualFile myRootFile;
private String myRootPath;
private final List<RevisionWrapper> myRevisions = new ArrayList<RevisionWrapper>();
private String myUser;
public static final int SUITABLE_DIFF = 2 * 60 * 1000;
private final CvsEnvironment myEnvironment;
private final Project myProject;
private List<Change> myChanges;
@NonNls private static final String EXP_STATE = "Exp";
@NonNls private static final String ADDED_STATE = "added";
@NonNls public static final String DEAD_STATE = "dead";
public CvsChangeList(final Project project,
final CvsEnvironment environment,
@Nullable final VirtualFile rootFile,
final long number,
@NotNull final String description,
final long date,
String user,
String rootPath) {
myRootFile = rootFile;
myDate = date;
myFinishDate = date;
myNumber = number;
myDescription = description;
myUser = user;
myRootPath = rootPath;
myEnvironment = environment;
myProject = project;
}
public CvsChangeList(final Project project,
final CvsEnvironment environment,
@Nullable final VirtualFile rootFile,
final DataInput stream) throws IOException {
myProject = project;
myEnvironment = environment;
myRootFile = rootFile;
readFromStream(stream);
}
public String getCommitterName() {
return myUser;
}
public Date getCommitDate() {
return new Date(myDate);
}
public long getNumber() {
return myNumber;
}
public AbstractVcs getVcs() {
return CvsVcs2.getInstance(myProject);
}
public Collection<Change> getChangesWithMovedTrees() {
return CommittedChangeListImpl.getChangesWithMovedTreesImpl(this);
}
@Override
public boolean isModifiable() {
return true;
}
@Override
public void setDescription(String newMessage) {
myDescription = newMessage;
}
@Nullable
public String getBranch() {
if (myRevisions.size() > 0) {
return myRevisions.get(0).getBranch();
}
return null;
}
public Collection<Change> getChanges() {
if (myChanges == null) {
myChanges = new ArrayList<Change>();
for(RevisionWrapper wrapper: myRevisions) {
final Revision revision = wrapper.getRevision();
final String state = revision.getState();
String path = wrapper.getFile();
final File localFile;
if (myRootFile != null) {
final String directorySuffix = myRootFile.isDirectory() ? "/" : "";
if (StringUtil.startsWithConcatenation(path, myRootPath, directorySuffix)) {
path = path.substring(myRootPath.length() + directorySuffix.length());
localFile = new File(myRootFile.getPresentableUrl(), path);
}
else {
localFile = new File(wrapper.getFile());
}
}
else {
localFile = new File(wrapper.getFile());
}
final boolean added = isAdded(revision);
final ContentRevision beforeRevision = added
? null
: new CvsContentRevision(new File(wrapper.getFile()), localFile,
new SimpleRevision(new CvsRevisionNumber(revision.getNumber()).getPrevNumber().asString()),
myEnvironment, myProject);
final ContentRevision afterRevision = (!added && DEAD_STATE.equals(state))
? null
: new CvsContentRevision(new File(wrapper.getFile()), localFile,
new SimpleRevision(revision.getNumber()),
myEnvironment, myProject);
myChanges.add(new Change(beforeRevision, afterRevision));
}
}
return myChanges;
}
@NotNull
public String getName() {
return myDescription;
}
public String getComment() {
return myDescription;
}
public boolean containsDate(long date) {
if (date >= myDate && date <= myFinishDate) {
return true;
}
if (Math.abs(date - myDate) < SUITABLE_DIFF) {
return true;
}
if (Math.abs(date - myFinishDate) < SUITABLE_DIFF) {
return true;
}
return false;
}
public boolean containsFile(final String file) {
for(RevisionWrapper revision: myRevisions) {
if (revision.getFile().equals(file)) {
return true;
}
}
return false;
}
public void addFileRevision(RevisionWrapper revision) {
myRevisions.add(revision);
final long revisionTime = revision.getTime();
if (revisionTime < myDate) {
myDate = revisionTime;
}
if (revisionTime > myFinishDate) {
myFinishDate = revisionTime;
}
}
public boolean containsFileRevision(RevisionWrapper revision) {
return myRevisions.contains(revision);
}
private static boolean isAdded(final Revision revision) {
final String revisionState = revision.getState();
if (EXP_STATE.equals(revisionState) && revision.getLines() == null) {
return true;
}
if (ADDED_STATE.equals(revisionState)) {
return true;
}
// files added on branch
final int[] subRevisions = new CvsRevisionNumber(revision.getNumber()).getSubRevisions();
if (subRevisions != null && subRevisions.length > 2 && subRevisions [subRevisions.length-1] == 1) {
return true;
}
return false;
}
public static boolean isAncestor(final String parent, final String child) {
return child.equals(parent) || StringUtil.startsWithConcatenation(child, parent, "/");
}
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final CvsChangeList that = (CvsChangeList)o;
if (!myRevisions.equals(that.myRevisions)) return false;
return true;
}
public int hashCode() {
int result = (int)(myNumber ^ (myNumber >>> 32));
result = 31 * result + myDescription.hashCode();
return result;
}
public String toString() {
return myDescription;
}
public void writeToStream(DataOutput stream) throws IOException {
stream.writeLong(myDate);
stream.writeLong(myFinishDate);
stream.writeLong(myNumber);
IOUtil.writeUTFTruncated(stream, myDescription);
stream.writeUTF(myUser);
stream.writeUTF(myRootPath);
stream.writeInt(myRevisions.size());
for(RevisionWrapper revision: myRevisions) {
revision.writeToStream(stream);
}
}
private void readFromStream(final DataInput stream) throws IOException {
myDate = stream.readLong();
myFinishDate = stream.readLong();
myNumber = stream.readLong();
myDescription = stream.readUTF();
myUser = stream.readUTF();
myRootPath = stream.readUTF();
final int revisionCount = stream.readInt();
for(int i=0; i<revisionCount; i++) {
myRevisions.add(RevisionWrapper.readFromStream(stream));
}
}
}