Skip to content

Commit

Permalink
state storage manager macro value as path instead of string
Browse files Browse the repository at this point in the history
GitOrigin-RevId: b1411b4deb77099d564e3cdeb413a1fc37b16219
  • Loading branch information
develar authored and intellij-monorepo-bot committed Jul 2, 2020
1 parent fffe74e commit c11cdea
Show file tree
Hide file tree
Showing 50 changed files with 495 additions and 467 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// 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.
// 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.
package com.intellij.codeInspection.ex

import com.intellij.codeHighlighting.HighlightDisplayLevel
Expand Down Expand Up @@ -63,7 +63,7 @@ class ProjectInspectionManagerTest {
</state>""".trimIndent()
assertThat(projectInspectionProfileManager.state).isEqualTo(doNotUseProjectProfileState)

val inspectionDir = Paths.get(project.stateStore.projectConfigDir!!, PROFILE_DIR)
val inspectionDir = project.stateStore.projectConfigDir!!.resolve(PROFILE_DIR)
val file = inspectionDir.resolve("profiles_settings.xml")
project.stateStore.save()
assertThat(file).exists()
Expand Down Expand Up @@ -93,7 +93,7 @@ class ProjectInspectionManagerTest {
@Test
fun `do not save default project profile`() {
doTest { project ->
val inspectionDir = Paths.get(project.stateStore.projectConfigDir!!, PROFILE_DIR)
val inspectionDir = project.stateStore.projectConfigDir!!.resolve(PROFILE_DIR)
val profileFile = inspectionDir.resolve("Project_Default.xml")
assertThat(profileFile).doesNotExist()

Expand Down Expand Up @@ -127,7 +127,7 @@ class ProjectInspectionManagerTest {

project.stateStore.save()

val inspectionDir = Paths.get(project.stateStore.projectConfigDir!!, PROFILE_DIR)
val inspectionDir = project.stateStore.projectConfigDir!!.resolve(PROFILE_DIR)
val file = inspectionDir.resolve("profiles_settings.xml")

assertThat(file).doesNotExist()
Expand Down Expand Up @@ -166,7 +166,7 @@ class ProjectInspectionManagerTest {
assertThat(profileManager.currentProfile.isProjectLevel).isTrue()
assertThat(profileManager.currentProfile.name).isEqualTo("Project Default")

val projectConfigDir = Paths.get(project.stateStore.projectConfigDir!!)
val projectConfigDir = project.stateStore.projectConfigDir!!

// test creation of .idea/inspectionProfiles dir, not .idea itself
projectConfigDir.createDirectories()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,11 +194,11 @@ public static VirtualFile copy(Object requestor, @NotNull VirtualFile file, @Not
}

public static @Nullable VirtualFile findFile(@NotNull Path file, boolean refreshIfNeeded) {
return findFile(FileUtil.toSystemIndependentName(file.toAbsolutePath().toString()), refreshIfNeeded);
return findFile(file.toAbsolutePath().toString().replace(File.separatorChar, '/'), refreshIfNeeded);
}

public static @Nullable VirtualFile findFileByIoFile(@NotNull File file, boolean refreshIfNeeded) {
return findFile(FileUtil.toSystemIndependentName(file.getAbsolutePath()), refreshIfNeeded);
return findFile(file.getAbsolutePath().replace(File.separatorChar, '/'), refreshIfNeeded);
}

private static @Nullable VirtualFile findFile(@NotNull String filePath, boolean refreshIfNeeded) {
Expand Down
28 changes: 14 additions & 14 deletions platform/configuration-store-impl/src/ApplicationStoreImpl.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,9 @@ import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.PathManager
import com.intellij.openapi.application.appSystemDir
import com.intellij.openapi.components.*
import com.intellij.openapi.components.impl.stores.FileStorageCoreUtil
import com.intellij.openapi.diagnostic.runAndLogException
import com.intellij.openapi.project.ex.ProjectManagerEx
import com.intellij.openapi.util.NamedJDOMExternalizable
import com.intellij.util.io.systemIndependentPath
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
import org.jetbrains.jps.model.serialization.JpsGlobalLoader
Expand All @@ -22,20 +20,19 @@ internal class ApplicationPathMacroManager : PathMacroManager(null)
const val APP_CONFIG = "\$APP_CONFIG$"

class ApplicationStoreImpl : ComponentStoreWithExtraComponents() {
private val application = ApplicationManager.getApplication()

override val storageManager = ApplicationStorageManager(application, PathMacroManager.getInstance(ApplicationManager.getApplication()))
override val storageManager = ApplicationStorageManager(ApplicationManager.getApplication(), PathMacroManager.getInstance(ApplicationManager.getApplication()))

// number of app components require some state, so, we load default state in test mode
override val loadPolicy: StateLoadPolicy
get() = if (application.isUnitTestMode) StateLoadPolicy.LOAD_ONLY_DEFAULT else StateLoadPolicy.LOAD
get() = if (ApplicationManager.getApplication().isUnitTestMode) StateLoadPolicy.LOAD_ONLY_DEFAULT else StateLoadPolicy.LOAD

override fun setPath(path: Path) {
val systemIndependentPath = path.systemIndependentPath
// app config must be first, because collapseMacros collapse from fist to last, so, at first we must replace APP_CONFIG because it overlaps ROOT_CONFIG value
storageManager.addMacro(APP_CONFIG, "$systemIndependentPath/${PathManager.OPTIONS_DIRECTORY}")
storageManager.addMacro(ROOT_CONFIG, systemIndependentPath)
storageManager.addMacro(StoragePathMacros.CACHE_FILE, appSystemDir.resolve("workspace").resolve("app.xml").systemIndependentPath)
storageManager.setMacros(listOf(
// app config must be first, because collapseMacros collapse from fist to last, so, at first we must replace APP_CONFIG because it overlaps ROOT_CONFIG value
Macro(APP_CONFIG, path.resolve(PathManager.OPTIONS_DIRECTORY)),
Macro(ROOT_CONFIG, path),
Macro(StoragePathMacros.CACHE_FILE, appSystemDir.resolve("workspace").resolve("app.xml"))
))
}

override suspend fun doSave(result: SaveResult, forceSavingAllSettings: Boolean) {
Expand Down Expand Up @@ -71,12 +68,12 @@ internal val appFileBasedStorageConfiguration = object: FileBasedStorageConfigur
}

class ApplicationStorageManager(application: Application?, pathMacroManager: PathMacroManager? = null)
: StateStorageManagerImpl("application", pathMacroManager?.createTrackingSubstitutor(), application) {
: StateStorageManagerImpl("application", pathMacroManager?.createTrackingSubstitutor (), application) {
override fun getFileBasedStorageConfiguration(fileSpec: String) = appFileBasedStorageConfiguration

override fun getOldStorageSpec(component: Any, componentName: String, operation: StateStorageOperation): String? {
return when (component) {
is NamedJDOMExternalizable -> "${component.externalFileName}${FileStorageCoreUtil.DEFAULT_EXT}"
is NamedJDOMExternalizable -> "${component.externalFileName}${PathManager.DEFAULT_EXT}"
else -> PathManager.DEFAULT_OPTIONS_FILE
}
}
Expand All @@ -102,5 +99,8 @@ class ApplicationStorageManager(application: Application?, pathMacroManager: Pat

override fun normalizeFileSpec(fileSpec: String) = removeMacroIfStartsWith(super.normalizeFileSpec(fileSpec), APP_CONFIG)

override fun expandMacros(path: String) = if (path[0] == '$') super.expandMacros(path) else "${expandMacro(APP_CONFIG)}/$path"
override fun expandMacro(collapsedPath: String): Path {
// APP_CONFIG is the first macro
return if (collapsedPath[0] == '$') super.expandMacro(collapsedPath) else macros.get(0).value.resolve(collapsedPath)
}
}
3 changes: 1 addition & 2 deletions platform/configuration-store-impl/src/ComponentStoreImpl.kt
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ import org.jetbrains.annotations.ApiStatus
import org.jetbrains.annotations.CalledInAwt
import org.jetbrains.annotations.TestOnly
import java.io.IOException
import java.nio.file.Paths
import java.util.*
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.TimeUnit
Expand Down Expand Up @@ -246,7 +245,7 @@ abstract class ComponentStoreImpl : IComponentStore {
LOG.debug { "saveComponent is called for ${stateSpec.name}" }
val saveManager = createSaveSessionProducerManager()
commitComponent(saveManager, ComponentInfoImpl(component, stateSpec), null, false)
val absolutePath = Paths.get(storageManager.expandMacros(findNonDeprecated(getStorageSpecs(component, stateSpec, StateStorageOperation.WRITE)).path)).toAbsolutePath().toString()
val absolutePath = storageManager.expandMacro(findNonDeprecated(getStorageSpecs(component, stateSpec, StateStorageOperation.WRITE)).path).toString()
Disposer.newDisposable().use {
VfsRootAccess.allowRootAccess(it, absolutePath)
runBlocking {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import org.jdom.Element
import org.jetbrains.annotations.ApiStatus
import java.io.Writer
import java.nio.file.Path
import java.nio.file.Paths

private const val FILE_SPEC = "${APP_CONFIG}/project.default.xml"

Expand Down Expand Up @@ -64,7 +63,7 @@ class DefaultProjectStoreImpl(override val project: Project) : ChildlessComponen
get() = if (ApplicationManager.getApplication().isUnitTestMode) StateLoadPolicy.NOT_LOAD else StateLoadPolicy.LOAD

private val storage by lazy {
DefaultProjectStorage(Paths.get(ApplicationManager.getApplication().stateStore.storageManager.expandMacros(FILE_SPEC)), FILE_SPEC, PathMacroManager.getInstance(project))
DefaultProjectStorage(ApplicationManager.getApplication().stateStore.storageManager.expandMacro(FILE_SPEC), FILE_SPEC, PathMacroManager.getInstance(project))
}

override val storageManager = object : StateStorageManager {
Expand All @@ -77,12 +76,9 @@ class DefaultProjectStoreImpl(override val project: Project) : ChildlessComponen
override fun removeStreamProvider(clazz: Class<out StreamProvider>) {
}

override fun rename(path: String, newName: String) {
}

override fun getStateStorage(storageSpec: Storage) = storage

override fun expandMacros(path: String) = throw UnsupportedOperationException()
override fun expandMacro(path: String) = throw UnsupportedOperationException()

override fun getOldStorage(component: Any, componentName: String, operation: StateStorageOperation) = storage
}
Expand Down
57 changes: 32 additions & 25 deletions platform/configuration-store-impl/src/ExportSettingsAction.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,18 @@ import com.intellij.openapi.options.SchemeManagerFactory
import com.intellij.openapi.project.DumbAware
import com.intellij.openapi.ui.Messages
import com.intellij.openapi.ui.showOkCancelDialog
import com.intellij.openapi.util.io.FileUtil
import com.intellij.serviceContainer.ComponentManagerImpl
import com.intellij.serviceContainer.processAllImplementationClasses
import com.intellij.util.ArrayUtil
import com.intellij.util.ReflectionUtil
import com.intellij.util.SmartList
import com.intellij.util.containers.CollectionFactory
import com.intellij.util.containers.putValue
import com.intellij.util.io.*
import java.io.IOException
import java.io.OutputStream
import java.io.StringWriter
import java.nio.file.Path
import java.nio.file.Paths
import java.util.*

internal fun isImportExportActionApplicable(): Boolean {
Expand All @@ -49,7 +48,7 @@ open class ExportSettingsAction : AnAction(), DumbAware {
protected open fun exportSettings(saveFile: Path, markedComponents: Set<ExportableItem>) {
val exportFiles = markedComponents.mapTo(CollectionFactory.createSmallMemoryFootprintSet()) { it.file }
saveFile.outputStream().use {
exportSettings(exportFiles, it, FileUtil.toSystemIndependentName(PathManager.getConfigPath()))
exportSettings(exportFiles, it, PathManager.getConfigDir())
}
}

Expand Down Expand Up @@ -92,24 +91,26 @@ open class ExportSettingsAction : AnAction(), DumbAware {
}
}

fun exportSettings(exportFiles: Set<Path>, out: OutputStream, configPath: String) {
val filter = CollectionFactory.createSmallMemoryFootprintSet<String>()
Compressor.Zip(out).filter { entryName, _ -> filter.add(entryName) }.use { zip ->
for (file in exportFiles) {
val fileInfo = file.basicAttributesIfExists() ?: continue
val relativePath = FileUtil.getRelativePath(configPath, file.toAbsolutePath().systemIndependentPath, '/')!!
if (fileInfo.isDirectory) {
zip.addDirectory(relativePath, file.toFile())
}
else {
zip.addFile(relativePath, file.inputStream())
fun exportSettings(exportFiles: Set<Path>, out: OutputStream, configPath: Path) {
val filter = HashSet<String>()
Compressor.Zip(out)
.nioFilter { entryName, _ -> filter.add(entryName) }
.use { zip ->
for (file in exportFiles) {
val fileInfo = file.basicAttributesIfExists() ?: continue
val relativePath = configPath.relativize(file).toString()
if (fileInfo.isDirectory) {
zip.addDirectory(relativePath, file)
}
else {
zip.addFile(relativePath, file)
}
}
}

exportInstalledPlugins(zip)
exportInstalledPlugins(zip)

zip.addFile(ImportSettingsFilenameFilter.SETTINGS_JAR_MARKER, ArrayUtil.EMPTY_BYTE_ARRAY)
}
zip.addFile(ImportSettingsFilenameFilter.SETTINGS_JAR_MARKER, ArrayUtil.EMPTY_BYTE_ARRAY)
}
}

data class ExportableItem(val file: Path, val presentableName: String, val roamingType: RoamingType = RoamingType.DEFAULT)
Expand All @@ -133,7 +134,7 @@ fun getExportableComponentsMap(isOnlyExisting: Boolean,
val processor = { component: ExportableComponent ->
for (file in component.exportFiles) {
val item = ExportableItem(file.toPath(), component.presentableName, RoamingType.DEFAULT)
result.putValue(item.file, item)
result.computeIfAbsent(item.file) { SmartList() }.add(item)
}
}

Expand All @@ -144,11 +145,16 @@ fun getExportableComponentsMap(isOnlyExisting: Boolean,
@Suppress("DEPRECATION")
ServiceBean.loadServicesFromBeans(ExportableComponent.EXTENSION_POINT, ExportableComponent::class.java).forEach(processor)

val configPath = storageManager.expandMacros(ROOT_CONFIG)
val configPath = storageManager.expandMacro(ROOT_CONFIG)

fun isSkipFile(file: Path): Boolean {
if (onlyPaths != null) {
var relativePath = FileUtil.getRelativePath(configPath, file.systemIndependentPath, '/')!!
// maybe in tests where in memory fs is used
if (configPath.fileSystem != file.fileSystem) {
return true
}

var relativePath = configPath.relativize(file).systemIndependentPath
if (!file.fileName.toString().contains('.') && !file.isFile()) {
relativePath += '/'
}
Expand Down Expand Up @@ -184,7 +190,7 @@ fun getExportableComponentsMap(isOnlyExisting: Boolean,

try {
additionalExportFile = getAdditionalExportFile(stateAnnotation, storageManager, ::isSkipFile)
file = Paths.get(storageManager.expandMacros(storage.path))
file = storageManager.expandMacro(storage.path)
}
catch (e: UnknownMacroException) {
LOG.error("Cannot expand macro for component \"${stateAnnotation.name}\"", e)
Expand Down Expand Up @@ -214,7 +220,7 @@ fun getExportableComponentsMap(isOnlyExisting: Boolean,
// must be in the end - because most of SchemeManager clients specify additionalExportFile in the State spec
(SchemeManagerFactory.getInstance() as SchemeManagerFactoryBase).process {
if (it.roamingType != RoamingType.DISABLED && it.fileSpec.getOrNull(0) != '$') {
val file = Paths.get(storageManager.expandMacros(ROOT_CONFIG), it.fileSpec)
val file = storageManager.expandMacro(ROOT_CONFIG).resolve(it.fileSpec)
if (!result.containsKey(file) && !isSkipFile(file)) {
result.putValue(file, ExportableItem(file, it.presentableName ?: "", it.roamingType))
}
Expand All @@ -232,10 +238,11 @@ private inline fun getAdditionalExportFile(stateAnnotation: State, storageManage
val additionalExportFile: Path?
// backward compatibility - path can contain macro
if (additionalExportPath[0] == '$') {
additionalExportFile = Paths.get(storageManager.expandMacros(additionalExportPath))
additionalExportFile = storageManager.expandMacro(additionalExportPath)
}
else {
additionalExportFile = Paths.get(storageManager.expandMacros(ROOT_CONFIG), additionalExportPath)
@Suppress("UNNECESSARY_NOT_NULL_ASSERTION")
additionalExportFile = storageManager.expandMacro(ROOT_CONFIG).resolve(additionalExportPath)!!
}
return if (isSkipFile(additionalExportFile)) null else additionalExportFile
}
Expand Down
48 changes: 39 additions & 9 deletions platform/configuration-store-impl/src/ModuleStateStorageManager.kt
Original file line number Diff line number Diff line change
@@ -1,34 +1,64 @@
// 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.
// 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.
package com.intellij.configurationStore

import com.intellij.ide.highlighter.ModuleFileType
import com.intellij.openapi.components.*
import com.intellij.openapi.module.Module
import com.intellij.openapi.module.ModuleManager
import com.intellij.openapi.module.impl.ModuleEx
import com.intellij.openapi.module.impl.ModuleManagerImpl
import com.intellij.openapi.module.impl.getModuleNameByFilePath
import com.intellij.openapi.project.isExternalStorageEnabled
import com.intellij.openapi.vfs.newvfs.events.VFileEvent
import org.jdom.Element
import org.jetbrains.annotations.ApiStatus
import java.io.FileNotFoundException
import java.io.IOException
import java.nio.file.Path
import java.nio.file.Paths
import kotlin.concurrent.write

@ApiStatus.Internal
open class ModuleStateStorageManager(macroSubstitutor: TrackingPathMacroSubstitutor, module: Module) : StateStorageManagerImpl("module", macroSubstitutor, module) {
open class ModuleStateStorageManager(macroSubstitutor: TrackingPathMacroSubstitutor, module: Module) : StateStorageManagerImpl("module", macroSubstitutor, module), RenameableStateStorageManager {
override fun getOldStorageSpec(component: Any, componentName: String, operation: StateStorageOperation) = StoragePathMacros.MODULE_FILE

override fun pathRenamed(oldPath: String, newPath: String, event: VFileEvent?) {
// the only macro is supported by ModuleStateStorageManager
final override fun expandMacro(collapsedPath: String): Path {
if (collapsedPath != StoragePathMacros.MODULE_FILE) {
throw IllegalStateException("Cannot resolve $collapsedPath in $macros")
}
return macros.get(0).value
}

final override fun rename(newName: String) {
storageLock.write {
val storage = getOrCreateStorage(StoragePathMacros.MODULE_FILE, RoamingType.DEFAULT) as FileBasedStorage
val file = storage.getVirtualFile(StateStorageOperation.WRITE)
try {
if (file != null) {
file.rename(storage, newName)
}
else if (storage.file.fileName.toString() != newName) {
// old file didn't exist or renaming failed
val newFile = storage.file.parent.resolve(newName)
storage.setFile(null, newFile)
pathRenamed(newFile, null)
}
}
catch (e: IOException) {
LOG.debug(e)
}
}
}

override fun pathRenamed(newPath: Path, event: VFileEvent?) {
try {
super.pathRenamed(oldPath, newPath, event)
setMacros(listOf(Macro(StoragePathMacros.MODULE_FILE, newPath)))
}
finally {
val requestor = event?.requestor
if (requestor == null || requestor !is StateStorage /* not renamed as result of explicit rename */) {
val module = componentManager as ModuleEx
val oldName = module.name
module.rename(getModuleNameByFilePath(newPath), false)
module.rename(newPath.fileName.toString().removeSuffix(ModuleFileType.DOT_DEFAULT_EXTENSION), false)
(ModuleManager.getInstance(module.project) as? ModuleManagerImpl)?.fireModuleRenamedByVfsEvent(module, oldName)
}
}
Expand Down Expand Up @@ -66,8 +96,8 @@ open class ModuleStateStorageManager(macroSubstitutor: TrackingPathMacroSubstitu
override val isExternalSystemStorageEnabled: Boolean
get() = (componentManager as Module?)?.project?.isExternalStorageEnabled ?: false

override fun createFileBasedStorage(path: String, collapsedPath: String, roamingType: RoamingType, rootTagName: String?): StateStorage {
return ModuleFileStorage(this, Paths.get(path), collapsedPath, rootTagName, roamingType, getMacroSubstitutor(collapsedPath), if (roamingType == RoamingType.DISABLED) null else compoundStreamProvider)
override fun createFileBasedStorage(path: Path, collapsedPath: String, roamingType: RoamingType, rootTagName: String?): StateStorage {
return ModuleFileStorage(this, path, collapsedPath, rootTagName, roamingType, getMacroSubstitutor(collapsedPath), if (roamingType == RoamingType.DISABLED) null else compoundStreamProvider)
}

override fun getFileBasedStorageConfiguration(fileSpec: String) = moduleFileBasedStorageConfiguration
Expand Down
Loading

0 comments on commit c11cdea

Please sign in to comment.