ExternalStorage — request reimport if data format changed or data corrupted

This commit is contained in:
Vladimir Krivosheev
2017-04-28 18:27:39 +02:00
parent 313802a59a
commit 1131e869eb
2 changed files with 48 additions and 22 deletions
@@ -23,18 +23,20 @@ import com.intellij.openapi.components.*
import com.intellij.openapi.diagnostic.catchAndLog
import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsDataStorage
import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManagerImpl
import com.intellij.openapi.module.Module
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.ex.ProjectEx
import com.intellij.openapi.roots.ExternalProjectSystemRegistry
import com.intellij.openapi.roots.ProjectModelElement
import com.intellij.openapi.startup.StartupManager
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.registry.Registry
import com.intellij.util.io.DataExternalizer
import com.intellij.util.io.EnumeratorStringDescriptor
import com.intellij.util.io.PersistentHashMap
import java.io.*
import com.intellij.util.io.*
import java.io.DataInput
import java.io.DataOutput
import java.io.IOException
import java.io.InputStream
import java.util.*
private val EXTERNAL_STORAGE_ANNOTATION = FileStorageAnnotation(StoragePathMacros.MODULE_FILE, false, ExternalProjectStorage::class.java)
@@ -93,10 +95,14 @@ internal class ExternalSystemStreamProviderFactory(private val project: Project)
}
}
private fun createStorage(project: Project): PersistentHashMap<String, ByteArray> {
val file = File(ExternalProjectsDataStorage.getProjectConfigurationDir(), "${project.locationHash}/modules")
private val MODULE_FILE_FORMAT_VERSION = 0
fun createMap() = PersistentHashMap<String, ByteArray>(file, EnumeratorStringDescriptor.INSTANCE, object : DataExternalizer<ByteArray> {
private fun createStorage(project: Project): PersistentHashMap<String, ByteArray> {
val dir = ExternalProjectsDataStorage.getProjectConfigurationDir(project)
val versionFile = dir.resolve("modules.version")
val file = dir.resolve("modules")
fun createMap() = PersistentHashMap<String, ByteArray>(file.toFile(), EnumeratorStringDescriptor.INSTANCE, object : DataExternalizer<ByteArray> {
override fun read(`in`: DataInput): ByteArray {
val available = (`in` as InputStream).available()
val result = ByteArray(available)
@@ -109,13 +115,27 @@ private fun createStorage(project: Project): PersistentHashMap<String, ByteArray
}
})
fun deleteFileAndWriteLatestFormatVersion() {
file.delete()
versionFile.outputStream().use { it.write(MODULE_FILE_FORMAT_VERSION) }
StartupManager.getInstance(project).runWhenProjectIsInitialized {
val externalProjectsManager = ExternalProjectsManagerImpl.getInstance(project)
externalProjectsManager.init()
externalProjectsManager.externalProjectsWatcher.markDirtyAllExternalProjects()
}
}
try {
val fileVersion = versionFile.inputStreamIfExists()?.use { it.read() } ?: -1
if (fileVersion != MODULE_FILE_FORMAT_VERSION) {
deleteFileAndWriteLatestFormatVersion()
}
return createMap()
}
catch (e: IOException) {
// todo force project reimport
LOG.info(e)
FileUtil.delete(file)
deleteFileAndWriteLatestFormatVersion()
}
return createMap()
}
@@ -49,6 +49,9 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
@@ -321,8 +324,8 @@ public class ExternalProjectsDataStorage implements SettingsSavingComponent, Per
private static void doSave(@NotNull final Project project, @NotNull Collection<InternalExternalProjectInfo> externalProjects)
throws IOException {
final File projectConfigurationFile = getProjectConfigurationFile(project);
if (!FileUtil.createParentDirs(projectConfigurationFile)) {
final Path projectConfigurationFile = getProjectConfigurationFile(project);
if (!FileUtil.createParentDirs(projectConfigurationFile.toFile())) {
throw new IOException("Unable to save " + projectConfigurationFile);
}
@@ -343,7 +346,7 @@ public class ExternalProjectsDataStorage implements SettingsSavingComponent, Per
});
}
DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(projectConfigurationFile)));
DataOutputStream out = new DataOutputStream(new BufferedOutputStream(Files.newOutputStream(projectConfigurationFile)));
try {
out.writeUTF(STORAGE_VERSION);
out.writeInt(externalProjects.size());
@@ -378,10 +381,10 @@ public class ExternalProjectsDataStorage implements SettingsSavingComponent, Per
@NotNull
private static Collection<InternalExternalProjectInfo> load(@NotNull Project project) throws IOException {
SmartList<InternalExternalProjectInfo> projects = new SmartList<>();
@SuppressWarnings("unchecked") final File configurationFile = getProjectConfigurationFile(project);
if (!configurationFile.isFile()) return projects;
@SuppressWarnings("unchecked") final Path configurationFile = getProjectConfigurationFile(project);
if (!Files.isRegularFile(configurationFile)) return projects;
DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(configurationFile)));
DataInputStream in = new DataInputStream(new BufferedInputStream(Files.newInputStream(configurationFile)));
try {
final String storage_version = in.readUTF();
@@ -409,16 +412,19 @@ public class ExternalProjectsDataStorage implements SettingsSavingComponent, Per
return projects;
}
private static File getProjectConfigurationFile(@NotNull Project project) {
return new File(getProjectConfigurationDir(), project.getLocationHash() + "/project.dat");
@NotNull
private static Path getProjectConfigurationFile(@NotNull Project project) {
return getProjectConfigurationDir(project).resolve("project.dat");
}
public static File getProjectConfigurationDir() {
return getExternalBuildSystemDir("Projects");
@NotNull
public static Path getProjectConfigurationDir(@NotNull Project project) {
return getExternalBuildSystemDir("Projects").resolve(project.getLocationHash());
}
private static File getExternalBuildSystemDir(String folder) {
return new File(PathManager.getSystemPath(), "external_build_system" + "/" + folder).getAbsoluteFile();
@NotNull
private static Path getExternalBuildSystemDir(String folder) {
return Paths.get(PathManager.getSystemPath(), "external_build_system", folder).toAbsolutePath();
}
@Nullable