| /* |
| * 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 git4idea.diff; |
| |
| import com.intellij.openapi.project.Project; |
| import com.intellij.openapi.util.Pair; |
| import com.intellij.openapi.vcs.*; |
| import com.intellij.openapi.vcs.changes.ContentRevision; |
| import com.intellij.openapi.vcs.diff.DiffMixin; |
| import com.intellij.openapi.vcs.diff.DiffProvider; |
| import com.intellij.openapi.vcs.diff.ItemLatestState; |
| import com.intellij.openapi.vcs.history.VcsFileRevision; |
| import com.intellij.openapi.vcs.history.VcsRevisionDescription; |
| import com.intellij.openapi.vcs.history.VcsRevisionNumber; |
| import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList; |
| import com.intellij.openapi.vfs.VirtualFile; |
| import com.intellij.vcsUtil.VcsUtil; |
| import git4idea.GitContentRevision; |
| import git4idea.GitFileRevision; |
| import git4idea.GitUtil; |
| import git4idea.GitVcs; |
| import git4idea.history.GitHistoryUtils; |
| import git4idea.i18n.GitBundle; |
| import gnu.trove.THashSet; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.Set; |
| |
| /** |
| * Git diff provider |
| */ |
| public class GitDiffProvider implements DiffProvider, DiffMixin { |
| /** |
| * The context project |
| */ |
| private final Project myProject; |
| /** |
| * The status manager for the project |
| */ |
| private final FileStatusManager myStatusManager; |
| /** |
| * |
| */ |
| private static final Set<FileStatus> ourGoodStatuses; |
| |
| static { |
| ourGoodStatuses = new THashSet<FileStatus>(); |
| ourGoodStatuses.addAll( |
| Arrays.asList(FileStatus.NOT_CHANGED, FileStatus.DELETED, FileStatus.MODIFIED, FileStatus.MERGE, FileStatus.MERGED_WITH_CONFLICTS)); |
| } |
| |
| /** |
| * A constructor |
| * |
| * @param project the context project |
| */ |
| public GitDiffProvider(@NotNull Project project) { |
| myProject = project; |
| myStatusManager = FileStatusManager.getInstance(myProject); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Nullable |
| public VcsRevisionNumber getCurrentRevision(VirtualFile file) { |
| if (file.isDirectory()) { |
| return null; |
| } |
| try { |
| return GitHistoryUtils.getCurrentRevision(myProject, VcsUtil.getFilePath(file.getPath()), "HEAD"); |
| } |
| catch (VcsException e) { |
| return null; |
| } |
| } |
| |
| @Nullable |
| @Override |
| public VcsRevisionDescription getCurrentRevisionDescription(final VirtualFile file) { |
| if (file.isDirectory()) { |
| return null; |
| } |
| try { |
| return GitHistoryUtils.getCurrentRevisionDescription(myProject, VcsUtil.getFilePath(file.getPath()), null); |
| } |
| catch (VcsException e) { |
| return null; |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Nullable |
| public ItemLatestState getLastRevision(VirtualFile file) { |
| if (file.isDirectory()) { |
| return null; |
| } |
| if (!ourGoodStatuses.contains(myStatusManager.getStatus(file))) { |
| return null; |
| } |
| try { |
| return GitHistoryUtils.getLastRevision(myProject, VcsUtil.getFilePath(file.getPath())); |
| } |
| catch (VcsException e) { |
| return null; |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Nullable |
| public ContentRevision createFileContent(VcsRevisionNumber revisionNumber, VirtualFile selectedFile) { |
| if (selectedFile.isDirectory()) { |
| return null; |
| } |
| final String path = selectedFile.getPath(); |
| if (GitUtil.gitRootOrNull(selectedFile) == null) { |
| return null; |
| } |
| |
| // faster, if there were no renames |
| FilePath filePath = VcsUtil.getFilePath(path); |
| try { |
| final CommittedChangesProvider committedChangesProvider = GitVcs.getInstance(myProject).getCommittedChangesProvider(); |
| final Pair<CommittedChangeList, FilePath> pair = committedChangesProvider.getOneList(selectedFile, revisionNumber); |
| if (pair != null) { |
| return GitContentRevision.createRevision(pair.getSecond(), revisionNumber, myProject, selectedFile.getCharset()); |
| } |
| } |
| catch (VcsException e) { |
| GitVcs.getInstance(myProject).showErrors(Collections.singletonList(e), GitBundle.message("diff.find.error", path)); |
| } |
| |
| try { |
| |
| for (VcsFileRevision f : GitHistoryUtils.history(myProject, filePath)) { |
| GitFileRevision gitRevision = (GitFileRevision)f; |
| if (f.getRevisionNumber().equals(revisionNumber)) { |
| return GitContentRevision.createRevision(gitRevision.getPath(), revisionNumber, myProject, selectedFile.getCharset()); |
| } |
| } |
| GitContentRevision candidate = |
| (GitContentRevision) GitContentRevision.createRevision(filePath, revisionNumber, myProject, |
| selectedFile.getCharset()); |
| try { |
| candidate.getContent(); |
| return candidate; |
| } |
| catch (VcsException e) { |
| // file does not exists |
| } |
| } |
| catch (VcsException e) { |
| GitVcs.getInstance(myProject).showErrors(Collections.singletonList(e), GitBundle.message("diff.find.error", path)); |
| } |
| return null; |
| } |
| |
| public ItemLatestState getLastRevision(FilePath filePath) { |
| if (filePath.isDirectory()) { |
| return null; |
| } |
| final VirtualFile vf = filePath.getVirtualFile(); |
| if (vf != null) { |
| if (! ourGoodStatuses.contains(myStatusManager.getStatus(vf))) { |
| return null; |
| } |
| } |
| try { |
| return GitHistoryUtils.getLastRevision(myProject, filePath); |
| } |
| catch (VcsException e) { |
| return null; |
| } |
| } |
| |
| public VcsRevisionNumber getLatestCommittedRevision(VirtualFile vcsRoot) { |
| // todo |
| return null; |
| } |
| } |