diff --git a/platform/lvcs-impl/api-dump.txt b/platform/lvcs-impl/api-dump.txt index 305c79715591..82dc695121f6 100644 --- a/platform/lvcs-impl/api-dump.txt +++ b/platform/lvcs-impl/api-dump.txt @@ -309,7 +309,6 @@ c:com.intellij.history.integration.IdeaGateway - getPathOrUrl(com.intellij.openapi.vfs.VirtualFile):java.lang.String - ps:getVersionedFilterData():com.intellij.history.integration.IdeaGateway$VersionedFilterData - isVersioned(com.intellij.openapi.vfs.VirtualFile):Z -- isVersioned(com.intellij.openapi.vfs.VirtualFile,Z):Z - s:iterateDBChildren(com.intellij.openapi.vfs.VirtualFile):java.lang.Iterable - s:loadAndIterateChildren(com.intellij.openapi.vfs.VirtualFile):java.lang.Iterable - registerUnsavedDocuments(com.intellij.history.core.LocalHistoryFacade):V diff --git a/platform/lvcs-impl/src/com/intellij/history/integration/IdeaGateway.java b/platform/lvcs-impl/src/com/intellij/history/integration/IdeaGateway.java index af721eb5a009..0026a404204a 100644 --- a/platform/lvcs-impl/src/com/intellij/history/integration/IdeaGateway.java +++ b/platform/lvcs-impl/src/com/intellij/history/integration/IdeaGateway.java @@ -63,10 +63,6 @@ public class IdeaGateway { } public boolean isVersioned(@NotNull VirtualFile f) { - return isVersioned(f, false); - } - - public boolean isVersioned(@NotNull VirtualFile f, boolean shouldBeUnderAnyContentRoot) { if (VersionManagingFileSystem.isDisabled(f)) { return false; } @@ -88,46 +84,35 @@ public class IdeaGateway { // optimisation: FileTypeManager.isFileIgnored(f) will be checked inside ProjectFileIndex.isUnderIgnored() if (numberOfOpenProjects == 0) { - if (shouldBeUnderAnyContentRoot) return false; // there is no project, so the file can't be in content if (FileTypeManager.getInstance().isFileIgnored(f)) return false; return true; } - boolean underAnyProjectContentRoot = false; - for (int i = 0; i < numberOfOpenProjects; ++i) { - ProjectFileIndex projectFileIndex = versionedFilterData.myProjectFileIndices.get(i); - boolean isProjectRelated = isProjectRelated(projectFileIndex, f); + boolean underAnyProject = false; + for (ProjectFileIndex projectFileIndex : versionedFilterData.myProjectFileIndices) { + boolean isProjectRelated = projectFileIndex.isInProjectOrExcluded(f) || projectFileIndex.isUnderIgnored(f); // isIsContent returns true when the file or directory is under the content root of the project, // AND is not excluded or ignored if (isProjectRelated && projectFileIndex.isInContent(f)) { // File is under the content root and isn't ignored/excluded. Track it in LVCS. return true; } - underAnyProjectContentRoot |= isProjectRelated; + underAnyProject |= isProjectRelated; } - if (underAnyProjectContentRoot) { - // File is under the content root of at least one project, but it is ignored/excluded by all these projects. + if (underAnyProject) { + // File does not belong to any content root, but it is excluded by one or more projects. // Do not track it in LVCS. return false; } - else if (shouldBeUnderAnyContentRoot) { - // At this moment the file isn't under any content root, and callsite asks us only for files that - // are under any content root. Do not track it in LVCS. - return false; - } else { - // File isn't under the content root of any project, call-site doesn't care if it is. + // File is outside all the projects. Let's track it anyway because a user may edit some external files or scratch files. // Check only if the file matches any ignored pattern. return !FileTypeManager.getInstance().isFileIgnored(f); } } - static boolean isProjectRelated(ProjectFileIndex projectFileIndex, VirtualFile file) { - return projectFileIndex.isInProjectOrExcluded(file) || projectFileIndex.isUnderIgnored(file); - } - public @NotNull String getPathOrUrl(@NotNull VirtualFile file) { return file.isInLocalFileSystem() ? file.getPath() : file.getUrl(); } diff --git a/platform/lvcs-impl/src/com/intellij/history/integration/LocalHistoryEventDispatcher.kt b/platform/lvcs-impl/src/com/intellij/history/integration/LocalHistoryEventDispatcher.kt index fb1e61fb24f1..a2f7a42eb38d 100644 --- a/platform/lvcs-impl/src/com/intellij/history/integration/LocalHistoryEventDispatcher.kt +++ b/platform/lvcs-impl/src/com/intellij/history/integration/LocalHistoryEventDispatcher.kt @@ -3,21 +3,17 @@ package com.intellij.history.integration import com.intellij.history.ActivityId import com.intellij.history.core.LocalHistoryFacade -import com.intellij.history.integration.IdeaGateway.isProjectRelated import com.intellij.history.integration.LocalHistoryImpl.Companion.getInstanceImpl import com.intellij.openapi.Disposable import com.intellij.openapi.command.CommandEvent import com.intellij.openapi.command.CommandListener import com.intellij.openapi.fileEditor.FileDocumentManager import com.intellij.openapi.roots.ContentIterator -import com.intellij.openapi.roots.ProjectFileIndex import com.intellij.openapi.util.Key import com.intellij.openapi.util.NlsContexts -import com.intellij.openapi.vfs.VfsUtilCore import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.VirtualFileFilter import com.intellij.openapi.vfs.VirtualFileManagerListener -import com.intellij.openapi.vfs.VirtualFileVisitor import com.intellij.openapi.vfs.newvfs.BulkFileListener import com.intellij.openapi.vfs.newvfs.events.VFileContentChangeEvent import com.intellij.openapi.vfs.newvfs.events.VFileCopyEvent @@ -26,7 +22,6 @@ import com.intellij.openapi.vfs.newvfs.events.VFileDeleteEvent import com.intellij.openapi.vfs.newvfs.events.VFileEvent import com.intellij.openapi.vfs.newvfs.events.VFileMoveEvent import com.intellij.openapi.vfs.newvfs.events.VFilePropertyChangeEvent -import com.intellij.util.SystemProperties import com.intellij.util.containers.DisposableWrapperList internal class LocalHistoryEventDispatcher(private val facade: LocalHistoryFacade, private val gateway: IdeaGateway) { @@ -57,48 +52,21 @@ internal class LocalHistoryEventDispatcher(private val facade: LocalHistoryFacad endChangeSet(null, null) } - /** - * @return true if the creation was processed - */ - private fun createRecursivelyUsingWorkspaceTraversal(dir: VirtualFile): Boolean { - val projectIndexes = IdeaGateway.getVersionedFilterData().myProjectFileIndices - var containingProjectIndex: ProjectFileIndex? = null - for (projectIndex in projectIndexes) { - val isProjectRelated = isProjectRelated(projectIndex, dir) - if (!isProjectRelated) continue - if (containingProjectIndex != null) return false // more than 1 project contains this dir + private fun createRecursively(dir: VirtualFile) { + // Let's iterate only over content files. + // It was already the case before this change. Iteration over VFS-cached files outside the project didn't do anything because + // new non-indexable directories are not recursively loaded into VFS on creation. - containingProjectIndex = projectIndex - } - if (containingProjectIndex == null) return false // no project contains this dir - - containingProjectIndex.iterateContentUnderDirectory(dir, ContentIterator { fileOrDir -> - if (isVersioned(fileOrDir)) { - facade.created(gateway.getPathOrUrl(fileOrDir), fileOrDir.isDirectory) - } - true - }, VirtualFileFilter { file -> isVersioned(file) }) - return true - } - - private fun createRecursively(f: VirtualFile) { - if (USE_WORKSPACE_TRAVERSAL) { - if (createRecursivelyUsingWorkspaceTraversal(f)) return - } - VfsUtilCore.visitChildrenRecursively(f, object : VirtualFileVisitor() { - override fun visitFile(f: VirtualFile): Boolean { - if (isVersioned(f)) { - facade.created(gateway.getPathOrUrl(f), f.isDirectory) + for (containingProjectIndex in IdeaGateway.getVersionedFilterData().myProjectFileIndices) { + // It's unlikely that the same content directory belongs to multiple open projects, but for completeness let's iterate + // over all of them as projects may have different excluded directories. + containingProjectIndex.iterateContentUnderDirectory(dir, ContentIterator { fileOrDir -> // NOOP if dir is not under content roots + if (isVersioned(fileOrDir)) { + facade.created(gateway.getPathOrUrl(fileOrDir), fileOrDir.isDirectory) } - return true - } - - override fun getChildrenIterable(f: VirtualFile): Iterable { - // For unversioned files we try to get cached children in hope that they are already generated by content root manager: - // cached children may mean that there are versioned sub-folders or sub-files. - return if (gateway.isVersioned(f, true)) IdeaGateway.loadAndIterateChildren(f) else IdeaGateway.iterateDBChildren(f) - } - }) + true + }, VirtualFileFilter { file -> isVersioned(file) }) + } } private fun beforeContentsChange(e: VFileContentChangeEvent) { @@ -237,6 +205,5 @@ internal class LocalHistoryEventDispatcher(private val facade: LocalHistoryFacad companion object { private val WAS_VERSIONED_KEY = Key.create(LocalHistoryEventDispatcher::class.java.simpleName + ".WAS_VERSIONED_KEY") - private val USE_WORKSPACE_TRAVERSAL = SystemProperties.getBooleanProperty("lvcs.use-workspace-traversal", true) } } \ No newline at end of file diff --git a/platform/lvcs-impl/testSrc/com/intellij/history/integration/IdeaGatewayTest.java b/platform/lvcs-impl/testSrc/com/intellij/history/integration/IdeaGatewayTest.java index 01c7029939d0..1f30c0b63893 100644 --- a/platform/lvcs-impl/testSrc/com/intellij/history/integration/IdeaGatewayTest.java +++ b/platform/lvcs-impl/testSrc/com/intellij/history/integration/IdeaGatewayTest.java @@ -172,8 +172,6 @@ public class IdeaGatewayTest extends IntegrationTestCase { // WHEN - THEN assertTrue(myGateway.isVersioned(sourceDirectory)); assertTrue(myGateway.isVersioned(sourceFile)); - assertTrue(myGateway.isVersioned(sourceDirectory, true)); - assertTrue(myGateway.isVersioned(sourceFile, true)); } public void testScratchFileVersionedOnlyWhenCallerDontCareAboutContentRoot() { @@ -188,7 +186,6 @@ public class IdeaGatewayTest extends IntegrationTestCase { // WHEN - THEN assertTrue(myGateway.isVersioned(scratchFile)); - assertFalse(myGateway.isVersioned(scratchFile, true)); } public void testFileNotVersionedWhenHasSpecificName() throws Exception { @@ -202,7 +199,6 @@ public class IdeaGatewayTest extends IntegrationTestCase { // WHEN - THEN ignoredFiles.forEach(file -> { assertFalse(myGateway.isVersioned(file)); - assertFalse(myGateway.isVersioned(file, true)); }); } @@ -216,8 +212,6 @@ public class IdeaGatewayTest extends IntegrationTestCase { // WHEN - THEN assertFalse(myGateway.isVersioned(excludedDirectory)); assertFalse(myGateway.isVersioned(fileInExcludedDirectory)); - assertFalse(myGateway.isVersioned(excludedDirectory, true)); - assertFalse(myGateway.isVersioned(fileInExcludedDirectory, true)); } public void testFileNotVersionedWhenGloballyIgnored() throws Exception { @@ -233,8 +227,6 @@ public class IdeaGatewayTest extends IntegrationTestCase { // WHEN - THEN assertTrue(myGateway.isVersioned(resourcesDirectory)); assertFalse(myGateway.isVersioned(ignoredFile)); - assertTrue(myGateway.isVersioned(resourcesDirectory, true)); - assertFalse(myGateway.isVersioned(ignoredFile, true)); } finally { WriteAction.runAndWait(() -> fileTypeManager.setIgnoredFilesList(originalIgnoredFileList)); } @@ -260,7 +252,6 @@ public class IdeaGatewayTest extends IntegrationTestCase { // WHEN - THEN assertSize(2, ProjectManagerEx.getInstanceEx().getOpenProjects()); assertFalse(myGateway.isVersioned(fileInIgnoredDirectory)); - assertFalse(myGateway.isVersioned(fileInIgnoredDirectory, true)); } public void testFileVersionedInOptimizedPath() throws Exception { @@ -273,7 +264,6 @@ public class IdeaGatewayTest extends IntegrationTestCase { // WHEN - THEN assertEmpty(ProjectManagerEx.getInstanceEx().getOpenProjects()); assertTrue(myGateway.isVersioned(fileOutsideContentRoot)); - assertFalse(myGateway.isVersioned(fileOutsideContentRoot, true)); } public static @NotNull String getAllPaths(@NotNull RootEntry rootEntry) {