From 4fa5151dc1c506d554ac140ac56dcc8f538893f8 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Tue, 6 Mar 2018 14:12:21 +0100 Subject: [PATCH] do not use VFS for application store --- .../src/ApplicationStoreImpl.kt | 26 ++------ .../src/FileBasedStorage.kt | 62 ++++++++++--------- .../src/StateStorageManagerImpl.kt | 24 +++---- .../src/com/intellij/util/io/path.kt | 13 ++-- 4 files changed, 55 insertions(+), 70 deletions(-) diff --git a/platform/configuration-store-impl/src/ApplicationStoreImpl.kt b/platform/configuration-store-impl/src/ApplicationStoreImpl.kt index 1d23ea057588..20be6d8f8ba7 100644 --- a/platform/configuration-store-impl/src/ApplicationStoreImpl.kt +++ b/platform/configuration-store-impl/src/ApplicationStoreImpl.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-2018 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.application.options.PathMacrosImpl @@ -35,7 +21,8 @@ import org.jdom.Element private class ApplicationPathMacroManager : BasePathMacroManager(null) const val APP_CONFIG = "\$APP_CONFIG$" -private val FILE_STORAGE_DIR = "options" +private const val FILE_STORAGE_DIR = "options" +private const val DEFAULT_STORAGE_SPEC = "${PathManager.DEFAULT_OPTIONS_FILE_NAME}${FileStorageCoreUtil.DEFAULT_EXT}" class ApplicationStoreImpl(private val application: Application, pathMacroManager: PathMacroManager? = null) : ComponentStoreImpl() { override val storageManager = ApplicationStorageManager(application, pathMacroManager) @@ -66,10 +53,6 @@ class ApplicationStoreImpl(private val application: Application, pathMacroManage } class ApplicationStorageManager(application: Application, pathMacroManager: PathMacroManager? = null) : StateStorageManagerImpl("application", pathMacroManager?.createTrackingSubstitutor(), application) { - companion object { - private val DEFAULT_STORAGE_SPEC = "${PathManager.DEFAULT_OPTIONS_FILE_NAME}${FileStorageCoreUtil.DEFAULT_EXT}" - - } override fun getOldStorageSpec(component: Any, componentName: String, operation: StateStorageOperation): String? { return if (component is NamedJDOMExternalizable) { @@ -85,6 +68,9 @@ class ApplicationStorageManager(application: Application, pathMacroManager: Path override val isUseXmlProlog: Boolean get() = false + override val isUseVfsForWrite: Boolean + get() = false + override fun providerDataStateChanged(storage: FileBasedStorage, element: Element?, type: DataStateChanged) { // IDEA-144052 When "Settings repository" is enabled changes in 'Path Variables' aren't saved to default path.macros.xml file causing errors in build process if (storage.fileSpec != "path.macros.xml") { diff --git a/platform/configuration-store-impl/src/FileBasedStorage.kt b/platform/configuration-store-impl/src/FileBasedStorage.kt index ffbee63d9d2e..c4c1e2f4f9f2 100644 --- a/platform/configuration-store-impl/src/FileBasedStorage.kt +++ b/platform/configuration-store-impl/src/FileBasedStorage.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-2018 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.notification.Notification @@ -33,10 +19,9 @@ import com.intellij.openapi.vfs.LocalFileSystem import com.intellij.openapi.vfs.VirtualFile import com.intellij.util.ArrayUtil import com.intellij.util.LineSeparator -import com.intellij.util.io.delete -import com.intellij.util.io.exists import com.intellij.util.io.readChars import com.intellij.util.io.systemIndependentPath +import com.intellij.util.io.writeSafe import com.intellij.util.loadElement import com.intellij.util.toBufferExposingByteArray import org.jdom.Element @@ -68,6 +53,7 @@ open class FileBasedStorage(file: Path, } protected open val isUseXmlProlog: Boolean = false + protected open val isUseVfsForWrite: Boolean = true // we never set io file to null fun setFile(virtualFile: VirtualFile?, ioFileIfChanged: Path?) { @@ -87,17 +73,39 @@ open class FileBasedStorage(file: Path, } override fun saveLocally(element: Element?) { - if (storage.lineSeparator == null) { - storage.lineSeparator = if (storage.isUseXmlProlog) LineSeparator.LF else LineSeparator.getSystemLineSeparator() + var lineSeparator = storage.lineSeparator + if (lineSeparator == null) { + lineSeparator = if (storage.isUseXmlProlog) LineSeparator.getSystemLineSeparator() else LineSeparator.LF + storage.lineSeparator = lineSeparator } - val virtualFile = storage.virtualFile + // only app level components do not use xml prolog + if (storage.roamingType == RoamingType.DISABLED && storage.isUseXmlProlog) { + if (element == null) { + + } + } + + val isUseVfs = storage.isUseVfsForWrite + val virtualFile = if (isUseVfs) storage.virtualFile else null if (element == null) { + if (isUseVfs && virtualFile == null) { + LOG.warn("Cannot find virtual file $virtualFile") + } + deleteFile(storage.file, this, virtualFile) storage.cachedVirtualFile = null } + else if (!isUseVfs) { + val file = storage.file + LOG.debug { "Save $file" } + + file.writeSafe { out -> + JDOMUtil.write(element, out, lineSeparator.separatorString) + } + } else { - storage.cachedVirtualFile = writeFile(storage.file, this, virtualFile, element, if (storage.isUseXmlProlog) storage.lineSeparator!! else LineSeparator.LF, storage.isUseXmlProlog) + storage.cachedVirtualFile = writeFile(storage.file, this, virtualFile, element, lineSeparator, storage.isUseXmlProlog) } } } @@ -260,12 +268,10 @@ internal fun detectLineSeparators(chars: CharSequence, defaultSeparator: LineSep private fun deleteFile(file: Path, requestor: Any, virtualFile: VirtualFile?) { if (virtualFile == null) { - LOG.warn("Cannot find virtual file $file") - } - - if (virtualFile == null) { - if (file.exists()) { - file.delete() + try { + Files.delete(file) + } + catch (ignored: NoSuchFileException) { } } else if (virtualFile.exists()) { @@ -282,4 +288,4 @@ internal fun deleteFile(requestor: Any, virtualFile: VirtualFile) { runUndoTransparentWriteAction { virtualFile.delete(requestor) } } -internal class ReadOnlyModificationException(val file: VirtualFile, val session: StateStorage.SaveSession?) : RuntimeException("File is read-only: "+file) \ No newline at end of file +internal class ReadOnlyModificationException(val file: VirtualFile, val session: StateStorage.SaveSession?) : RuntimeException("File is read-only: $file") \ No newline at end of file diff --git a/platform/configuration-store-impl/src/StateStorageManagerImpl.kt b/platform/configuration-store-impl/src/StateStorageManagerImpl.kt index a7d80cd3c5b0..d094b21845e1 100644 --- a/platform/configuration-store-impl/src/StateStorageManagerImpl.kt +++ b/platform/configuration-store-impl/src/StateStorageManagerImpl.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-2018 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.openapi.Disposable @@ -74,11 +60,14 @@ open class StateStorageManagerImpl(private val rootTagName: String, // access under storageLock @Suppress("LeakingThis") - private var isUseVfsListener = if (componentManager == null) ThreeState.NO else ThreeState.UNSURE // unsure because depends on stream provider state + private var isUseVfsListener = if (componentManager == null || !isUseVfsForWrite) ThreeState.NO else ThreeState.UNSURE // unsure because depends on stream provider state protected open val isUseXmlProlog: Boolean get() = true + protected open val isUseVfsForWrite: Boolean + get() = true + companion object { private fun createDefaultVirtualTracker(componentManager: ComponentManager?): StorageVirtualFileTracker? { return when (componentManager) { @@ -298,6 +287,9 @@ open class StateStorageManagerImpl(private val rootTagName: String, override val isUseXmlProlog: Boolean get() = rootElementName != null && storageManager.isUseXmlProlog + override val isUseVfsForWrite: Boolean + get() = storageManager.isUseVfsForWrite + override fun beforeElementSaved(element: Element) { if (rootElementName != null) { storageManager.beforeElementSaved(element) diff --git a/platform/projectModel-api/src/com/intellij/util/io/path.kt b/platform/projectModel-api/src/com/intellij/util/io/path.kt index 113cfd29ffed..c797b7646148 100644 --- a/platform/projectModel-api/src/com/intellij/util/io/path.kt +++ b/platform/projectModel-api/src/com/intellij/util/io/path.kt @@ -1,6 +1,4 @@ -/* - * Copyright 2000-2018 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-2018 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.util.io import com.intellij.openapi.diagnostic.Logger @@ -171,9 +169,9 @@ fun Path.writeSafe(outConsumer: (OutputStream) -> Unit): Path { try { Files.move(tempFile, this, StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING) } - catch (e: IOException) { + catch (e: AtomicMoveNotSupportedException) { LOG.warn(e) - FileUtil.rename(tempFile.toFile(), this.toFile()) + Files.move(tempFile, this, StandardCopyOption.REPLACE_EXISTING) } return this } @@ -276,4 +274,7 @@ fun sanitizeFileName(name: String, replacement: String? = "_", isTruncate: Boole } return result.toString().truncateFileName() -} \ No newline at end of file +} + +val Path.isWritable: Boolean + get() = Files.isWritable(this) \ No newline at end of file