/* * Copyright 2000-2010 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 org.community.intellij.plugins.communitycase.actions; import com.intellij.notification.Notification; import com.intellij.notification.NotificationType; import com.intellij.notification.Notifications; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.actionSystem.Presentation; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.FilePathImpl; import com.intellij.openapi.vcs.ProjectLevelVcsManager; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.history.CurrentRevision; import com.intellij.openapi.vcs.history.VcsFileRevision; import com.intellij.openapi.vcs.history.VcsHistoryUtil; import com.intellij.openapi.vcs.history.VcsRevisionNumber; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.components.JBList; import com.intellij.util.NotNullFunction; import com.intellij.vcsUtil.VcsUtil; import org.community.intellij.plugins.communitycase.Branch; import org.community.intellij.plugins.communitycase.FileRevision; import org.community.intellij.plugins.communitycase.Vcs; import org.community.intellij.plugins.communitycase.history.HistoryUtils; import org.community.intellij.plugins.communitycase.i18n.Bundle; import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.font.TextAttribute; import java.io.IOException; import java.util.*; /** * Compares selected file with itself in one of other branches. * @author Kirill Likhodedov */ public class CompareWithBranchAction extends DumbAwareAction { private static final Logger LOG = Logger.getInstance("#"+CompareWithBranchAction.class.getName()); public CompareWithBranchAction() { super(Bundle.getString("compare.branch.action.name")); } @Override public void actionPerformed(final AnActionEvent event) { // get basic information final Project project = event.getData(PlatformDataKeys.PROJECT); if (project == null || project.isDisposed()) { notifyError(project, "Project is null. " + event.getPlace() + ", " + event.getDataContext(), null); return; } final VirtualFile[] vFiles = event.getData(PlatformDataKeys.VIRTUAL_FILE_ARRAY); if (vFiles == null || vFiles.length != 1 || vFiles[0] == null) { notifyError(project, "Selected incorrect virtual files array: " + Arrays.toString(vFiles), null); return; } final VirtualFile file = vFiles[0]; final VirtualFile vcsRoot = VcsUtil.getVcsRootFor(project, file); if (vcsRoot == null) { notifyError(project, "Could not determine version control system root for file " + file, null); return; } //todo wc popup a "loading branches.." window before we try to list the branches since this can be slow and context menu stays open during this time // get branches information final List<Branch> branches = new ArrayList<Branch>(); Branch curBranch = null; try { curBranch = Branch.list(project, vcsRoot, true, true, branches, null); } catch (VcsException e) { notifyError(project, "Couldn't get information about current branch", e); } //todo wc filter only the branches that exist for this file // prepare and invoke popup final JBList list = new JBList(branches); list.installCellRenderer(new NotNullFunction<Branch, JComponent>() { // display current branch in bold with asterisk @NotNull public JComponent fun(Branch branch) { if (branch.isActive()) { JLabel label = new JLabel(branch.getName() + " *"); final Map<TextAttribute, Float> attributes = new HashMap<TextAttribute, Float>(1); attributes.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD); label.setFont(label.getFont().deriveFont(attributes)); return label; } return new JLabel(branch.getName()); } }); JBPopupFactory.getInstance() .createListPopupBuilder(list) .setTitle(Bundle.getString("compare.branch.title")) .setItemChoosenCallback( new Runnable() { public void run() { Application app = ApplicationManager.getApplication(); if (project.isDisposed() || app == null || !app.isActive() || app.isDisposed() || app.isDisposeInProgress()) { // safe check return; } ApplicationManager.getApplication() .invokeLater(new Runnable() { // don't block awt thread - getting revision content may take long @Override public void run() { try { showDiffWithBranch(project, file, list.getSelectedValue().toString()); } catch (Exception e) { notifyError(project, "Couldn't compare file [" + file + "] with selected branch [" + list.getSelectedValue() + "]", e); } } }); } }) .setAutoselectOnMouseMove(true) .createPopup() .showInBestPositionFor(event.getDataContext()); } private static void notifyError(Project project, String message, Throwable t) { if (t != null) { LOG.info(message, t); } else { LOG.info(message); } Notifications.Bus.notify(new Notification(Vcs.NOTIFICATION_GROUP_ID, "Couldn't compare with branch", message, NotificationType.WARNING), project); } private static void showDiffWithBranch(Project project, VirtualFile file, String compareBranch) throws VcsException, IOException { final FilePath filePath = new FilePathImpl(file); /* final VcsRevisionNumber currentRevisionNumber = HistoryUtils.getCurrentRevision(project, filePath, currentBranch); final VcsRevisionNumber compareRevisionNumber = HistoryUtils.getCurrentRevision(project, filePath, compareBranch); if (compareRevisionNumber == null) { Notifications.Bus.notify(new Notification(Vcs.NOTIFICATION_GROUP_ID, "File doesn't exist in branch", "File " + file.getPresentableUrl() + " doesn't exist in branch [" + compareBranch + "]", NotificationType.INFORMATION), project); return; } */ if(compareBranch.equals("/main/main")) compareBranch="/main"; //main branch is the exception.. never main/main/LATEST, just main/LATEST VcsRevisionNumber compareRevisionNumber=HistoryUtils.getLatestRevisionOnBranch(compareBranch); final VcsFileRevision compareRevision = new FileRevision(project, filePath, compareRevisionNumber); final String currentTitle="Local changes on current branch"; final String compareTitle=compareRevisionNumber.asString() + " on " + compareBranch; VcsHistoryUtil.showDiff(project, filePath, new CurrentRevision(file, HistoryUtils.getCurrentRevision(project, filePath)), compareRevision, currentTitle, compareTitle); /*final VirtualFile vcsRoot = VcsUtil.getVcsRootFor(project, file); final SimpleHandler handler = new SimpleHandler(project, vcsRoot, Command.DIFF); handler.addParameter(); handler.setRemote(true); handler.setSilent(true); final String output = handler.run(); */ } @Override public void update(AnActionEvent e) { super.update(e); Presentation presentation = e.getPresentation(); Project project = e.getData(PlatformDataKeys.PROJECT); if (project == null) { presentation.setEnabled(false); presentation.setVisible(false); return; } VirtualFile[] vFiles = e.getData(PlatformDataKeys.VIRTUAL_FILE_ARRAY); if (vFiles == null || vFiles.length == 0 || vFiles.length > 1) { // only 1 file for now presentation.setEnabled(false); presentation.setVisible(true); return; } Vcs vcs = Vcs.getInstance(project); boolean enabled = ProjectLevelVcsManager.getInstance(project).checkAllFilesAreUnder(vcs, vFiles); enabled &= vFiles[0] != null && !vFiles[0].isDirectory(); // not for dirs for now presentation.setEnabled(enabled); presentation.setVisible(enabled); } }