Skip to content

Commit bbb7148

Browse files
committed
Add support in Linux, MacOS and refactor
1 parent 7d03376 commit bbb7148

1 file changed

Lines changed: 86 additions & 46 deletions

File tree

src/code/Utils.cs

Lines changed: 86 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
using Azure.Identity;
2323
using System.Text.RegularExpressions;
2424
using System.Threading;
25+
using System.Text.Json;
2526
using System.Threading.Tasks;
2627
using System.Xml;
2728

@@ -1157,6 +1158,42 @@ private static string GetHomeOrCreateTempHome()
11571158

11581159
private readonly static Version PSVersion6 = new Version(6, 0);
11591160

1161+
/// <summary>
1162+
/// Gets the user content directory path based on PSContentPath experimental feature settings.
1163+
/// Checks if PSContentPath is enabled and returns the appropriate path (custom, default, or legacy).
1164+
/// </summary>
1165+
private static string GetUserContentPath(PSCmdlet psCmdlet, string defaultPSContentPath, string legacyPath)
1166+
{
1167+
bool usePSContentPath = IsExperimentalFeatureEnabled(psCmdlet, "PSContentPath");
1168+
1169+
if (usePSContentPath)
1170+
{
1171+
psCmdlet.WriteVerbose("PSContentPath experimental feature is enabled");
1172+
1173+
// Check environment variable and config file for custom PSUserContentPath
1174+
string customPSUserContentPath = GetPSUserContentPath(psCmdlet);
1175+
1176+
if (!string.IsNullOrEmpty(customPSUserContentPath) && Directory.Exists(customPSUserContentPath))
1177+
{
1178+
// Use custom configured path
1179+
psCmdlet.WriteVerbose($"Using custom PSUserContentPath: {customPSUserContentPath}");
1180+
return customPSUserContentPath;
1181+
}
1182+
else
1183+
{
1184+
// Use default PSContentPath location when feature is enabled
1185+
psCmdlet.WriteVerbose($"Using default PSContentPath location: {defaultPSContentPath}");
1186+
return defaultPSContentPath;
1187+
}
1188+
}
1189+
else
1190+
{
1191+
// PSContentPath not enabled, use legacy location
1192+
psCmdlet.WriteVerbose($"Using legacy location: {legacyPath}");
1193+
return legacyPath;
1194+
}
1195+
}
1196+
11601197
/// <summary>
11611198
/// Checks if a PowerShell experimental feature is enabled by reading the PowerShell configuration file.
11621199
/// Returns false if the configuration file doesn't exist or if the feature is not enabled.
@@ -1179,18 +1216,19 @@ private static bool IsExperimentalFeatureEnabled(PSCmdlet psCmdlet, string featu
11791216
}
11801217

11811218
string jsonContent = File.ReadAllText(configPath);
1182-
var config = Newtonsoft.Json.Linq.JObject.Parse(jsonContent);
1183-
1184-
// Look for "ExperimentalFeatures": ["FeatureName"] in the config
1185-
var experimentalFeatures = config["ExperimentalFeatures"] as Newtonsoft.Json.Linq.JArray;
1186-
if (experimentalFeatures != null)
1219+
using (var jsonDoc = JsonDocument.Parse(jsonContent))
11871220
{
1188-
foreach (var feature in experimentalFeatures)
1221+
// Look for "ExperimentalFeatures": ["FeatureName"] in the config
1222+
if (jsonDoc.RootElement.TryGetProperty("ExperimentalFeatures", out var experimentalFeatures) &&
1223+
experimentalFeatures.ValueKind == JsonValueKind.Array)
11891224
{
1190-
if (string.Equals(feature.ToString(), featureName, StringComparison.OrdinalIgnoreCase))
1225+
foreach (var feature in experimentalFeatures.EnumerateArray())
11911226
{
1192-
psCmdlet.WriteVerbose(string.Format("Experimental feature '{0}' found in configuration file", featureName));
1193-
return true;
1227+
if (string.Equals(feature.GetString(), featureName, StringComparison.OrdinalIgnoreCase))
1228+
{
1229+
psCmdlet.WriteVerbose(string.Format("Experimental feature '{0}' found in configuration file", featureName));
1230+
return true;
1231+
}
11941232
}
11951233
}
11961234
}
@@ -1236,14 +1274,18 @@ private static string GetPSUserContentPath(PSCmdlet psCmdlet)
12361274
}
12371275

