From 9412f6c6605452ff49126921f3856576e15ffbc7 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Sun, 26 Jan 2020 22:31:13 +0300 Subject: [PATCH] vcs: Enable "Commit File" action for deleted files (IDEA-225882) GitOrigin-RevId: 4c3ab9675094d7e83e0df7ddf1e00f3d123ad2d2 --- .../com/intellij/openapi/vcs/VcsDataKeys.java | 6 +++-- .../vcs/actions/CommonCheckinFilesAction.kt | 21 +++++++++------ .../vcs/actions/VcsContextWrapper.java | 21 +++------------ .../vcs/changes/ChangeListManagerImpl.java | 23 +++++++++++----- .../vcs/changes/ui/ChangesListView.java | 27 ++++++++++++++----- 5 files changed, 57 insertions(+), 41 deletions(-) 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 04faa08a4455..ef5b414dea1e 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/VcsDataKeys.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/VcsDataKeys.java @@ -1,4 +1,4 @@ -// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.openapi.vcs; @@ -7,13 +7,14 @@ import com.intellij.openapi.actionSystem.DataKey; import com.intellij.openapi.util.Pair; import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vcs.changes.ChangeList; -import com.intellij.vcs.commit.CommitWorkflowHandler; import com.intellij.openapi.vcs.history.VcsFileRevision; import com.intellij.openapi.vcs.history.VcsHistoryProvider; import com.intellij.openapi.vcs.history.VcsHistorySession; import com.intellij.openapi.vcs.history.VcsRevisionNumber; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.Consumer; +import com.intellij.vcs.commit.CommitWorkflowHandler; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NonNls; import java.io.File; @@ -34,6 +35,7 @@ public interface VcsDataKeys { DataKey VCS_VIRTUAL_FILE = DataKey.create("VCS_VIRTUAL_FILE"); DataKey FILE_PATH = DataKey.create("FILE_PATH"); DataKey FILE_PATH_ARRAY = DataKey.create("FILE_PATH_ARRAY"); + @ApiStatus.Internal DataKey> FILE_PATH_STREAM = DataKey.create("FILE_PATH_STREAM"); DataKey FILE_HISTORY_PANEL = DataKey.create("FILE_HISTORY_PANEL"); DataKey CHANGE_LISTS = DataKey.create("vcs.ChangeList"); DataKey CURRENT_CHANGE = DataKey.create("vcs.CurrentChange"); diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/CommonCheckinFilesAction.kt b/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/CommonCheckinFilesAction.kt index 0240f8fb7a2b..632a503580bb 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/CommonCheckinFilesAction.kt +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/CommonCheckinFilesAction.kt @@ -1,4 +1,4 @@ -// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.openapi.vcs.actions import com.intellij.openapi.project.Project @@ -8,6 +8,7 @@ import com.intellij.openapi.vcs.FilePath import com.intellij.openapi.vcs.FileStatus import com.intellij.openapi.vcs.VcsBundle.message import com.intellij.openapi.vcs.changes.ChangeListManager +import com.intellij.openapi.vcs.changes.ChangeListManagerImpl import com.intellij.openapi.vcs.changes.LocalChangeList import com.intellij.openapi.vfs.VirtualFile import com.intellij.util.containers.ContainerUtil.intersects @@ -53,16 +54,20 @@ open class CommonCheckinFilesAction : AbstractCommonCheckinAction() { return result ?: defaultChangeList } - override fun approximatelyHasRoots(dataContext: VcsContext): Boolean { - val manager = ChangeListManager.getInstance(dataContext.project!!) + override fun approximatelyHasRoots(dataContext: VcsContext): Boolean = + dataContext.getRoots().any { isApplicableRoot(it, dataContext) } - return dataContext.getRoots() - .mapNotNull { it.virtualFile } - .any { isApplicableRoot(it, manager.getStatus(it), dataContext) } + protected open fun isApplicableRoot(path: FilePath, dataContext: VcsContext): Boolean { + val manager = ChangeListManagerImpl.getInstanceImpl(dataContext.project!!) + val status = manager.getStatus(path) + + @Suppress("DEPRECATION") + return (path.isDirectory || status != FileStatus.NOT_CHANGED) && status != FileStatus.IGNORED && + path.virtualFile?.let { isApplicableRoot(it, status, dataContext) } != false } - protected open fun isApplicableRoot(file: VirtualFile, status: FileStatus, dataContext: VcsContext): Boolean = - (file.isDirectory || status != FileStatus.NOT_CHANGED) && status != FileStatus.IGNORED + @Deprecated("Use `isApplicableRoot(FilePath, VcsContext)` instead", ReplaceWith("isApplicableRoot()")) + protected open fun isApplicableRoot(file: VirtualFile, status: FileStatus, dataContext: VcsContext): Boolean = true override fun getRoots(dataContext: VcsContext): Array = dataContext.selectedFilePaths diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/VcsContextWrapper.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/VcsContextWrapper.java index d9464a6c0577..3686c808cb59 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/VcsContextWrapper.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/VcsContextWrapper.java @@ -1,18 +1,4 @@ -/* - * 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. - */ +// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.openapi.vcs.actions; import com.intellij.openapi.actionSystem.AnActionEvent; @@ -164,13 +150,14 @@ public class VcsContextWrapper implements VcsContext { @Override public Stream getSelectedFilePathsStream() { FilePath path = VcsDataKeys.FILE_PATH.getData(myContext); + Stream pathStream = VcsDataKeys.FILE_PATH_STREAM.getData(myContext); return concat( StreamEx.ofNullable(path), stream(VcsDataKeys.FILE_PATH_ARRAY.getData(myContext)), - getSelectedFilesStream().map(VcsUtil::getFilePath), + pathStream != null ? pathStream : getSelectedFilesStream().map(VcsUtil::getFilePath), stream(getSelectedIOFiles()).map(VcsUtil::getFilePath) - ); + ).distinct(); } @Nullable diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerImpl.java index a6390849cd84..b004dfec27a4 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerImpl.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerImpl.java @@ -1,4 +1,4 @@ -// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.openapi.vcs.changes; import com.intellij.ide.highlighter.WorkspaceFileType; @@ -1096,19 +1096,28 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Change }); } + @NotNull + public FileStatus getStatus(@NotNull FilePath path) { + return getStatus(path, path.getVirtualFile()); + } + @Override @NotNull public FileStatus getStatus(@NotNull VirtualFile file) { + return getStatus(VcsUtil.getFilePath(file), file); + } + + @NotNull + private FileStatus getStatus(@NotNull FilePath path, @Nullable VirtualFile file) { return ReadAction.compute(() -> { synchronized (myDataLock) { - FilePath filePath = VcsUtil.getFilePath(file); - if (myComposite.getUnversionedFileHolder().containsFile(filePath)) return FileStatus.UNKNOWN; - if (myComposite.getModifiedWithoutEditingFileHolder().containsFile(file)) return FileStatus.HIJACKED; - if (myComposite.getIgnoredFileHolder().containsFile(filePath)) return FileStatus.IGNORED; + if (myComposite.getUnversionedFileHolder().containsFile(path)) return FileStatus.UNKNOWN; + if (file != null && myComposite.getModifiedWithoutEditingFileHolder().containsFile(file)) return FileStatus.HIJACKED; + if (myComposite.getIgnoredFileHolder().containsFile(path)) return FileStatus.IGNORED; - final FileStatus status = ObjectUtils.notNull(myWorker.getStatus(file), FileStatus.NOT_CHANGED); + FileStatus status = ObjectUtils.notNull(myWorker.getStatus(path), FileStatus.NOT_CHANGED); - if (FileStatus.NOT_CHANGED.equals(status)) { + if (file != null && FileStatus.NOT_CHANGED.equals(status)) { boolean switched = myComposite.getSwitchedFileHolder().containsFile(file); if (switched) return FileStatus.SWITCHED; } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesListView.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesListView.java index 28e730a01c8f..29ab5ae61636 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesListView.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesListView.java @@ -1,4 +1,4 @@ -// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.openapi.vcs.changes.ui; import com.intellij.ide.dnd.DnDAware; @@ -38,8 +38,7 @@ import java.util.stream.Stream; import static com.intellij.openapi.vcs.changes.ChangesUtil.*; import static com.intellij.openapi.vcs.changes.ui.ChangesBrowserNode.*; -import static com.intellij.util.containers.UtilKt.getIfSingle; -import static com.intellij.util.containers.UtilKt.stream; +import static com.intellij.util.containers.UtilKt.*; import static com.intellij.vcs.commit.ChangesViewCommitPanelKt.subtreeRootObject; import static java.util.stream.Collectors.toList; @@ -157,6 +156,9 @@ public class ChangesListView extends ChangesTree implements DataProvider, DnDAwa if (VcsDataKeys.VIRTUAL_FILE_STREAM.is(dataId)) { return getSelectedFiles(); } + if (VcsDataKeys.FILE_PATH_STREAM.is(dataId)) { + return getSelectedFilePaths(); + } if (CommonDataKeys.NAVIGATABLE.is(dataId)) { VirtualFile file = getIfSingle(getNavigatableFiles()); return file != null && !file.isDirectory() ? PsiNavigationSupport.getInstance() @@ -338,19 +340,30 @@ public class ChangesListView extends ChangesTree implements DataProvider, DnDAwa return getSelectedLocallyDeletedChanges().map(LocallyDeletedChange::getPath); } + @NotNull + private Stream getSelectedFilePaths() { + return concat( + getSelectedChanges().map(ChangesUtil::getFilePath), + getSelectedVirtualFiles(null).map(VcsUtil::getFilePath), + getSelectedFilePaths(null) + ).distinct(); + } + @NotNull private Stream getSelectedFiles() { - return Stream.concat( + return concat( getAfterRevisionsFiles(getSelectedChanges()), - Stream.concat(getSelectedVirtualFiles(null), getFilesFromPaths(getSelectedFilePaths(null))) + getSelectedVirtualFiles(null), + getFilesFromPaths(getSelectedFilePaths(null)) ).distinct(); } @NotNull private Stream getNavigatableFiles() { - return Stream.concat( + return concat( getFiles(getSelectedChanges()), - Stream.concat(getSelectedVirtualFiles(null), getFilesFromPaths(getSelectedFilePaths(null))) + getSelectedVirtualFiles(null), + getFilesFromPaths(getSelectedFilePaths(null)) ).distinct(); }