From 4dc61efa3bf7e1ddf28a6131c96bb7784b881abb Mon Sep 17 00:00:00 2001 From: Dmitry Zhuravlev Date: Mon, 7 Oct 2024 14:07:04 +0200 Subject: [PATCH] vcs: introduce failed state for default mapping detection In case e.g., no internet connection, this will notify vcs mapping detection routine about the problem, so no "empty" new mappings will be saved as a valid result. GitOrigin-RevId: 2d78753ac0bf4c3fb688ab9bf56e01f377b170e4 --- .../intellij/openapi/vcs/VcsRootChecker.java | 5 ++- .../openapi/vcs/impl/ModuleVcsDetector.kt | 9 ++++- .../vcs/impl/projectlevelman/NewMappings.java | 39 +++++++++++-------- 3 files changed, 33 insertions(+), 20 deletions(-) diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/VcsRootChecker.java b/platform/vcs-api/src/com/intellij/openapi/vcs/VcsRootChecker.java index 4c0ea7acc797..a151cfbe7f61 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/VcsRootChecker.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/VcsRootChecker.java @@ -1,4 +1,4 @@ -// 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. +// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.openapi.vcs; import com.intellij.openapi.diagnostic.Logger; @@ -100,11 +100,12 @@ public abstract class VcsRootChecker { * @param mappedDirs - roots that have an explicit mappings, and should not be included into detection * @return Detected vcs root mappings for the project * or null if default logic should be used instead (relying on {@link #isRoot} calls). + * @throws VcsException - when detection of project mappings failed (e.g., no internet connection for VCSs that require it). */ @Nullable public Collection detectProjectMappings(@NotNull Project project, @NotNull Collection projectRoots, - @NotNull Set mappedDirs) { + @NotNull Set mappedDirs) throws VcsException { return null; } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ModuleVcsDetector.kt b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ModuleVcsDetector.kt index 21db9bfee7f3..d8be80fdac34 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ModuleVcsDetector.kt +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ModuleVcsDetector.kt @@ -8,6 +8,7 @@ import com.intellij.openapi.extensions.ExtensionNotApplicableException import com.intellij.openapi.project.Project import com.intellij.openapi.vcs.AbstractVcs import com.intellij.openapi.vcs.VcsDirectoryMapping +import com.intellij.openapi.vcs.VcsException import com.intellij.openapi.vcs.VcsRootChecker import com.intellij.openapi.vcs.ex.ProjectLevelVcsManagerEx.MAPPING_DETECTION_LOG import com.intellij.openapi.vfs.VirtualFile @@ -69,7 +70,13 @@ internal class ModuleVcsDetector(private val project: Project) { val directMappings = detectedRoots.map { it.first }.toMutableSet() for (rootChecker in VcsRootChecker.EXTENSION_POINT_NAME.extensionList) { val vcs = vcsManager.findVcsByName(rootChecker.supportedVcs.name) ?: continue - val detectedMappings = rootChecker.detectProjectMappings(project, contentRoots, directMappings) ?: continue + val detectedMappings = try { + rootChecker.detectProjectMappings(project, contentRoots, directMappings) ?: continue + } + catch (e: VcsException) { + MAPPING_DETECTION_LOG.debug("ModuleVcsDetector.autoDetectForContentRoots - exception while detecting mapping", e) + continue + } if (detectedMappings.isEmpty()) continue usedVcses.add(vcs) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/projectlevelman/NewMappings.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/projectlevelman/NewMappings.java index 7a0e92acd904..c98d68c546fb 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/projectlevelman/NewMappings.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/projectlevelman/NewMappings.java @@ -263,18 +263,16 @@ public final class NewMappings implements Disposable { private void updateMappedRoots(boolean fireMappingsChangedEvent) { myRootUpdateQueue.cancelAllUpdates(); - if (!myActivated) return; - LOG.debug("updateMappedRoots"); - - List mappings = myMappings; - Mappings newMappedRoots = collectMappedRoots(mappings, null); - - setNewMappedRoots(mappings, newMappedRoots, fireMappingsChangedEvent); + updateMappedRootsImpl(fireMappingsChangedEvent, false); } private void updateMappedRootsFast(boolean fireMappingsChangedEvent) { + updateMappedRootsImpl(fireMappingsChangedEvent, true); + } + + private void updateMappedRootsImpl(boolean fireMappingsChangedEvent, boolean onlyFastUpdate) { if (!myActivated) return; - LOG.debug("updateMappedRootsFast"); + LOG.debug("updateMappedRoots: fastUpdate = " + onlyFastUpdate); List mappings; List mappedRoots; @@ -285,7 +283,7 @@ public final class NewMappings implements Disposable { if (mappedRoots.isEmpty()) { mappedRoots = getCachedMappedRootsIfNeeded(mappings); } - Mappings newMappedRoots = collectMappedRoots(mappings, mappedRoots); + Mappings newMappedRoots = collectMappedRoots(mappings, mappedRoots, onlyFastUpdate); setNewMappedRoots(mappings, newMappedRoots, fireMappingsChangedEvent); } @@ -396,7 +394,8 @@ public final class NewMappings implements Disposable { } private @NotNull Mappings collectMappedRoots(@NotNull List mappings, - @Nullable List reuseMappedRoots) { + @NotNull List reuseMappedRoots, + boolean onlyFastUpdate) { Map mappedRoots = new HashMap<>(); Disposable pointerDisposable = Disposer.newDisposable(); @@ -426,15 +425,21 @@ public final class NewMappings implements Disposable { } List defaultMappings; - if (reuseMappedRoots != null) { + if (onlyFastUpdate) { defaultMappings = reuseDefaultMappingsFrom(mapping, reuseMappedRoots, pointerDisposable); } else { Set directMappingDirs = ContainerUtil.map2Set(mappedRoots.values(), it -> it.root); - defaultMappings = findDefaultMappingsFor(mapping, directMappingDirs, pointerDisposable); + try { + defaultMappings = findDefaultMappingsFor(mapping, directMappingDirs, pointerDisposable); - VcsDirectoryMappingCache.getInstance(myProject).setMappings(mapping.getVcs(), - ContainerUtil.map(defaultMappings, it -> it.root.getPath())); + VcsDirectoryMappingCache.getInstance(myProject).setMappings(mapping.getVcs(), + ContainerUtil.map(defaultMappings, it -> it.root.getPath())); + } + catch (VcsException e) { + LOG.warn("Cannot find default mappings for " + mapping.getVcs(), e); + defaultMappings = reuseDefaultMappingsFrom(mapping, reuseMappedRoots, pointerDisposable); + } } for (MappedRoot mappedRoot : defaultMappings) { mappedRoots.putIfAbsent(mappedRoot.root, mappedRoot); @@ -484,7 +489,7 @@ public final class NewMappings implements Disposable { @NotNull private List findDefaultMappingsFor(@NotNull VcsDirectoryMapping mapping, @NotNull Set directMappingDirs, - @NotNull Disposable pointerDisposable) { + @NotNull Disposable pointerDisposable) throws VcsException { AbstractVcs vcs = getMappingsVcs(mapping); if (vcs == null) { return Collections.emptyList(); @@ -549,7 +554,7 @@ public final class NewMappings implements Disposable { private @NotNull Collection detectDefaultRootsFor(@NotNull AbstractVcs vcs, @NotNull Collection projectRoots, - @NotNull Set mappedDirs) { + @NotNull Set mappedDirs) throws VcsException { try { if (vcs.needsLegacyDefaultMappings()) return projectRoots; @@ -560,7 +565,7 @@ public final class NewMappings implements Disposable { return VcsDefaultMappingUtils.detectProjectMappings(myProject, rootChecker, projectRoots, mappedDirs); } - catch (ProcessCanceledException e) { + catch (ProcessCanceledException | VcsException e) { throw e; } catch (Throwable e) {