12381276
string jsonContent = File.ReadAllText(configPath);
1239-
var config = Newtonsoft.Json.Linq.JObject.Parse(jsonContent);
1240-
1241-
// Look for PSUserContentPath in the config
1242-
var psUserContentPath = config["PSUserContentPath"]?.ToString();
1243-
if (!string.IsNullOrEmpty(psUserContentPath))
1277+
using (var jsonDoc = JsonDocument.Parse(jsonContent))
12441278
{
1245-
psCmdlet.WriteVerbose(string.Format("Found PSUserContentPath in config file: {0}", psUserContentPath));
1246-
return psUserContentPath;
1279+
// Look for PSUserContentPath in the config
1280+
if (jsonDoc.RootElement.TryGetProperty("PSUserContentPath", out var pathElement))
1281+
{
1282+
string psUserContentPath = pathElement.GetString();
1283+
if (!string.IsNullOrEmpty(psUserContentPath))
1284+
{
1285+
psCmdlet.WriteVerbose(string.Format("Found PSUserContentPath in config file: {0}", psUserContentPath));
1286+
return psUserContentPath;
1287+
}
1288+
}
12471289
}
12481290

12491291
psCmdlet.WriteVerbose("PSUserContentPath not configured in PowerShell configuration file or environment variable");
@@ -1265,52 +1307,50 @@ private static void GetStandardPlatformPaths(
12651307
{
12661308
string powerShellType = (psCmdlet.Host.Version >= PSVersion6) ? "PowerShell" : "WindowsPowerShell";
12671309

1268-
// Check if PSContentPath experimental feature is enabled
1269-
bool usePSContentPath = IsExperimentalFeatureEnabled(psCmdlet, "PSContentPath");
1270-
1271-
if (usePSContentPath)
1310+
// Windows PowerShell doesn't support experimental features or PSContentPath
1311+
if (powerShellType == "WindowsPowerShell")
12721312
{
1273-
psCmdlet.WriteVerbose("PSContentPath experimental feature is enabled");
1274-
1275-
// Check environment variable and config file for custom PSUserContentPath
1276-
string customPSUserContentPath = GetPSUserContentPath(psCmdlet);
1277-
1278-
if (!string.IsNullOrEmpty(customPSUserContentPath) && Directory.Exists(customPSUserContentPath))
1279-
{
1280-
// Use custom configured path
1281-
localUserDir = customPSUserContentPath;
1282-
psCmdlet.WriteVerbose($"Using custom PSUserContentPath: {localUserDir}");
1283-
}
1284-
else
1285-
{
1286-
// Use default LocalApplicationData location when PSContentPath is enabled
1287-
localUserDir = Path.Combine(
1288-
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
1289-
powerShellType
1290-
);
1291-
psCmdlet.WriteVerbose($"Using default PSContentPath location: {localUserDir}");
1292-
}
1313+
// Use legacy Documents folder for Windows PowerShell
1314+
localUserDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), powerShellType);
1315+
psCmdlet.WriteVerbose($"Using Windows PowerShell Documents folder: {localUserDir}");
12931316
}
12941317
else
12951318
{
1296-
// PSContentPath not enabled, use legacy Documents folder
1297-
localUserDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), powerShellType);
1298-
psCmdlet.WriteVerbose($"Using legacy Documents folder: {localUserDir}");
1319+
string defaultPSContentPath = Path.Combine(
1320+
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
1321+
powerShellType
1322+
);
1323+
string legacyPath = Path.Combine(
1324+
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
1325+
powerShellType
1326+
);
1327+
1328+
localUserDir = GetUserContentPath(psCmdlet, defaultPSContentPath, legacyPath);
12991329
}
13001330

13011331
allUsersDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), powerShellType);
13021332
}
13031333
else
13041334
{
13051335
// paths are the same for both Linux and macOS
1306-
localUserDir = Path.Combine(GetHomeOrCreateTempHome(), ".local", "share", "powershell");
1307-
// Create the default data directory if it doesn't exist.
1336+
string xdgDataHome = Environment.GetEnvironmentVariable("XDG_DATA_HOME");
1337+
if (string.IsNullOrEmpty(xdgDataHome))
1338+
{
1339+
xdgDataHome = Path.Combine(GetHomeOrCreateTempHome(), ".local", "share");
1340+
}
1341+
1342+
string defaultPSContentPath = Path.Combine(xdgDataHome, "powershell");
1343+
string legacyPath = Path.Combine(GetHomeOrCreateTempHome(), ".local", "share", "powershell");
1344+
1345+
localUserDir = GetUserContentPath(psCmdlet, defaultPSContentPath, legacyPath);
1346+
1347+
// Create the default data directory if it doesn't exist
13081348
if (!Directory.Exists(localUserDir))
13091349
{
13101350
Directory.CreateDirectory(localUserDir);
13111351
}
13121352

1313-
allUsersDir = System.IO.Path.Combine("/usr", "local", "share", "powershell");
1353+
allUsersDir = Path.Combine("/usr", "local", "share", "powershell");
13141354
}
13151355
}
13161356

0 commit comments

Comments
 (0)