[platform] migrating app directories to recommended locations on Windows and Linux (IDEA-22407/IDEA-26855)

GitOrigin-RevId: 3bb0a4bfa863c6536ec8ce0cc9fff6c7005b2169
This commit is contained in:
Roman Shevchenko
2020-01-15 18:22:04 +01:00
committed by intellij-monorepo-bot
parent b4cb8f3639
commit 02c6cb2724
8 changed files with 127 additions and 128 deletions

View File

@@ -105,12 +105,12 @@ IDI_WINLAUNCHER ICON "WinLauncher.ico"
// TEXTINCLUDE // TEXTINCLUDE
// //
1 TEXTINCLUDE 1 TEXTINCLUDE
BEGIN BEGIN
"resource.h\0" "resource.h\0"
END END
2 TEXTINCLUDE 2 TEXTINCLUDE
BEGIN BEGIN
"#ifndef APSTUDIO_INVOKED\r\n" "#ifndef APSTUDIO_INVOKED\r\n"
"#include ""targetver.h""\r\n" "#include ""targetver.h""\r\n"
@@ -121,7 +121,7 @@ BEGIN
"\0" "\0"
END END
3 TEXTINCLUDE 3 TEXTINCLUDE
BEGIN BEGIN
"\r\n" "\r\n"
"\0" "\0"
@@ -139,14 +139,14 @@ STRINGTABLE
BEGIN BEGIN
IDS_APP_TITLE "WinLauncher" IDS_APP_TITLE "WinLauncher"
IDS_JDK_ENV_VAR "IDEA_JDK" IDS_JDK_ENV_VAR "IDEA_JDK"
IDS_VM_OPTIONS_PATH "%USERPROFILE%\\.__PRODUCT_PATHS_SELECTOR__" IDS_VM_OPTIONS_PATH "%APPDATA%\\JetBrains\\__PRODUCT_PATHS_SELECTOR__"
IDS_VM_OPTION_ERRORFILE "-XX:ErrorFile=%USERPROFILE%\\java_error_in___product_uc___%p.log" IDS_VM_OPTION_ERRORFILE "-XX:ErrorFile=%USERPROFILE%\\java_error_in___product_uc___%p.log"
IDS_VM_OPTION_HEAPDUMPPATH "-XX:HeapDumpPath=%USERPROFILE%\\java_error_in___product_uc__.hprof" IDS_VM_OPTION_HEAPDUMPPATH "-XX:HeapDumpPath=%USERPROFILE%\\java_error_in___product_uc__.hprof"
IDS_MAIN_CLASS "com/intellij/idea/Main" IDS_MAIN_CLASS "com/intellij/idea/Main"
IDS_CLASSPATH_LIBS "bootstrap.jar;extensions.jar;util.jar;jdom.jar;log4j.jar;trove4j.jar;jna.jar" IDS_CLASSPATH_LIBS "bootstrap.jar;extensions.jar;util.jar;jdom.jar;log4j.jar;trove4j.jar;jna.jar"
IDS_JDK_ONLY "true" IDS_JDK_ONLY "true"
IDC_WINLAUNCHER "WINLAUNCHER" IDC_WINLAUNCHER "WINLAUNCHER"
IDS_COMMAND_LINE_PROCESSOR_CLASS IDS_COMMAND_LINE_PROCESSOR_CLASS
"com/intellij/ide/WindowsCommandLineProcessor" "com/intellij/ide/WindowsCommandLineProcessor"
END END
@@ -160,16 +160,3 @@ END
#endif // English (United States) resources #endif // English (United States) resources
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View File

