[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
//
1 TEXTINCLUDE
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
2 TEXTINCLUDE
BEGIN
"#ifndef APSTUDIO_INVOKED\r\n"
"#include ""targetver.h""\r\n"
@@ -121,7 +121,7 @@ BEGIN
"\0"
END
3 TEXTINCLUDE
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
@@ -139,14 +139,14 @@ STRINGTABLE
BEGIN
IDS_APP_TITLE "WinLauncher"
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_HEAPDUMPPATH "-XX:HeapDumpPath=%USERPROFILE%\\java_error_in___product_uc__.hprof"
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_JDK_ONLY "true"
IDC_WINLAUNCHER "WINLAUNCHER"
IDS_COMMAND_LINE_PROCESSOR_CLASS
IDS_COMMAND_LINE_PROCESSOR_CLASS
"com/intellij/ide/WindowsCommandLineProcessor"
END
@@ -160,16 +160,3 @@ END
#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
import com.intellij.openapi.util.io.FileFilters
@@ -135,6 +135,7 @@ class WindowsDistributionBuilder extends OsSpecificDistributionBuilder {
filterset(begintoken: "@@", endtoken: "@@") {
filter(token: "product_full", value: fullName)
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: "isEap", value: buildContext.applicationInfo.isEAP)
filter(token: "system_selector", value: buildContext.systemSelector)
@@ -185,7 +186,7 @@ class WindowsDistributionBuilder extends OsSpecificDistributionBuilder {
IDS_JDK_ONLY=$buildContext.productProperties.toolsJarRequired
IDS_JDK_ENV_VAR=${envVarBaseName}_JDK$jdkEnvVarSuffix
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_HEAPDUMPPATH=-XX:HeapDumpPath=%USERPROFILE%\\\\java_error_in_${lowerCaseProductName}.hprof
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"
fi
if [ -z "$JDK" ] && [ -s "$HOME/.__system_selector__/config/__vm_options__.jdk" ]; then
USER_JRE=$("$CAT" "$HOME/.__system_selector__/config/__vm_options__.jdk")
if [ -z "$JDK" ] && [ -s "${XDG_CONFIG_HOME:-$HOME/.config}/__system_selector__/__vm_options__.jdk" ]; then
USER_JRE=$("$CAT" "${XDG_CONFIG_HOME:-$HOME/.config}/__system_selector__/__vm_options__.jdk")
if [ ! -d "$USER_JRE" ]; then
USER_JRE="$IDE_HOME/$USER_JRE"
fi
@@ -165,9 +165,9 @@ if [ -n "$__product_uc___VM_OPTIONS" ] && [ -r "$__product_uc___VM_OPTIONS" ]; t
elif [ -r "$IDE_HOME.vmoptions" ]; then
# Toolbox
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
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
# default, standard installation
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
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 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%" (
SET /P JDK=<%USER_JDK64_FILE%
) ELSE (
@@ -77,7 +77,7 @@ IF NOT EXIST "%VM_OPTIONS_FILE%" (
)
IF NOT EXIST "%VM_OPTIONS_FILE%" (
:: 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%" (
:: default, standard installation

View File

@@ -21,6 +21,7 @@ import com.intellij.ui.AppUIUtil;
import com.intellij.util.PlatformUtils;
import com.intellij.util.ReflectionUtil;
import com.intellij.util.Restarter;
import com.intellij.util.SystemProperties;
import com.intellij.util.io.Decompressor;
import com.intellij.util.text.VersionComparatorUtil;
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.openapi.application.PathManager.OPTIONS_DIRECTORY;
import static com.intellij.openapi.util.Pair.pair;
import static com.intellij.openapi.util.text.StringUtil.startsWithIgnoreCase;
public final class ConfigImportHelper {
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 PLIST = "Info.plist";
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() { }
@@ -154,21 +157,22 @@ public final class ConfigImportHelper {
}
static @NotNull List<Path> findConfigDirectories(@NotNull Path newConfigDir) {
// looks for existing config directories in the vicinity of the new one, assuming standard layout
// ("~/Library/<selector_prefix><selector_version>" on macOS, "~/.<selector_prefix><selector_version>/config" on other OSes)
boolean isMacOs = SystemInfo.isMac;
// looking for existing config directories ...
Set<Path> homes = new HashSet<>();
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);
homes.add((isMacOs ? newConfigDir : newConfigDir.getParent()).getParent());
String defaultPrefix = StringUtil.replace(StringUtil.notNullize(
ApplicationNamesInfo.getInstance().getFullProductName(), PlatformUtils.getPlatformPrefix()), " ", "");
Path configDir = newConfigDir.getFileSystem().getPath(PathManager.getDefaultConfigPathFor(defaultPrefix));
Path configHome = (isMacOs ? configDir : configDir.getParent()).getParent();
if (!homes.contains(configHome)) homes.add(configHome);
String nameWithSelector = StringUtil.notNullize(PathManager.getPathsSelector(), getNameWithVersion(newConfigDir, isMacOs));
String prefix = getPrefixFromSelector(nameWithSelector, isMacOs);
if (prefix == null) prefix = defaultPrefix;
String prefix = getPrefixFromSelector(PathManager.getPathsSelector());
if (prefix == null) prefix = getPrefixFromSelector(getNameWithVersion(newConfigDir));
if (prefix == null) {
String productName = ApplicationNamesInfo.getInstance().getFullProductName();
if (productName != null) prefix = productName.replace(" ", "");
}
if (prefix == null) prefix = PlatformUtils.getPlatformPrefix();
String dotPrefix = '.' + prefix;
List<Path> candidates = new ArrayList<>();
for (Path home : homes) {
@@ -176,10 +180,11 @@ public final class ConfigImportHelper {
try (DirectoryStream<Path> stream = Files.newDirectoryStream(home)) {
for (Path path : stream) {
if (!path.equals(isMacOs ? newConfigDir : newConfigDir.getParent()) &&
startsWithIgnoreCase(path.getFileName().toString(), prefix) &&
Files.isDirectory(path)) {
candidates.add(path);
if (!path.equals(newConfigDir)) {
String name = path.getFileName().toString();
if ((StringUtil.startsWithIgnoreCase(name, prefix) || StringUtil.startsWithIgnoreCase(name, dotPrefix)) && Files.isDirectory(path)) {
candidates.add(path);
}
}
}
}
@@ -191,7 +196,9 @@ public final class ConfigImportHelper {
Map<Path, FileTime> lastModified = new THashMap<>();
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;
for (String name : OPTIONS) {
try {
@@ -217,14 +224,20 @@ public final class ConfigImportHelper {
return result;
}
private static String getNameWithVersion(Path configDir, boolean isMacOs) {
return (isMacOs ? configDir : configDir.getParent()).getFileName().toString();
private static String getNameWithVersion(Path configDir) {
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) {
Matcher m = Pattern.compile("\\.?([^\\d]+)\\d+(\\.\\d+)?").matcher(nameWithSelector);
String selector = m.matches() ? m.group(1) : null;
return StringUtil.isEmpty(selector) ? null : isMacOs ? selector : '.' + selector;
private static @Nullable String getPrefixFromSelector(@Nullable String nameWithSelector) {
if (nameWithSelector != null) {
Matcher m = SELECTOR_PATTERN.matcher(nameWithSelector);
if (m.matches()) {
return m.group(1);
}
}
return null;
}
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))) {
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)) {
return pair(configDir, selectedDir);
}
@@ -368,13 +381,13 @@ public final class ConfigImportHelper {
}
Path oldPluginsDir = oldConfigDir.resolve(PLUGINS);
if (SystemInfo.isMac && !Files.isDirectory(oldPluginsDir)) {
if (!Files.isDirectory(oldPluginsDir)) {
oldPluginsDir = 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) {
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
if (Files.isDirectory(oldPluginsDir)) {
Path oldSystemDir = null;
if (oldIdeHome != null) {
oldSystemDir = getSettingsPath(oldIdeHome, PathManager.PROPERTY_SYSTEM_PATH, PathManager::getDefaultSystemPathFor);
}
if (oldSystemDir == null) {
String selector = SystemInfo.isMac ? oldConfigDir.getFileName().toString() : StringUtil.trimLeading(oldConfigDir.getParent().getFileName().toString(), '.');
oldSystemDir = oldConfigDir.getFileSystem().getPath(PathManager.getDefaultSystemPathFor(selector));
Path oldSystemDir = oldConfigDir.getParent().resolve(SYSTEM);
if (!Files.isDirectory(oldSystemDir)) {
oldSystemDir = null;
if (oldIdeHome != null) {
oldSystemDir = getSettingsPath(oldIdeHome, PathManager.PROPERTY_SYSTEM_PATH, ConfigImportHelper::defaultSystemPath);
}
if (oldSystemDir == null) {
oldSystemDir = oldConfigDir.getFileSystem().getPath(defaultSystemPath(getNameWithVersion(oldConfigDir)));
}
}
Path script = oldSystemDir.resolve(PLUGINS + '/' + StartupActionScriptManager.ACTION_SCRIPT_FILE); // PathManager#getPluginTempPath
if (Files.isRegularFile(script)) {
@@ -446,7 +461,7 @@ public final class ConfigImportHelper {
}
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);
if (!m.matches() || VersionComparatorUtil.compare("2019.1", m.group(1)) < 0) {
return;
@@ -506,4 +521,24 @@ public final class ConfigImportHelper {
}
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>()
class ConfigImportHelperTest : BareTestFixtureTestCase() {
@JvmField @Rule val memoryFs = InMemoryFsRule()
@JvmField @Rule val memoryFs = InMemoryFsRule(SystemInfo.isWindows)
@JvmField @Rule val localTempDir = TempDirectory()
@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`() {
val cfg201 = createConfigDir("2020.1", storageTS = 100)
val cfg211 = createConfigDir("2021.1", storageTS = 200)
@@ -80,7 +89,7 @@ class ConfigImportHelperTest : BareTestFixtureTestCase() {
val cfg191 = createConfigDir("2019.1", "DataGrip", 1548225505000)
val cfg173 = createConfigDir("2017.3", "DataGrip", 1549092322000)
val newConfigPath = createConfigDir("2019.2", "DataGrip")
val newConfigPath = createConfigDir("2020.1", "DataGrip")
assertThat(ConfigImportHelper.findConfigDirectories(newConfigPath)).containsExactly(
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 {
val defaultPath = PathManager.getDefaultConfigPathFor("${product}${version}")
val relative = Paths.get(SystemProperties.getUserHome()).relativize(Paths.get(defaultPath))
val dir = Files.createDirectories(memoryFs.fs.getPath("/data/${relative.toString().replace('\\', '/')}"))
val path = if (SystemInfo.isMac || version >= "2020.1") PathManager.getDefaultConfigPathFor("${product}${version}")
else "${SystemProperties.getUserHome()}/.${product}${version}/config"
val dir = Files.createDirectories(memoryFs.fs.getPath(path).normalize())
if (storageTS > 0) writeStorageFile(dir, storageTS)
return dir
}

View File

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

View File

@@ -46,6 +46,7 @@ public class PathManager {
private static final String CONFIG_DIRECTORY = "config";
private static final String SYSTEM_DIRECTORY = "system";
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 final Pattern PROPERTY_REF = Pattern.compile("\\$\\{(.+?)}");
@@ -262,7 +263,7 @@ public class PathManager {
@NotNull
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
@@ -283,7 +284,7 @@ public class PathManager {
if (explicit != null) {
ourPluginsPath = explicit;
}
else if (SystemInfoRt.isMac && PATHS_SELECTOR != null) {
else if (PATHS_SELECTOR != null) {
ourPluginsPath = getDefaultPluginPathFor(PATHS_SELECTOR);
}
else {
@@ -295,12 +296,7 @@ public class PathManager {
@NotNull
public static String getDefaultPluginPathFor(@NotNull String selector) {
if (SystemInfoRt.isMac) {
return platformPath(selector, "Library/Application Support", "");
}
else {
return getDefaultConfigPathFor(selector) + '/' + PLUGINS_DIRECTORY;
}
return platformPath(selector, "Library/Application Support", "APPDATA", PLUGINS_DIRECTORY, "XDG_DATA_HOME", ".local/share", "");
}
@Nullable
@@ -331,7 +327,7 @@ public class PathManager {
@NotNull
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
@@ -354,8 +350,8 @@ public class PathManager {
if (explicit != null) {
ourLogPath = explicit;
}
else if (SystemInfoRt.isMac && PATHS_SELECTOR != null) {
ourLogPath = SystemProperties.getUserHome() + "/Library/Logs/" + PATHS_SELECTOR;
else if (PATHS_SELECTOR != null) {
ourLogPath = platformPath(PATHS_SELECTOR, "Library/Logs", "LOCALAPPDATA", LOG_DIRECTORY, "XDG_CACHE_HOME", ".cache", LOG_DIRECTORY);
}
else {
ourLogPath = getSystemPath() + '/' + LOG_DIRECTORY;
@@ -589,39 +585,29 @@ public class PathManager {
return path != null ? getAbsolutePath(StringUtilRt.unquoteString(path, '"')) : null;
}
// todo[r.sh] XDG directories, Windows folders
// 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) {
private static String platformPath(String selector, String macDir, String winVar, String winSub, String xdgVar, String xdgDfl, String xdgSub) {
String userHome = SystemProperties.getUserHome();
if (SystemInfoRt.isMac) {
return userHome + '/' + macDir + '/' + selector;
}
if (winVar != null && SystemInfoRt.isWindows) {
if (SystemInfoRt.isWindows) {
String dir = System.getenv(winVar);
if (dir != null) {
return dir + '/' + selector;
}
if (dir == null || dir.isEmpty()) dir = userHome + "\\AppData\\" + (winVar.startsWith("LOCAL") ? "Local" : "Roaming");
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);
if (dir == null) dir = userHome + '/' + xdgDir;
return dir + '/' + selector;
if (dir == null || dir.isEmpty()) dir = userHome + '/' + xdgDfl;
dir = dir + '/' + selector;
if (!xdgSub.isEmpty()) dir = dir + '/' + xdgSub;
return dir;
}
return userHome + "/." + selector + '/' + fallback;
throw new UnsupportedOperationException("Unsupported OS: " + SystemInfoRt.OS_NAME);
}
}