diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/VcsDataKeys.java b/platform/vcs-api/src/com/intellij/openapi/vcs/VcsDataKeys.java index f9ca49e09706..d44885c6a3f9 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/VcsDataKeys.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/VcsDataKeys.java @@ -23,6 +23,7 @@ import com.intellij.openapi.vcs.changes.ChangeRequestChain; import com.intellij.openapi.vcs.history.VcsFileRevision; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.pointers.VirtualFilePointer; +import com.intellij.util.Consumer; import org.jetbrains.annotations.NonNls; import java.io.File; @@ -60,6 +61,6 @@ public interface VcsDataKeys { DataKey LABEL_AFTER = DataKey.create("LABEL_AFTER"); DataKey PRESET_COMMIT_MESSAGE = DataKey.create("PRESET_COMMIT_MESSAGE"); DataKey COMMIT_MESSAGE_CONTROL = DataKey.create("COMMIT_MESSAGE_CONTROL"); - DataKey REMOTE_HISTORY_CHANGED_LISTENER = DataKey.create("REMOTE_HISTORY_CHANGED_LISTENER"); + DataKey> REMOTE_HISTORY_CHANGED_LISTENER = DataKey.create("REMOTE_HISTORY_CHANGED_LISTENER"); DataKey REMOTE_HISTORY_LOCATION = DataKey.create("REMOTE_HISTORY_LOCATION"); } diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/history/VcsHistoryCache.java b/platform/vcs-api/src/com/intellij/openapi/vcs/history/VcsHistoryCache.java index b81b2bdd6e56..2d9ed544b56e 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/history/VcsHistoryCache.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/history/VcsHistoryCache.java @@ -18,6 +18,7 @@ package com.intellij.openapi.vcs.history; import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.VcsKey; import com.intellij.openapi.vcs.annotate.VcsAnnotation; +import com.intellij.util.Consumer; import com.intellij.util.containers.SLRUMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -58,6 +59,15 @@ public class VcsHistoryCache { } } + public void editCached(final FilePath filePath, final VcsKey vcsKey, final Consumer> consumer) { + synchronized (myLock) { + final CachedHistory cachedHistory = myHistoryCache.get(new HistoryCacheBaseKey(filePath, vcsKey)); + if (cachedHistory != null) { + consumer.consume(cachedHistory.getRevisions()); + } + } + } + @Nullable public T getFull(final FilePath filePath, final VcsKey vcsKey, @NotNull final VcsCacheableHistorySessionFactory factory) { diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangesPanel.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangesPanel.java index 067597012c8b..325378b79d02 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangesPanel.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangesPanel.java @@ -69,7 +69,7 @@ public class CommittedChangesPanel extends JPanel implements TypeSafeDataProvide private final List myShouldBeCalledOnDispose; private volatile boolean myDisposed; private volatile boolean myInLoad; - private Runnable myIfNotCachedReloader; + private Consumer myIfNotCachedReloader; public CommittedChangesPanel(Project project, final CommittedChangesProvider provider, final ChangeBrowserSettings settings, @Nullable final RepositoryLocation location, @Nullable ActionGroup extraActions) { @@ -109,9 +109,9 @@ public class CommittedChangesPanel extends JPanel implements TypeSafeDataProvide final AnAction anAction = ActionManager.getInstance().getAction("CommittedChanges.Refresh"); anAction.registerCustomShortcutSet(CommonShortcuts.getRerun(), this); myBrowser.addFilter(myFilterComponent); - myIfNotCachedReloader = myLocation == null ? null : new Runnable() { + myIfNotCachedReloader = myLocation == null ? null : new Consumer() { @Override - public void run() { + public void consume(String s) { refreshChanges(false); } }; diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/history/FileHistoryPanelImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/history/FileHistoryPanelImpl.java index 08ce3adf78e2..5ed4855546aa 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/history/FileHistoryPanelImpl.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/history/FileHistoryPanelImpl.java @@ -1208,8 +1208,14 @@ public class FileHistoryPanelImpl extends PanelWithActionsAndCloseButton { } else if (VcsDataKeys.VCS_FILE_REVISIONS.is(dataId)) { return getSelectedRevisions(); - } - else if (VcsDataKeys.CHANGES.is(dataId)) { + } else if (VcsDataKeys.REMOTE_HISTORY_CHANGED_LISTENER.is(dataId)) { + return new Consumer() { + @Override + public void consume(String s) { + myDualView.rebuild(); + } + }; + } else if (VcsDataKeys.CHANGES.is(dataId)) { return getChanges(); } else if (VcsDataKeys.VCS_VIRTUAL_FILE.is(dataId)) { diff --git a/plugins/svn4idea/src/META-INF/plugin.xml b/plugins/svn4idea/src/META-INF/plugin.xml index 11a09ba26912..a17160ce475d 100644 --- a/plugins/svn4idea/src/META-INF/plugin.xml +++ b/plugins/svn4idea/src/META-INF/plugin.xml @@ -39,8 +39,7 @@ - + diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnEditCommitMessageAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnEditCommitMessageAction.java index 1cea0bed0158..ab90c4c6c6b2 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnEditCommitMessageAction.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnEditCommitMessageAction.java @@ -33,6 +33,7 @@ import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.changes.ChangeList; import com.intellij.openapi.vcs.changes.committed.CommittedChangesCache; import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier; +import com.intellij.util.Consumer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnUtil; @@ -59,12 +60,17 @@ public class SvnEditCommitMessageAction extends AnAction { final SvnChangeList svnList = (SvnChangeList) lists[0]; Project project = PlatformDataKeys.PROJECT.getData(dc); project = project == null ? ProjectManager.getInstance().getDefaultProject() : project; + final Consumer listener = VcsDataKeys.REMOTE_HISTORY_CHANGED_LISTENER.getData(dc); + askAndEditRevision(svnList.getNumber(), svnList.getComment(), svnList.getLocation(), project, listener, false); + } + + public static void askAndEditRevision(final long number, final String oldComment, final SvnRepositoryLocation location, Project project, Consumer listener, final boolean fromVersionControl) { final String edited = Messages.showMultilineInputDialog(project, "Attention! Previous message will be lost!\n\nNew revision comment:", - "Edit Revision # " + svnList.getNumber() + " Comment", svnList.getComment(), Messages.getInformationIcon(), null); - if (edited == null || edited.trim().equals(svnList.getComment().trim())) return; - final Runnable listener = VcsDataKeys.REMOTE_HISTORY_CHANGED_LISTENER.getData(dc); - ProgressManager.getInstance().run(new EditMessageTask(project, edited, svnList, listener)); + "Edit Revision # " + number + " Comment", oldComment, + Messages.getInformationIcon(), null); + if (edited == null || edited.trim().equals(oldComment.trim())) return; + ProgressManager.getInstance().run(new EditMessageTask(project, edited, location, number, listener, fromVersionControl)); } @Override @@ -99,25 +105,34 @@ public class SvnEditCommitMessageAction extends AnAction { return cr instanceof MarkerVcsContentRevision && SvnVcs.getKey().equals(((MarkerVcsContentRevision) cr).getVcsKey()); }*/ - private static class EditMessageTask extends Task.Backgroundable { + static class EditMessageTask extends Task.Backgroundable { private final String myNewMessage; - private final SvnChangeList myChangeList; - private final Runnable myListener; + private final SvnRepositoryLocation myLocation; + private final long myNumber; + private final Consumer myListener; + private final boolean myFromVersionControl; private VcsException myException; private final SvnVcs myVcs; - private EditMessageTask(@Nullable Project project, final String newMessage, final SvnChangeList changeList, Runnable listener) { + EditMessageTask(@Nullable Project project, + final String newMessage, + final SvnRepositoryLocation location, + final long number, + Consumer listener, + boolean fromVersionControl) { super(project, "Edit Revision Comment"); myNewMessage = newMessage; - myChangeList = changeList; + myLocation = location; + myNumber = number; myListener = listener; + myFromVersionControl = fromVersionControl; myVcs = SvnVcs.getInstance(myProject); } @Override public void run(@NotNull ProgressIndicator indicator) { final SVNWCClient client = myVcs.createWCClient(); - final String url = myChangeList.getLocation().getURL(); + final String url = myLocation.getURL(); final SVNURL root; try { root = SvnUtil.getRepositoryRoot(myVcs, SVNURL.parseURIEncoded(url)); @@ -125,7 +140,7 @@ public class SvnEditCommitMessageAction extends AnAction { myException = new VcsException("Can not determine repository root for URL: " + url); return; } - client.doSetRevisionProperty(root, SVNRevision.create(myChangeList.getNumber()), "svn:log", + client.doSetRevisionProperty(root, SVNRevision.create(myNumber), "svn:log", SVNPropertyValue.create(myNewMessage), false, null); } catch (SVNException e) { @@ -139,14 +154,18 @@ public class SvnEditCommitMessageAction extends AnAction { AbstractVcsHelper.getInstance(myProject).showError(myException, myTitle); } else { if (myListener != null) { - myListener.run(); + myListener.consume(myNewMessage); } if (! myProject.isDefault()) { - CommittedChangesCache.getInstance(myProject).commitMessageChanged(myVcs, - myChangeList.getLocation(), myChangeList.getNumber(), myNewMessage); + CommittedChangesCache.getInstance(myProject).commitMessageChanged(myVcs, myLocation, myNumber, myNewMessage); + } + if (myFromVersionControl) { + VcsBalloonProblemNotifier.showOverVersionControlView(myProject, "Revision #" + myNumber + " comment " + + "changed to:\n'" + myNewMessage + "'", MessageType.INFO); + } else { + VcsBalloonProblemNotifier.showOverChangesView(myProject, "Revision #" + myNumber + " comment " + + "changed to:\n'" + myNewMessage + "'", MessageType.INFO); } - VcsBalloonProblemNotifier.showOverChangesView(myProject, "Revision #" + myChangeList.getNumber() + " comment " + - "changed to:\n'" + myNewMessage + "'", MessageType.INFO); } } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnEditCommitMessageFromFileHistoryAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnEditCommitMessageFromFileHistoryAction.java new file mode 100644 index 000000000000..b8bb1a6dcade --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnEditCommitMessageFromFileHistoryAction.java @@ -0,0 +1,89 @@ +/* + * Copyright 2000-2012 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.jetbrains.idea.svn.history; + +import com.intellij.icons.AllIcons; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.PlatformDataKeys; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vcs.FilePathImpl; +import com.intellij.openapi.vcs.ProjectLevelVcsManager; +import com.intellij.openapi.vcs.VcsDataKeys; +import com.intellij.openapi.vcs.VcsKey; +import com.intellij.openapi.vcs.history.VcsFileRevision; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.Consumer; +import org.jetbrains.idea.svn.SvnVcs; + +import java.util.List; + +/** + * Created with IntelliJ IDEA. + * User: Irina.Chernushina + * Date: 10/25/12 + * Time: 10:22 AM + */ +public class SvnEditCommitMessageFromFileHistoryAction extends AnAction { + public SvnEditCommitMessageFromFileHistoryAction() { + super("Edit Revision Comment", "Edit revision comment. Previous message is rewritten.", AllIcons.Actions.Edit); + } + + @Override + public void actionPerformed(AnActionEvent e) { + final Project project = e.getData(PlatformDataKeys.PROJECT); + if (project == null) return; + final VcsKey vcsKey = e.getData(VcsDataKeys.VCS); + if (vcsKey == null || ! SvnVcs.getKey().equals(vcsKey)) return; + final VcsFileRevision revision = e.getData(VcsDataKeys.VCS_FILE_REVISION); + final VirtualFile revisionVirtualFile = e.getData(VcsDataKeys.VCS_VIRTUAL_FILE); + if (revision == null || revisionVirtualFile == null) return; + final SvnFileRevision svnFileRevision = (SvnFileRevision) revision; + final Consumer listener = VcsDataKeys.REMOTE_HISTORY_CHANGED_LISTENER.getData(e.getDataContext()); + SvnEditCommitMessageAction.askAndEditRevision(svnFileRevision.getRevision().getNumber(), svnFileRevision.getCommitMessage(), + (SvnRepositoryLocation) svnFileRevision.getChangedRepositoryPath(), project, new Consumer() { + @Override + public void consume(final String newMessage) { + svnFileRevision.setCommitMessage(newMessage); + if (listener != null) { + listener.consume(newMessage); + } + ProjectLevelVcsManager.getInstance(project).getVcsHistoryCache().editCached(new FilePathImpl(revisionVirtualFile), vcsKey, + new Consumer>() { + @Override + public void consume(List revisions) { + for (VcsFileRevision fileRevision : revisions) { + if (! (fileRevision instanceof SvnFileRevision)) continue; + if (((SvnFileRevision) fileRevision).getRevision().getNumber() == svnFileRevision.getRevision().getNumber()) { + ((SvnFileRevision) fileRevision).setCommitMessage(newMessage); + break; + } + } + } + }); + } + }, true); + } + + @Override + public void update(AnActionEvent e) { + final VcsKey vcsKey = e.getData(VcsDataKeys.VCS); + final boolean isSvn = SvnVcs.getKey().equals(vcsKey); + e.getPresentation().setVisible(isSvn); + final VcsFileRevision revision = e.getData(VcsDataKeys.VCS_FILE_REVISION); + e.getPresentation().setEnabled(isSvn && revision != null); + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnFileRevision.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnFileRevision.java index 19065b5be2b1..954c322d7303 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnFileRevision.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnFileRevision.java @@ -47,7 +47,7 @@ public class SvnFileRevision implements VcsFileRevision { private final static Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.history.SvnFileRevision"); private final Date myDate; - private final String myCommitMessage; + private String myCommitMessage; private final String myAuthor; private final VcsRevisionNumber myRevisionNumber; private final SvnVcs myVCS; @@ -178,6 +178,10 @@ public class SvnFileRevision implements VcsFileRevision { return myCopyFromPath; } + public void setCommitMessage(String message) { + myCommitMessage = message; + } + private class ContentLoader implements Runnable { private final SVNRevision myRevision; private final SVNRevision myPegRevision; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java index af4d5f85f11d..47ed8d1785e4 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java @@ -474,7 +474,7 @@ public class SvnHistoryProvider } public AnAction[] getAdditionalActions(final Runnable refresher) { - return new AnAction[]{ ShowAllAffectedGenericAction.getInstance(), new MergeSourceDetailsAction()}; + return new AnAction[]{ ShowAllAffectedGenericAction.getInstance(), new MergeSourceDetailsAction(), new SvnEditCommitMessageFromFileHistoryAction()}; } public boolean isDateOmittable() {