@@ -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 org.jetbrains.intellij.build.impl package org.jetbrains.intellij.build.impl
import com.intellij.openapi.util.io.FileFilters import com.intellij.openapi.util.io.FileFilters
@@ -135,6 +135,7 @@ class WindowsDistributionBuilder extends OsSpecificDistributionBuilder {
filterset(begintoken: "@@", endtoken: "@@") { filterset(begintoken: "@@", endtoken: "@@") {
filter(token: "product_full", value: fullName) filter(token: "product_full", value: fullName)
filter(token: "product_uc", value: buildContext.productProperties.getEnvironmentVariableBaseName(buildContext.applicationInfo)) filter(token: "product_uc", value: buildContext.productProperties.getEnvironmentVariableBaseName(buildContext.applicationInfo))
filter(token: "product_vendor", value: buildContext.applicationInfo.shortCompanyName)
filter(token: "vm_options", value: vmOptionsFileName) filter(token: "vm_options", value: vmOptionsFileName)
filter(token: "isEap", value: buildContext.applicationInfo.isEAP) filter(token: "isEap", value: buildContext.applicationInfo.isEAP)
filter(token: "system_selector", value: buildContext.systemSelector) filter(token: "system_selector", value: buildContext.systemSelector)
@@ -185,7 +186,7 @@ class WindowsDistributionBuilder extends OsSpecificDistributionBuilder {
IDS_JDK_ONLY=$buildContext.productProperties.toolsJarRequired IDS_JDK_ONLY=$buildContext.productProperties.toolsJarRequired
IDS_JDK_ENV_VAR=${envVarBaseName}_JDK$jdkEnvVarSuffix IDS_JDK_ENV_VAR=${envVarBaseName}_JDK$jdkEnvVarSuffix
IDS_APP_TITLE=$productName Launcher IDS_APP_TITLE=$productName Launcher
IDS_VM_OPTIONS_PATH=%USERPROFILE%\\\\.$buildContext.systemSelector\\\\config IDS_VM_OPTIONS_PATH=%APPDATA%\\\\${buildContext.applicationInfo.shortCompanyName}\\\\${buildContext.systemSelector}
IDS_VM_OPTION_ERRORFILE=-XX:ErrorFile=%USERPROFILE%\\\\java_error_in_${lowerCaseProductName}_%p.log IDS_VM_OPTION_ERRORFILE=-XX:ErrorFile=%USERPROFILE%\\\\java_error_in_${lowerCaseProductName}_%p.log
IDS_VM_OPTION_HEAPDUMPPATH=-XX:HeapDumpPath=%USERPROFILE%\\\\java_error_in_${lowerCaseProductName}.hprof IDS_VM_OPTION_HEAPDUMPPATH=-XX:HeapDumpPath=%USERPROFILE%\\\\java_error_in_${lowerCaseProductName}.hprof
IDC_WINLAUNCHER=${upperCaseProductName}_LAUNCHER IDC_WINLAUNCHER=${upperCaseProductName}_LAUNCHER

View File

@@ -63,8 +63,8 @@ if [ -n "$__product_uc___JDK" ] && [ -x "$__product_uc___JDK/bin/java" ]; then
JDK="$__product_uc___JDK" JDK="$__product_uc___JDK"
fi fi
if [ -z "$JDK" ] && [ -s "$HOME/.__system_selector__/config/__vm_options__.jdk" ]; then if [ -z "$JDK" ] && [ -s "${XDG_CONFIG_HOME:-$HOME/.config}/__system_selector__/__vm_options__.jdk" ]; then
USER_JRE=$("$CAT" "$HOME/.__system_selector__/config/__vm_options__.jdk") USER_JRE=$("$CAT" "${XDG_CONFIG_HOME:-$HOME/.config}/__system_selector__/__vm_options__.jdk")
if [ ! -d "$USER_JRE" ]; then if [ ! -d "$USER_JRE" ]; then
USER_JRE="$IDE_HOME/$USER_JRE" USER_JRE="$IDE_HOME/$USER_JRE"
fi fi
@@ -165,9 +165,9 @@ if [ -n "$__product_uc___VM_OPTIONS" ] && [ -r "$__product_uc___VM_OPTIONS" ]; t
elif [ -r "$IDE_HOME.vmoptions" ]; then elif [ -r "$IDE_HOME.vmoptions" ]; then
# Toolbox # Toolbox
VM_OPTIONS_FILE="$IDE_HOME.vmoptions" VM_OPTIONS_FILE="$IDE_HOME.vmoptions"
elif [ -r "$HOME/.__system_selector__/config/__vm_options__$BITS.vmoptions" ]; then elif [ -r "${XDG_CONFIG_HOME:-$HOME/.config}/__system_selector__/__vm_options__$BITS.vmoptions" ]; then
# user-overridden # user-overridden
VM_OPTIONS_FILE="$HOME/.__system_selector__/config/__vm_options__$BITS.vmoptions" VM_OPTIONS_FILE="${XDG_CONFIG_HOME:-$HOME/.config}/__system_selector__/__vm_options__$BITS.vmoptions"
elif [ -r "$IDE_BIN_HOME/__vm_options__$BITS.vmoptions" ]; then elif [ -r "$IDE_BIN_HOME/__vm_options__$BITS.vmoptions" ]; then
# default, standard installation # default, standard installation
VM_OPTIONS_FILE="$IDE_BIN_HOME/__vm_options__$BITS.vmoptions" VM_OPTIONS_FILE="$IDE_BIN_HOME/__vm_options__$BITS.vmoptions"

View File

@@ -20,9 +20,9 @@ IF EXIST "%@@product_uc@@_JDK%" SET JDK=%@@product_uc@@_JDK%
IF EXIST "%JDK%" GOTO check IF EXIST "%JDK%" GOTO check
SET BITS=64 SET BITS=64
SET USER_JDK64_FILE=%USERPROFILE%\.@@system_selector@@\config\@@vm_options@@.jdk SET USER_JDK64_FILE=%APPDATA%\@@product_vendor@@\@@system_selector@@\@@vm_options@@.jdk
SET BITS= SET BITS=
SET USER_JDK_FILE=%USERPROFILE%\.@@system_selector@@\config\@@vm_options@@.jdk SET USER_JDK_FILE=%APPDATA%\@@product_vendor@@\@@system_selector@@\@@vm_options@@.jdk
IF EXIST "%USER_JDK64_FILE%" ( IF EXIST "%USER_JDK64_FILE%" (
SET /P JDK=<%USER_JDK64_FILE% SET /P JDK=<%USER_JDK64_FILE%
) ELSE ( ) ELSE (
@@ -77,7 +77,7 @@ IF NOT EXIST "%VM_OPTIONS_FILE%" (
) )
IF NOT EXIST "%VM_OPTIONS_FILE%" ( IF NOT EXIST "%VM_OPTIONS_FILE%" (
:: user-overridden :: user-overridden
SET VM_OPTIONS_FILE=%USERPROFILE%\.@@system_selector@@\config\@@vm_options@@.vmoptions SET VM_OPTIONS_FILE=%APPDATA%\@@product_vendor@@\@@system_selector@@\@@vm_options@@.vmoptions
) )
IF NOT EXIST "%VM_OPTIONS_FILE%" ( IF NOT EXIST "%VM_OPTIONS_FILE%" (
:: default, standard installation :: default, standard installation

View File

@@ -21,6 +21,7 @@ import com.intellij.ui.AppUIUtil;
import com.intellij.util.PlatformUtils; import com.intellij.util.PlatformUtils;
import com.intellij.util.ReflectionUtil; import com.intellij.util.ReflectionUtil;
import com.intellij.util.Restarter; import com.intellij.util.Restarter;
import com.intellij.util.SystemProperties;
import com.intellij.util.io.Decompressor; import com.intellij.util.io.Decompressor;
import com.intellij.util.text.VersionComparatorUtil; import com.intellij.util.text.VersionComparatorUtil;
import gnu.trove.THashMap; import gnu.trove.THashMap;
@@ -49,7 +50,6 @@ import java.util.zip.ZipFile;
import static com.intellij.ide.GeneralSettings.IDE_GENERAL_XML; import static com.intellij.ide.GeneralSettings.IDE_GENERAL_XML;
import static com.intellij.openapi.application.PathManager.OPTIONS_DIRECTORY; import static com.intellij.openapi.application.PathManager.OPTIONS_DIRECTORY;
import static com.intellij.openapi.util.Pair.pair; import static com.intellij.openapi.util.Pair.pair;
import static com.intellij.openapi.util.text.StringUtil.startsWithIgnoreCase;
public final class ConfigImportHelper { public final class ConfigImportHelper {
private static final String FIRST_SESSION_KEY = "intellij.first.ide.session"; private static final String FIRST_SESSION_KEY = "intellij.first.ide.session";
@@ -64,6 +64,9 @@ public final class ConfigImportHelper {
private static final String CONTENTS = "Contents"; private static final String CONTENTS = "Contents";
private static final String PLIST = "Info.plist"; private static final String PLIST = "Info.plist";
private static final String PLUGINS = "plugins"; private static final String PLUGINS = "plugins";
private static final String SYSTEM = "system";
private static final Pattern SELECTOR_PATTERN = Pattern.compile("\\.?([^\\d]+)(\\d+(?:\\.\\d+)?)");
private ConfigImportHelper() { } private ConfigImportHelper() { }
@@ -154,21 +157,22 @@ public final class ConfigImportHelper {
} }
static @NotNull List<Path> findConfigDirectories(@NotNull Path newConfigDir) { static @NotNull List<Path> findConfigDirectories(@NotNull Path newConfigDir) {
// looks for existing config directories in the vicinity of the new one, assuming standard layout // looking for existing config directories ...
// ("~/Library/<selector_prefix><selector_version>" on macOS, "~/.<selector_prefix><selector_version>/config" on other OSes) Set<Path> homes = new HashSet<>();
boolean isMacOs = SystemInfo.isMac; homes.add(newConfigDir.getParent()); // ... in the vicinity of the new config directory
homes.add(newConfigDir.getFileSystem().getPath(PathManager.getDefaultConfigPathFor("JB-IDE")).getParent()); // ... in the default location
if (!SystemInfo.isMac) {
homes.add(newConfigDir.getFileSystem().getPath(SystemProperties.getUserHome())); // ... in the historic location ("~/.<selector>/config")
}
List<Path> homes = new ArrayList<>(2); String prefix = getPrefixFromSelector(PathManager.getPathsSelector());
homes.add((isMacOs ? newConfigDir : newConfigDir.getParent()).getParent()); if (prefix == null) prefix = getPrefixFromSelector(getNameWithVersion(newConfigDir));
String defaultPrefix = StringUtil.replace(StringUtil.notNullize( if (prefix == null) {
ApplicationNamesInfo.getInstance().getFullProductName(), PlatformUtils.getPlatformPrefix()), " ", ""); String productName = ApplicationNamesInfo.getInstance().getFullProductName();
Path configDir = newConfigDir.getFileSystem().getPath(PathManager.getDefaultConfigPathFor(defaultPrefix)); if (productName != null) prefix = productName.replace(" ", "");
Path configHome = (isMacOs ? configDir : configDir.getParent()).getParent(); }
if (!homes.contains(configHome)) homes.add(configHome); if (prefix == null) prefix = PlatformUtils.getPlatformPrefix();
String dotPrefix = '.' + prefix;
String nameWithSelector = StringUtil.notNullize(PathManager.getPathsSelector(), getNameWithVersion(newConfigDir, isMacOs));
String prefix = getPrefixFromSelector(nameWithSelector, isMacOs);
if (prefix == null) prefix = defaultPrefix;
List<Path> candidates = new ArrayList<>(); List<Path> candidates = new ArrayList<>();
for (Path home : homes) { for (Path home : homes) {
@@ -176,10 +180,11 @@ public final class ConfigImportHelper {
try (DirectoryStream<Path> stream = Files.newDirectoryStream(home)) { try (DirectoryStream<Path> stream = Files.newDirectoryStream(home)) {
for (Path path : stream) { for (Path path : stream) {
if (!path.equals(isMacOs ? newConfigDir : newConfigDir.getParent()) && if (!path.equals(newConfigDir)) {
startsWithIgnoreCase(path.getFileName().toString(), prefix) && String name = path.getFileName().toString();
Files.isDirectory(path)) { if ((StringUtil.startsWithIgnoreCase(name, prefix) || StringUtil.startsWithIgnoreCase(name, dotPrefix)) && Files.isDirectory(path)) {
candidates.add(path); candidates.add(path);
}
} }
} }
} }
@@ -191,7 +196,9 @@ public final class ConfigImportHelper {
Map<Path, FileTime> lastModified = new THashMap<>(); Map<Path, FileTime> lastModified = new THashMap<>();
for (Path child : candidates) { for (Path child : candidates) {
Path candidate = isMacOs ? child : child.resolve(CONFIG); Path candidate = child, config = child.resolve(CONFIG);
if (Files.isDirectory(config)) candidate = config;
FileTime max = null; FileTime max = null;
for (String name : OPTIONS) { for (String name : OPTIONS) {
try { try {
@@ -217,14 +224,20 @@ public final class ConfigImportHelper {
return result; return result;
} }
private static String getNameWithVersion(Path configDir, boolean isMacOs) { private static String getNameWithVersion(Path configDir) {
return (isMacOs ? configDir : configDir.getParent()).getFileName().toString(); String name = configDir.getFileName().toString();
if (CONFIG.equals(name)) name = StringUtil.trimStart(configDir.getParent().getFileName().toString(), ".");
return name;
} }
private static @Nullable String getPrefixFromSelector(String nameWithSelector, boolean isMacOs) { private static @Nullable String getPrefixFromSelector(@Nullable String nameWithSelector) {
Matcher m = Pattern.compile("\\.?([^\\d]+)\\d+(\\.\\d+)?").matcher(nameWithSelector); if (nameWithSelector != null) {
String selector = m.matches() ? m.group(1) : null; Matcher m = SELECTOR_PATTERN.matcher(nameWithSelector);
return StringUtil.isEmpty(selector) ? null : isMacOs ? selector : '.' + selector; if (m.matches()) {
return m.group(1);
}
}
return null;
} }
private static @Nullable Pair<Path, Path> findConfigDirectoryByPath(Path selectedDir) { private static @Nullable Pair<Path, Path> findConfigDirectoryByPath(Path selectedDir) {
@@ -241,7 +254,7 @@ public final class ConfigImportHelper {
} }
if (Files.isDirectory(selectedDir.resolve(SystemInfo.isMac ? CONTENTS : BIN))) { if (Files.isDirectory(selectedDir.resolve(SystemInfo.isMac ? CONTENTS : BIN))) {
Path configDir = getSettingsPath(selectedDir, PathManager.PROPERTY_CONFIG_PATH, PathManager::getDefaultConfigPathFor); Path configDir = getSettingsPath(selectedDir, PathManager.PROPERTY_CONFIG_PATH, ConfigImportHelper::defaultConfigPath);
if (configDir != null && isConfigDirectory(configDir)) { if (configDir != null && isConfigDirectory(configDir)) {
return pair(configDir, selectedDir); return pair(configDir, selectedDir);
} }
@@ -368,13 +381,13 @@ public final class ConfigImportHelper {
} }
Path oldPluginsDir = oldConfigDir.resolve(PLUGINS); Path oldPluginsDir = oldConfigDir.resolve(PLUGINS);
if (SystemInfo.isMac && !Files.isDirectory(oldPluginsDir)) { if (!Files.isDirectory(oldPluginsDir)) {
oldPluginsDir = null; oldPluginsDir = null;
if (oldIdeHome != null) { if (oldIdeHome != null) {
oldPluginsDir = getSettingsPath(oldIdeHome, PathManager.PROPERTY_PLUGINS_PATH, PathManager::getDefaultPluginPathFor); oldPluginsDir = getSettingsPath(oldIdeHome, PathManager.PROPERTY_PLUGINS_PATH, ConfigImportHelper::defaultPluginsPath);
} }
if (oldPluginsDir == null) { if (oldPluginsDir == null) {
oldPluginsDir = oldConfigDir.getFileSystem().getPath(PathManager.getDefaultPluginPathFor(oldConfigDir.getFileName().toString())); oldPluginsDir = oldConfigDir.getFileSystem().getPath(defaultPluginsPath(getNameWithVersion(oldConfigDir)));
} }
} }
@@ -415,13 +428,15 @@ public final class ConfigImportHelper {
// apply stale plugin updates // apply stale plugin updates
if (Files.isDirectory(oldPluginsDir)) { if (Files.isDirectory(oldPluginsDir)) {
Path oldSystemDir = null; Path oldSystemDir = oldConfigDir.getParent().resolve(SYSTEM);
if (oldIdeHome != null) { if (!Files.isDirectory(oldSystemDir)) {
oldSystemDir = getSettingsPath(oldIdeHome, PathManager.PROPERTY_SYSTEM_PATH, PathManager::getDefaultSystemPathFor); oldSystemDir = null;
} if (oldIdeHome != null) {
if (oldSystemDir == null) { oldSystemDir = getSettingsPath(oldIdeHome, PathManager.PROPERTY_SYSTEM_PATH, ConfigImportHelper::defaultSystemPath);
String selector = SystemInfo.isMac ? oldConfigDir.getFileName().toString() : StringUtil.trimLeading(oldConfigDir.getParent().getFileName().toString(), '.'); }
oldSystemDir = oldConfigDir.getFileSystem().getPath(PathManager.getDefaultSystemPathFor(selector)); if (oldSystemDir == null) {
oldSystemDir = oldConfigDir.getFileSystem().getPath(defaultSystemPath(getNameWithVersion(oldConfigDir)));
}
} }
Path script = oldSystemDir.resolve(PLUGINS + '/' + StartupActionScriptManager.ACTION_SCRIPT_FILE); // PathManager#getPluginTempPath Path script = oldSystemDir.resolve(PLUGINS + '/' + StartupActionScriptManager.ACTION_SCRIPT_FILE); // PathManager#getPluginTempPath
if (Files.isRegularFile(script)) { if (Files.isRegularFile(script)) {
@@ -446,7 +461,7 @@ public final class ConfigImportHelper {
} }
static void setKeymapIfNeeded(@NotNull Path oldConfigDir, @NotNull Path newConfigDir, @NotNull Logger log) { static void setKeymapIfNeeded(@NotNull Path oldConfigDir, @NotNull Path newConfigDir, @NotNull Logger log) {
String nameWithVersion = getNameWithVersion(oldConfigDir, true); String nameWithVersion = getNameWithVersion(oldConfigDir);
Matcher m = Pattern.compile("\\.?[^\\d]+(\\d+\\.\\d+)?").matcher(nameWithVersion); Matcher m = Pattern.compile("\\.?[^\\d]+(\\d+\\.\\d+)?").matcher(nameWithVersion);
if (!m.matches() || VersionComparatorUtil.compare("2019.1", m.group(1)) < 0) { if (!m.matches() || VersionComparatorUtil.compare("2019.1", m.group(1)) < 0) {
return; return;
@@ -506,4 +521,24 @@ public final class ConfigImportHelper {
} }
return false; return false;
} }
private static String defaultConfigPath(String selector) {
return newOrUnknown(selector) ? PathManager.getDefaultConfigPathFor(selector)
: SystemProperties.getUserHome() + "/." + selector + '/' + CONFIG;
}
private static String defaultPluginsPath(String selector) {
return newOrUnknown(selector) ? PathManager.getDefaultPluginPathFor(selector)
: SystemProperties.getUserHome() + "/." + selector + '/' + CONFIG + '/' + PLUGINS;
}
private static String defaultSystemPath(String selector) {
return newOrUnknown(selector) ? PathManager.getDefaultSystemPathFor(selector)
: SystemProperties.getUserHome() + "/." + selector + '/' + SYSTEM;
}
private static boolean newOrUnknown(String selector) {
Matcher m = SELECTOR_PATTERN.matcher(selector);
return !m.matches() || "2020.1".compareTo(m.group(2)) >= 0;
}
} }

View File

@@ -27,7 +27,7 @@ import java.util.function.Predicate
private val LOG = logger<ConfigImportHelperTest>() private val LOG = logger<ConfigImportHelperTest>()
class ConfigImportHelperTest : BareTestFixtureTestCase() { class ConfigImportHelperTest : BareTestFixtureTestCase() {
@JvmField @Rule val memoryFs = InMemoryFsRule() @JvmField @Rule val memoryFs = InMemoryFsRule(SystemInfo.isWindows)
@JvmField @Rule val localTempDir = TempDirectory() @JvmField @Rule val localTempDir = TempDirectory()
@Test fun `config directory is valid for import`() { @Test fun `config directory is valid for import`() {
@@ -46,6 +46,15 @@ class ConfigImportHelperTest : BareTestFixtureTestCase() {
} }
} }
@Test fun `find both historic and current config directories`() {
val cfg15 = createConfigDir("15", storageTS = 1448928000000)
val cfg193 = createConfigDir("2019.1", storageTS = 1574845200000)
val cfg201 = createConfigDir("2020.1", storageTS = 1585731600000)
val newConfigPath = createConfigDir("2020.2")
assertThat(ConfigImportHelper.findConfigDirectories(newConfigPath)).containsExactly(cfg201, cfg193, cfg15)
}
@Test fun `find recent config directory`() { @Test fun `find recent config directory`() {
val cfg201 = createConfigDir("2020.1", storageTS = 100) val cfg201 = createConfigDir("2020.1", storageTS = 100)
val cfg211 = createConfigDir("2021.1", storageTS = 200) val cfg211 = createConfigDir("2021.1", storageTS = 200)
@@ -80,7 +89,7 @@ class ConfigImportHelperTest : BareTestFixtureTestCase() {
val cfg191 = createConfigDir("2019.1", "DataGrip", 1548225505000) val cfg191 = createConfigDir("2019.1", "DataGrip", 1548225505000)
val cfg173 = createConfigDir("2017.3", "DataGrip", 1549092322000) val cfg173 = createConfigDir("2017.3", "DataGrip", 1549092322000)
val newConfigPath = createConfigDir("2019.2", "DataGrip") val newConfigPath = createConfigDir("2020.1", "DataGrip")
assertThat(ConfigImportHelper.findConfigDirectories(newConfigPath)).containsExactly( assertThat(ConfigImportHelper.findConfigDirectories(newConfigPath)).containsExactly(
cfg173, cfg191, cfg182, cfg183, cfg181, cfg163, cfg172, cfg171, cfg161, cfg162, cfg10) cfg173, cfg191, cfg182, cfg183, cfg181, cfg163, cfg172, cfg171, cfg161, cfg162, cfg10)
} }
@@ -146,9 +155,9 @@ class ConfigImportHelperTest : BareTestFixtureTestCase() {
} }
private fun createConfigDir(version: String, product: String = "IntelliJIdea", storageTS: Long = 0): Path { private fun createConfigDir(version: String, product: String = "IntelliJIdea", storageTS: Long = 0): Path {
val defaultPath = PathManager.getDefaultConfigPathFor("${product}${version}") val path = if (SystemInfo.isMac || version >= "2020.1") PathManager.getDefaultConfigPathFor("${product}${version}")
val relative = Paths.get(SystemProperties.getUserHome()).relativize(Paths.get(defaultPath)) else "${SystemProperties.getUserHome()}/.${product}${version}/config"
val dir = Files.createDirectories(memoryFs.fs.getPath("/data/${relative.toString().replace('\\', '/')}")) val dir = Files.createDirectories(memoryFs.fs.getPath(path).normalize())
if (storageTS > 0) writeStorageFile(dir, storageTS) if (storageTS > 0) writeStorageFile(dir, storageTS)
return dir return dir
} }

View File

@@ -1,18 +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-2016 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.
*/
package com.intellij.testFramework.rules package com.intellij.testFramework.rules
import com.github.marschall.memoryfilesystem.MemoryFileSystemBuilder import com.github.marschall.memoryfilesystem.MemoryFileSystemBuilder
@@ -23,9 +9,8 @@ import java.net.URLEncoder
import java.nio.file.FileSystem import java.nio.file.FileSystem
import kotlin.properties.Delegates import kotlin.properties.Delegates
class InMemoryFsRule : ExternalResource() { class InMemoryFsRule(private val windows: Boolean = false) : ExternalResource() {
private var _fs: FileSystem? = null private var _fs: FileSystem? = null
private var sanitizedName: String by Delegates.notNull() private var sanitizedName: String by Delegates.notNull()
override fun apply(base: Statement, description: Description): Statement { override fun apply(base: Statement, description: Description): Statement {
@@ -35,15 +20,11 @@ class InMemoryFsRule : ExternalResource() {
val fs: FileSystem val fs: FileSystem
get() { get() {
var r = _fs if (_fs == null) {
if (r == null) { _fs = (if (windows) MemoryFileSystemBuilder.newWindows().setCurrentWorkingDirectory("C:\\")
r = MemoryFileSystemBuilder else MemoryFileSystemBuilder.newLinux().setCurrentWorkingDirectory("/")).build(sanitizedName)
.newLinux()
.setCurrentWorkingDirectory("/")
.build(sanitizedName)
_fs = r
} }
return r!! return _fs!!
} }
override fun after() { override fun after() {

View File

@@ -46,6 +46,7 @@ public class PathManager {
private static final String CONFIG_DIRECTORY = "config"; private static final String CONFIG_DIRECTORY = "config";
private static final String SYSTEM_DIRECTORY = "system"; private static final String SYSTEM_DIRECTORY = "system";
private static final String PATHS_SELECTOR = System.getProperty(PROPERTY_PATHS_SELECTOR); private static final String PATHS_SELECTOR = System.getProperty(PROPERTY_PATHS_SELECTOR);
private static final String IDE_VENDOR_NAME = System.getProperty("idea.vendor.name", "JetBrains");
private static class Lazy { private static class Lazy {
private static final Pattern PROPERTY_REF = Pattern.compile("\\$\\{(.+?)}"); private static final Pattern PROPERTY_REF = Pattern.compile("\\$\\{(.+?)}");
@@ -262,7 +263,7 @@ public class PathManager {
@NotNull @NotNull
public static String getDefaultConfigPathFor(@NotNull String selector) { public static String getDefaultConfigPathFor(@NotNull String selector) {
return platformPath(selector, "Library/Preferences", CONFIG_DIRECTORY); return platformPath(selector, "Library/Preferences", "APPDATA", "", "XDG_CONFIG_HOME", ".config", "");
} }
@NotNull @NotNull
@@ -283,7 +284,7 @@ public class PathManager {
if (explicit != null) { if (explicit != null) {
ourPluginsPath = explicit; ourPluginsPath = explicit;
} }
else if (SystemInfoRt.isMac && PATHS_SELECTOR != null) { else if (PATHS_SELECTOR != null) {
ourPluginsPath = getDefaultPluginPathFor(PATHS_SELECTOR); ourPluginsPath = getDefaultPluginPathFor(PATHS_SELECTOR);
} }
else { else {
@@ -295,12 +296,7 @@ public class PathManager {
@NotNull @NotNull
public static String getDefaultPluginPathFor(@NotNull String selector) { public static String getDefaultPluginPathFor(@NotNull String selector) {
if (SystemInfoRt.isMac) { return platformPath(selector, "Library/Application Support", "APPDATA", PLUGINS_DIRECTORY, "XDG_DATA_HOME", ".local/share", "");
return platformPath(selector, "Library/Application Support", "");
}
else {
return getDefaultConfigPathFor(selector) + '/' + PLUGINS_DIRECTORY;
}
} }
@Nullable @Nullable
@@ -331,7 +327,7 @@ public class PathManager {
@NotNull @NotNull
public static String getDefaultSystemPathFor(@NotNull String selector) { public static String getDefaultSystemPathFor(@NotNull String selector) {
return platformPath(selector, "Library/Caches", SYSTEM_DIRECTORY); return platformPath(selector, "Library/Caches", "LOCALAPPDATA", "", "XDG_CACHE_HOME", ".cache", "");
} }
@NotNull @NotNull
@@ -354,8 +350,8 @@ public class PathManager {
if (explicit != null) { if (explicit != null) {
ourLogPath = explicit; ourLogPath = explicit;
} }
else if (SystemInfoRt.isMac && PATHS_SELECTOR != null) { else if (PATHS_SELECTOR != null) {
ourLogPath = SystemProperties.getUserHome() + "/Library/Logs/" + PATHS_SELECTOR; ourLogPath = platformPath(PATHS_SELECTOR, "Library/Logs", "LOCALAPPDATA", LOG_DIRECTORY, "XDG_CACHE_HOME", ".cache", LOG_DIRECTORY);
} }
else { else {
ourLogPath = getSystemPath() + '/' + LOG_DIRECTORY; ourLogPath = getSystemPath() + '/' + LOG_DIRECTORY;
@@ -589,39 +585,29 @@ public class PathManager {
return path != null ? getAbsolutePath(StringUtilRt.unquoteString(path, '"')) : null; return path != null ? getAbsolutePath(StringUtilRt.unquoteString(path, '"')) : null;
} }
// todo[r.sh] XDG directories, Windows folders private static String platformPath(String selector, String macDir, String winVar, String winSub, String xdgVar, String xdgDfl, String xdgSub) {
// http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
// http://www.microsoft.com/security/portal/mmpc/shared/variables.aspx
private static String platformPath(String selector, String macDir, String fallback) {
return platformPath(selector, macDir, null, null, null, fallback);
}
@SuppressWarnings("SameParameterValue")
private static String platformPath(String selector,
String macDir,
@Nullable String winVar,
@Nullable String xdgVar,
@Nullable String xdgDir,
String fallback) {
String userHome = SystemProperties.getUserHome(); String userHome = SystemProperties.getUserHome();
if (SystemInfoRt.isMac) { if (SystemInfoRt.isMac) {
return userHome + '/' + macDir + '/' + selector; return userHome + '/' + macDir + '/' + selector;
} }
if (winVar != null && SystemInfoRt.isWindows) { if (SystemInfoRt.isWindows) {
String dir = System.getenv(winVar); String dir = System.getenv(winVar);
if (dir != null) { if (dir == null || dir.isEmpty()) dir = userHome + "\\AppData\\" + (winVar.startsWith("LOCAL") ? "Local" : "Roaming");
return dir + '/' + selector; dir = dir + '\\' + IDE_VENDOR_NAME + '\\' + selector;
} if (!winSub.isEmpty()) dir = dir + '\\' + winSub;
return dir;
} }
if (xdgVar != null && xdgDir != null && SystemInfoRt.isUnix) { if (SystemInfoRt.isUnix) {
String dir = System.getenv(xdgVar); String dir = System.getenv(xdgVar);
if (dir == null) dir = userHome + '/' + xdgDir; if (dir == null || dir.isEmpty()) dir = userHome + '/' + xdgDfl;
return dir + '/' + selector; dir = dir + '/' + selector;
if (!xdgSub.isEmpty()) dir = dir + '/' + xdgSub;
return dir;
} }
return userHome + "/." + selector + '/' + fallback; throw new UnsupportedOperationException("Unsupported OS: " + SystemInfoRt.OS_NAME);
} }
} }