vcs: Enable "Commit File" action for deleted files (IDEA-225882)

GitOrigin-RevId: 4c3ab9675094d7e83e0df7ddf1e00f3d123ad2d2
This commit is contained in:
Konstantin Kolosovsky
2020-01-30 11:03:20 +00:00
committed by intellij-monorepo-bot
parent e45be2b02e
commit 9412f6c660
5 changed files with 57 additions and 41 deletions
@@ -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<VirtualFile> VCS_VIRTUAL_FILE = DataKey.create("VCS_VIRTUAL_FILE");
DataKey<FilePath> FILE_PATH = DataKey.create("FILE_PATH");
DataKey<FilePath[]> FILE_PATH_ARRAY = DataKey.create("FILE_PATH_ARRAY");
@ApiStatus.Internal DataKey<Stream<FilePath>> FILE_PATH_STREAM = DataKey.create("FILE_PATH_STREAM");
DataKey<Object> FILE_HISTORY_PANEL = DataKey.create("FILE_HISTORY_PANEL");
DataKey<ChangeList[]> CHANGE_LISTS = DataKey.create("vcs.ChangeList");
DataKey<Change> CURRENT_CHANGE = DataKey.create("vcs.CurrentChange");
@@ -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<FilePath> = dataContext.selectedFilePaths
@@ -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<FilePath> getSelectedFilePathsStream() {
FilePath path = VcsDataKeys.FILE_PATH.getData(myContext);
Stream<FilePath> 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
@@ -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;
}
@@ -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<FilePath> getSelectedFilePaths() {
return concat(
getSelectedChanges().map(ChangesUtil::getFilePath),
getSelectedVirtualFiles(null).map(VcsUtil::getFilePath),
getSelectedFilePaths(null)
).distinct();
}
@NotNull
private Stream<VirtualFile> getSelectedFiles() {
return Stream.concat(
return concat(
getAfterRevisionsFiles(getSelectedChanges()),
Stream.concat(getSelectedVirtualFiles(null), getFilesFromPaths(getSelectedFilePaths(null)))
getSelectedVirtualFiles(null),
getFilesFromPaths(getSelectedFilePaths(null))
).distinct();
}
@NotNull
private Stream<VirtualFile> getNavigatableFiles() {
return Stream.concat(
return concat(
getFiles(getSelectedChanges()),
Stream.concat(getSelectedVirtualFiles(null), getFilesFromPaths(getSelectedFilePaths(null)))
getSelectedVirtualFiles(null),
getFilesFromPaths(getSelectedFilePaths(null))
).distinct();
}