From 54c64c9db651b1be5e13c080ae355d887a203ddb Mon Sep 17 00:00:00 2001 From: v-alexjo Date: Tue, 24 May 2016 14:29:00 -0700 Subject: [PATCH] Initial XDG support and folder default changes Conflicts: src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs --- .../host/msh/ConsoleHost.cs | 15 +++--- .../Cmdlets.cs | 21 ++++++-- .../CoreCLR/CorePsPlatform.cs | 53 ++++++++++++++++++- .../engine/Modules/ModuleIntrinsics.cs | 8 +-- .../engine/Utils.cs | 4 +- .../engine/hostifaces/HostUtilities.cs | 9 +++- 6 files changed, 88 insertions(+), 22 deletions(-) diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs index 61a4012d6..8c04e0fcb 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs @@ -185,14 +185,18 @@ namespace Microsoft.PowerShell { profileDir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + @"\Microsoft\Windows\PowerShell"; - } else + } + + else { - profileDir = System.IO.Path.Combine(Environment.GetEnvironmentVariable("HOME"), ".powershell"); + //check if the user has set an XDG path in their environment variables + profileDir = Platform.SelectProductNameForDirectory("profile"); } - - if (!Directory.Exists(profileDir)) + + if (!Directory.Exists(profileDir)) //xdg value may have been set but not a valid directory { - Directory.CreateDirectory(profileDir); + Console.WriteLine("The selected directory for the profile does not exist. Using the default path."); + profileDir = Platform.SelectProductNameForDirectory("default"); } ClrFacade.SetProfileOptimizationRoot(profileDir); } @@ -268,7 +272,6 @@ namespace Microsoft.PowerShell : "StartupProfileData-NonInteractive"); exitCode = theConsoleHost.Run(cpp, !string.IsNullOrEmpty(preStartWarning)); } - } finally { diff --git a/src/Microsoft.PowerShell.PSReadLine/Cmdlets.cs b/src/Microsoft.PowerShell.PSReadLine/Cmdlets.cs index 3210a8965..fb9145314 100644 --- a/src/Microsoft.PowerShell.PSReadLine/Cmdlets.cs +++ b/src/Microsoft.PowerShell.PSReadLine/Cmdlets.cs @@ -178,14 +178,25 @@ namespace Microsoft.PowerShell } else { + //PSReadline does not have access to Utils.CorePSPlatform. Must set PSReadline path seperately + string modulepath = System.Environment.GetEnvironmentVariable("XDG_CACHE_HOME"); + + if (String.IsNullOrEmpty(modulepath)) + { + modulepath = System.IO.Path.Combine( + Environment.GetEnvironmentVariable("HOME"), + ".config/powershell/modules"); + } + HistorySavePath = System.IO.Path.Combine( Environment.GetEnvironmentVariable("HOME"), - ".powershell", + modulepath, "PSReadLine", hostName + "_history.txt"); - } -#else - HistorySavePath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + + } + #else + HistorySavePath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\Microsoft\Windows\PowerShell\PSReadline\" + hostName + "_history.txt"; #endif CommandValidationHandler = null; @@ -205,7 +216,7 @@ namespace Microsoft.PowerShell "Where-Object", "?", "where", }; } - + public EditMode EditMode { get; set; } public string ContinuationPrompt { get; set; } diff --git a/src/System.Management.Automation/CoreCLR/CorePsPlatform.cs b/src/System.Management.Automation/CoreCLR/CorePsPlatform.cs index 34623fc1b..9e2d40541 100644 --- a/src/System.Management.Automation/CoreCLR/CorePsPlatform.cs +++ b/src/System.Management.Automation/CoreCLR/CorePsPlatform.cs @@ -96,8 +96,57 @@ namespace System.Management.Automation "WSMan.format.ps1xml" }; - // directory location of PowerShell for profile loading - public static string ProductNameForDirectory = ".powershell"; + // function for choosing directory location of PowerShell for profile loading + public static string SelectProductNameForDirectory (string dir){ + + string xdgconfighome = System.Environment.GetEnvironmentVariable("XDG_CONFIG_HOME"); + string xdgdatahome = System.Environment.GetEnvironmentVariable("XDG_DATA_HOME"); + string xdgcachehome = System.Environment.GetEnvironmentVariable("XDG_CACHE_HOME"); + + + //the user has set XDG_CONFIG_HOME corrresponding to profile path + if (!String.IsNullOrEmpty(xdgconfighome) && dir == "profile") + { + return xdgconfighome; + } + + //the user has set XDG_DATA_HOME corresponding to module path + if (!String.IsNullOrEmpty(xdgdatahome) && dir == "modules") + { + return xdgdatahome; + } + + //the user has set XDG_CACHE_HOME + if (!String.IsNullOrEmpty(xdgcachehome) && dir == "history") + { + return xdgcachehome; + } + + if (dir == "default") + { + return @".config/powershell"; + } + //the user has set XDG_DATA_HOME + else //xdg values have not been set + { + if (dir == "profile" || dir == "history") + { + return @".config/powershell"; //default on Linux + } + if (dir == "modules") + { + if (!Directory.Exists(@".config/powershell/modules")) + { + Directory.CreateDirectory(@".config/powershell/modules"); + + } + + return @".config/powershell/modules"; //default on Linux + } + + return @".config/powershell"; + } + } // ComObjectType is null on CoreCLR for Linux since there is // no COM support on Linux diff --git a/src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs b/src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs index 129fd8db5..46bd51a21 100644 --- a/src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs +++ b/src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs @@ -548,12 +548,7 @@ namespace System.Management.Automation /// personal module path internal static string GetPersonalModulePath() { - string personalModuleRoot = Path.Combine( - Path.Combine( - Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), - Utils.ProductNameForDirectory), - Utils.ModuleDirectory); - + string personalModuleRoot = Platform.SelectProductNameForDirectory("modules"); return personalModuleRoot; } @@ -597,6 +592,7 @@ namespace System.Management.Automation psHome = psHome.ToLowerInvariant().Replace("\\syswow64\\", "\\system32\\"); } Interlocked.CompareExchange(ref SystemWideModulePath, Path.Combine(psHome, Utils.ModuleDirectory), null); + } return SystemWideModulePath; diff --git a/src/System.Management.Automation/engine/Utils.cs b/src/System.Management.Automation/engine/Utils.cs index 8c4f55e7d..3e6857d1b 100644 --- a/src/System.Management.Automation/engine/Utils.cs +++ b/src/System.Management.Automation/engine/Utils.cs @@ -606,13 +606,13 @@ namespace System.Management.Automation /// Profile uses this to control profile loading. /// internal static string ProductNameForDirectory = - Platform.IsWindows ? "WindowsPowerShell" : Platform.ProductNameForDirectory; + Platform.IsWindows ? "WindowsPowerShell" : Platform.SelectProductNameForDirectory("profile"); /// /// The name of the subdirectory that contains packages. /// internal static string ModuleDirectory = "Modules"; - + /// /// The partial path to the DSC module directory /// diff --git a/src/System.Management.Automation/engine/hostifaces/HostUtilities.cs b/src/System.Management.Automation/engine/hostifaces/HostUtilities.cs index 8783240ec..aef980161 100644 --- a/src/System.Management.Automation/engine/hostifaces/HostUtilities.cs +++ b/src/System.Management.Automation/engine/hostifaces/HostUtilities.cs @@ -152,6 +152,7 @@ namespace System.Management.Automation { continue; } + command = new PSCommand(); command.AddCommand(profilePath, false); commands.Add(command); @@ -186,7 +187,14 @@ namespace System.Management.Automation { basePath = Environment.GetFolderPath(Environment.SpecialFolder.Personal); basePath = IO.Path.Combine(basePath, Utils.ProductNameForDirectory); + + //If the profile path doesn't exist, create it. + if (!System.IO.Directory.Exists(basePath)) + { + System.IO.Directory.CreateDirectory(basePath); + } } + else { basePath = GetAllUsersFolderPath(shellId); @@ -198,7 +206,6 @@ namespace System.Management.Automation string profileName = useTestProfile ? "profile_test.ps1" : "profile.ps1"; - if (!string.IsNullOrEmpty(shellId)) { profileName = shellId + "_" + profileName;