From abe5663270c8290793aa19db6f1a33b1d6c490b8 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Wed, 2 Jan 2019 17:45:44 +0100 Subject: [PATCH] IDEA-202726 AccessDeniedException on project name change if .name file is read-only --- .../src/ProjectStoreImpl.kt | 29 +++++++++++++--- .../testSrc/ProjectStoreTest.kt | 33 ++++++++++--------- 2 files changed, 42 insertions(+), 20 deletions(-) diff --git a/platform/configuration-store-impl/src/ProjectStoreImpl.kt b/platform/configuration-store-impl/src/ProjectStoreImpl.kt index 3fcd2084269f..aff00aba822a 100644 --- a/platform/configuration-store-impl/src/ProjectStoreImpl.kt +++ b/platform/configuration-store-impl/src/ProjectStoreImpl.kt @@ -37,6 +37,7 @@ import com.intellij.util.containers.mapSmart import com.intellij.util.io.* import com.intellij.util.lang.CompoundRuntimeException import com.intellij.util.text.nullize +import java.nio.file.AccessDeniedException import java.nio.file.Path import java.nio.file.Paths @@ -294,12 +295,30 @@ private open class ProjectStoreImpl(project: Project, private val pathMacroManag lastSavedProjectName = currentProjectName val basePath = projectBasePath - if (currentProjectName == PathUtilRt.getFileName(basePath)) { - // name equals to base path name - just remove name - nameFile.delete() + + fun doSave() { + if (currentProjectName == PathUtilRt.getFileName(basePath)) { + // name equals to base path name - just remove name + nameFile.delete() + } + else if (Paths.get(basePath).isDirectory()) { + nameFile.write(currentProjectName.toByteArray()) + } } - else if (Paths.get(basePath).isDirectory()) { - nameFile.write(currentProjectName.toByteArray()) + + try { + doSave() + } + catch (e: AccessDeniedException) { + val status = runReadAction { + ReadonlyStatusHandler.getInstance(project).ensureFilesWritable( + listOf(LocalFileSystem.getInstance().refreshAndFindFileByPath(nameFile.systemIndependentPath))) + } + if (status.hasReadonlyFiles()) { + throw e + } + + doSave() } } diff --git a/platform/configuration-store-impl/testSrc/ProjectStoreTest.kt b/platform/configuration-store-impl/testSrc/ProjectStoreTest.kt index 1418836fb4f3..c7823295f32d 100644 --- a/platform/configuration-store-impl/testSrc/ProjectStoreTest.kt +++ b/platform/configuration-store-impl/testSrc/ProjectStoreTest.kt @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2015 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-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. package com.intellij.configurationStore import com.intellij.ide.highlighter.ProjectFileType @@ -23,6 +9,8 @@ import com.intellij.openapi.project.ProjectManager import com.intellij.openapi.project.ex.ProjectEx import com.intellij.openapi.project.impl.ProjectImpl import com.intellij.openapi.util.io.FileUtilRt +import com.intellij.openapi.vcs.readOnlyHandler.ReadonlyStatusHandlerImpl +import com.intellij.openapi.vfs.ReadonlyStatusHandler import com.intellij.project.stateStore import com.intellij.testFramework.* import com.intellij.testFramework.assertions.Assertions.assertThat @@ -33,7 +21,9 @@ import org.intellij.lang.annotations.Language import org.junit.ClassRule import org.junit.Rule import org.junit.Test +import java.nio.file.Files import java.nio.file.Paths +import java.nio.file.attribute.PosixFilePermission internal class ProjectStoreTest { companion object { @@ -113,6 +103,19 @@ internal class ProjectStoreTest { project.saveStore() assertThat(store.nameFile).hasContent(newName) + project.setProjectName("clear-read-only") + Files.setPosixFilePermissions(store.nameFile, setOf(PosixFilePermission.OWNER_READ)) + + val handler = ReadonlyStatusHandler.getInstance(project) as ReadonlyStatusHandlerImpl + try { + handler.setClearReadOnlyInTests(true) + project.saveStore() + } + finally { + handler.setClearReadOnlyInTests(false) + } + assertThat(store.nameFile).hasContent("clear-read-only") + project.setProjectName(oldName) project.saveStore() assertThat(store.nameFile).doesNotExist()