| /* |
| * Copyright 2000-2009 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. |
| */ |
| |
| package com.intellij.history.core; |
| |
| import com.intellij.history.FileRevisionTimestampComparator; |
| import com.intellij.history.core.changes.Change; |
| import com.intellij.history.core.changes.ChangeSet; |
| import com.intellij.history.core.changes.ChangeVisitor; |
| import com.intellij.history.core.changes.ContentChange; |
| import com.intellij.history.core.tree.Entry; |
| import com.intellij.history.integration.IdeaGateway; |
| import com.intellij.openapi.util.Pair; |
| import com.intellij.openapi.vfs.VirtualFile; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| // Optimization: we do not need to build revisions list, though we have to provide |
| // correct number of timestamps for each possible revision for comparator. |
| // Therefore we have to move along the changelist, revert only content changes |
| // and record file and changeset timestamps to call comparator with. |
| public class ByteContentRetriever extends ChangeSetsProcessor { |
| private final LocalHistoryFacade myVcs; |
| private final FileRevisionTimestampComparator myComparator; |
| |
| private long myCurrentFileTimestamp; |
| private Content myCurrentFileContent; |
| |
| public ByteContentRetriever(IdeaGateway gateway, LocalHistoryFacade vcs, VirtualFile file, FileRevisionTimestampComparator c) { |
| super(file.getPath()); |
| myVcs = vcs; |
| myComparator = c; |
| |
| Entry e = gateway.createTransientEntry(file); |
| myCurrentFileContent = e.getContent(); |
| myCurrentFileTimestamp = e.getTimestamp(); |
| } |
| |
| public byte[] getResult() { |
| try { |
| checkCurrentRevision(); // optimization: do not collect changes if current revision will do |
| process(); |
| } |
| catch (ContentFoundException ignore) { |
| return myCurrentFileContent.getBytesIfAvailable(); |
| } |
| |
| return null; |
| } |
| |
| @Override |
| protected Pair<String, List<ChangeSet>> collectChanges() { |
| final List<ChangeSet> result = new ArrayList<ChangeSet>(); |
| |
| myVcs.accept(new ChangeVisitor() { |
| @Override |
| public void begin(ChangeSet c) throws StopVisitingException { |
| if (c.affectsPath(myPath)) result.add(c); |
| } |
| }); |
| |
| return Pair.create(myPath, result); |
| } |
| |
| @Override |
| protected void nothingToVisit() { |
| // visit current version |
| checkCurrentRevision(); |
| } |
| |
| @Override |
| public void visit(ChangeSet changeSet) { |
| checkCurrentRevision(); |
| recordContentAndTimestamp(changeSet); |
| } |
| |
| private void checkCurrentRevision() { |
| if (myComparator.isSuitable(myCurrentFileTimestamp)) { |
| throw new ContentFoundException(); |
| } |
| } |
| |
| private void recordContentAndTimestamp(ChangeSet c) { |
| // todo what if the path is being changed during changes? |
| for (Change each : c.getChanges()) { |
| if (!(each instanceof ContentChange)) continue; |
| ContentChange cc = (ContentChange)each; |
| if (!cc.affectsPath(myPath)) continue; |
| |
| myCurrentFileTimestamp = cc.getOldTimestamp(); |
| myCurrentFileContent = cc.getOldContent(); |
| } |
| } |
| |
| |
| private static class ContentFoundException extends RuntimeException { |
| } |
| } |