mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
BAZEL-2845 [lvcs]: Fix algorithm deciding if the file is versioned
Before the change, IdeaGateway#isVersioned incorrectly returned true when a file was marked as ignored, and the user opened two or more projects. Merge-request: IJ-MR-190455 Merged-by: Michał Kasprzyk [External] <michal.kasprzyk.external@jetbrains.com> GitOrigin-RevId: effa2e900d6cb5f5849b7f6c2a40afe75bf84953
This commit is contained in:
committed by
intellij-monorepo-bot
parent
fcd775c683
commit
c34e0f1f35
@@ -85,6 +85,7 @@ jvm_library(
|
||||
"//platform/vcs-impl/shared:shared_test_lib",
|
||||
"@lib//:jetbrains-annotations",
|
||||
"//platform/projectModel-impl",
|
||||
"//platform/lang-core",
|
||||
]
|
||||
)
|
||||
### auto-generated section `build intellij.platform.lvcs.impl` end
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
<orderEntry type="module" module-name="intellij.platform.vcs.impl.shared" />
|
||||
<orderEntry type="library" name="jetbrains-annotations" level="project" />
|
||||
<orderEntry type="module" module-name="intellij.platform.projectModel.impl" />
|
||||
<orderEntry type="module" module-name="intellij.platform.lang.core" scope="TEST" />
|
||||
</component>
|
||||
<component name="copyright">
|
||||
<Base>
|
||||
|
||||
@@ -66,7 +66,7 @@ public class IdeaGateway {
|
||||
return isVersioned(f, false);
|
||||
}
|
||||
|
||||
public boolean isVersioned(@NotNull VirtualFile f, boolean shouldBeInContent) {
|
||||
public boolean isVersioned(@NotNull VirtualFile f, boolean shouldBeUnderAnyContentRoot) {
|
||||
if (VersionManagingFileSystem.isDisabled(f)) {
|
||||
return false;
|
||||
}
|
||||
@@ -84,31 +84,48 @@ public class IdeaGateway {
|
||||
|
||||
VersionedFilterData versionedFilterData = getVersionedFilterData();
|
||||
|
||||
int numberOfOpenProjects = versionedFilterData.myOpenedProjects.size();
|
||||
int numberOfOpenProjects = versionedFilterData.myProjectFileIndices.size();
|
||||
|
||||
// optimisation: FileTypeManager.isFileIgnored(f) will be checked inside ProjectFileIndex.isUnderIgnored()
|
||||
if (numberOfOpenProjects == 0) {
|
||||
if (shouldBeInContent) return false; // there is no project, so the file can't be in content
|
||||
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 isExcludedFromAll = true;
|
||||
boolean isInContent = false;
|
||||
|
||||
boolean underAnyProjectContentRoot = false;
|
||||
for (int i = 0; i < numberOfOpenProjects; ++i) {
|
||||
ProjectFileIndex index = versionedFilterData.myProjectFileIndices.get(i);
|
||||
|
||||
if (index.isUnderIgnored(f)) return false;
|
||||
isInContent |= index.isInContent(f);
|
||||
isExcludedFromAll &= index.isExcluded(f);
|
||||
ProjectFileIndex projectFileIndex = versionedFilterData.myProjectFileIndices.get(i);
|
||||
boolean isProjectRelated = isProjectRelated(projectFileIndex, 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;
|
||||
}
|
||||
|
||||
if (isExcludedFromAll) return false;
|
||||
if (shouldBeInContent && !isInContent) return false;
|
||||
if (underAnyProjectContentRoot) {
|
||||
// File is under the content root of at least one project, but it is ignored/excluded by all these 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.
|
||||
// Check only if the file matches any ignored pattern.
|
||||
return !FileTypeManager.getInstance().isFileIgnored(f);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
static boolean isProjectRelated(ProjectFileIndex projectFileIndex, VirtualFile file) {
|
||||
return projectFileIndex.isInProjectOrExcluded(file) || projectFileIndex.isUnderIgnored(file);
|
||||
}
|
||||
|
||||
public @NotNull String getPathOrUrl(@NotNull VirtualFile file) {
|
||||
@@ -172,7 +189,6 @@ public class IdeaGateway {
|
||||
}
|
||||
|
||||
protected static final class VersionedFilterData {
|
||||
final List<Project> myOpenedProjects = new ArrayList<>();
|
||||
final List<ProjectFileIndex> myProjectFileIndices = new ArrayList<>();
|
||||
|
||||
VersionedFilterData() {
|
||||
@@ -182,7 +198,6 @@ public class IdeaGateway {
|
||||
if (each.isDefault()) continue;
|
||||
if (!each.isInitialized()) continue;
|
||||
|
||||
myOpenedProjects.add(each);
|
||||
myProjectFileIndices.add(ProjectRootManager.getInstance(each).getFileIndex());
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -3,6 +3,7 @@ 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
|
||||
@@ -63,7 +64,7 @@ internal class LocalHistoryEventDispatcher(private val facade: LocalHistoryFacad
|
||||
val projectIndexes = IdeaGateway.getVersionedFilterData().myProjectFileIndices
|
||||
var containingProjectIndex: ProjectFileIndex? = null
|
||||
for (projectIndex in projectIndexes) {
|
||||
val isProjectRelated = projectIndex.isInProjectOrExcluded(dir) || projectIndex.isUnderIgnored(dir)
|
||||
val isProjectRelated = isProjectRelated(projectIndex, dir)
|
||||
if (!isProjectRelated) continue
|
||||
if (containingProjectIndex != null) return false // more than 1 project contains this dir
|
||||
|
||||
|
||||
@@ -3,10 +3,24 @@ package com.intellij.history.integration;
|
||||
|
||||
import com.intellij.history.core.tree.Entry;
|
||||
import com.intellij.history.core.tree.RootEntry;
|
||||
import com.intellij.ide.scratch.ScratchFileActions;
|
||||
import com.intellij.ide.scratch.ScratchFileCreationHelper;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.WriteAction;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.fileTypes.FileTypeManager;
|
||||
import com.intellij.openapi.module.ModifiableModuleModel;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ex.ProjectManagerEx;
|
||||
import com.intellij.openapi.roots.ModuleRootModificationUtil;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.ThrowableComputable;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.testFramework.OpenProjectTaskBuilder;
|
||||
import com.intellij.testFramework.PlatformTestUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -18,6 +32,8 @@ import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import static com.intellij.openapi.roots.ModuleRootModificationUtil.updateExcludedFolders;
|
||||
|
||||
public class IdeaGatewayTest extends IntegrationTestCase {
|
||||
public void testFindingFile() {
|
||||
assertEquals(myRoot, myGateway.findVirtualFile(myRoot.getPath()));
|
||||
@@ -148,6 +164,118 @@ public class IdeaGatewayTest extends IntegrationTestCase {
|
||||
getAllPaths(rootEntry));
|
||||
}
|
||||
|
||||
public void testFileVersionedWhenInContentRoot() throws Exception {
|
||||
// GIVEN
|
||||
VirtualFile sourceFile = createFile("src/main/java/Main.java");
|
||||
VirtualFile sourceDirectory = sourceFile.getParent();
|
||||
|
||||
// WHEN - THEN
|
||||
assertTrue(myGateway.isVersioned(sourceDirectory));
|
||||
assertTrue(myGateway.isVersioned(sourceFile));
|
||||
assertTrue(myGateway.isVersioned(sourceDirectory, true));
|
||||
assertTrue(myGateway.isVersioned(sourceFile, true));
|
||||
}
|
||||
|
||||
public void testScratchFileVersionedOnlyWhenCallerDontCareAboutContentRoot() {
|
||||
// GIVEN there is no module, so the project doesn't have content roots
|
||||
ModifiableModuleModel model = ModuleManager.getInstance(getProject()).getModifiableModel();
|
||||
model.disposeModule(getModule());
|
||||
WriteCommandAction.runWriteCommandAction(getProject(), () -> model.commit());
|
||||
|
||||
// AND scratch file
|
||||
ScratchFileCreationHelper.Context context = new ScratchFileCreationHelper.Context();
|
||||
VirtualFile scratchFile = ScratchFileActions.doCreateNewScratch(getProject(), context).getVirtualFile();
|
||||
|
||||
// WHEN - THEN
|
||||
assertTrue(myGateway.isVersioned(scratchFile));
|
||||
assertFalse(myGateway.isVersioned(scratchFile, true));
|
||||
}
|
||||
|
||||
public void testFileNotVersionedWhenHasSpecificName() throws Exception {
|
||||
// GIVEN
|
||||
List<VirtualFile> ignoredFiles = List.of(
|
||||
createFile("workspace.xml"),
|
||||
createFile("project.iws"),
|
||||
createFile("some.class")
|
||||
);
|
||||
|
||||
// WHEN - THEN
|
||||
ignoredFiles.forEach(file -> {
|
||||
assertFalse(myGateway.isVersioned(file));
|
||||
assertFalse(myGateway.isVersioned(file, true));
|
||||
});
|
||||
}
|
||||
|
||||
public void testFileNotVersionedWhenInExcludedDirectory() throws Exception {
|
||||
// GIVEN
|
||||
VirtualFile fileInExcludedDirectory = createFile("out/example-file.txt");
|
||||
VirtualFile excludedDirectory = fileInExcludedDirectory.getParent();
|
||||
|
||||
updateExcludedFolders(myModule, myRoot, List.of(), List.of(excludedDirectory.getUrl()));
|
||||
|
||||
// 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 {
|
||||
// GIVEN
|
||||
VirtualFile ignoredFile = createFile("src/main/resources/ignored.file");
|
||||
VirtualFile resourcesDirectory = ignoredFile.getParent();
|
||||
|
||||
FileTypeManager fileTypeManager = FileTypeManager.getInstance();
|
||||
String originalIgnoredFileList = fileTypeManager.getIgnoredFilesList();
|
||||
try {
|
||||
WriteAction.runAndWait(() -> fileTypeManager.setIgnoredFilesList(originalIgnoredFileList + ";ignored.file"));
|
||||
|
||||
// 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));
|
||||
}
|
||||
}
|
||||
|
||||
public void testFileNotVersionedWhenIgnoredByOneOfTheProjects() throws Exception {
|
||||
// GIVEN a second opened project
|
||||
VirtualFile anotherProjectRootDir = getTempDir().createVirtualDir();
|
||||
Project anotherProject = ProjectManagerEx.getInstanceEx().openProject(anotherProjectRootDir.toNioPath(), new OpenProjectTaskBuilder().build());
|
||||
Disposer.register(getTestRootDisposable(), () -> PlatformTestUtil.forceCloseProjectWithoutSaving(anotherProject));
|
||||
|
||||
// AND a module in the second project
|
||||
Module module = doCreateRealModuleIn(anotherProject.getName(), anotherProject, getModuleType());
|
||||
ModuleRootModificationUtil.addContentRoot(module, anotherProjectRootDir.getPath());
|
||||
|
||||
// AND an ignored directory
|
||||
VirtualFile ignoredDirectory = WriteAction.compute(() -> anotherProjectRootDir.createChildDirectory(this, "out"));
|
||||
updateExcludedFolders(module, anotherProjectRootDir, List.of(), List.of(ignoredDirectory.getUrl()));
|
||||
|
||||
// AND a file inside the ignored directory
|
||||
VirtualFile fileInIgnoredDirectory = WriteAction.compute(() -> ignoredDirectory.createChildData(this, "fileInAnotherProject.txt"));
|
||||
|
||||
// WHEN - THEN
|
||||
assertSize(2, ProjectManagerEx.getInstanceEx().getOpenProjects());
|
||||
assertFalse(myGateway.isVersioned(fileInIgnoredDirectory));
|
||||
assertFalse(myGateway.isVersioned(fileInIgnoredDirectory, true));
|
||||
}
|
||||
|
||||
public void testFileVersionedInOptimizedPath() throws Exception {
|
||||
// GIVEN there are no opened projects
|
||||
PlatformTestUtil.forceCloseProjectWithoutSaving(myProject);
|
||||
|
||||
// AND a file outside the content root (because the project isn't opened)
|
||||
VirtualFile fileOutsideContentRoot = createFile("file/outside/content/root/Main.java");
|
||||
|
||||
// WHEN - THEN
|
||||
assertEmpty(ProjectManagerEx.getInstanceEx().getOpenProjects());
|
||||
assertTrue(myGateway.isVersioned(fileOutsideContentRoot));
|
||||
assertFalse(myGateway.isVersioned(fileOutsideContentRoot, true));
|
||||
}
|
||||
|
||||
public static @NotNull String getAllPaths(@NotNull RootEntry rootEntry) {
|
||||
List<String> result = new ArrayList<>();
|
||||
printAllPaths(rootEntry, result);
|
||||
|
||||
Reference in New Issue
Block a user