From 66a665d09b070b1f72469c0bf78f623b1e2f101b Mon Sep 17 00:00:00 2001 From: Eduardo Assis Date: Tue, 12 Dec 2023 00:44:11 -0300 Subject: [PATCH] Implements append logic for env-vars Get value from shell, as this will validate if the variable is being overwritten in some place. Making the information more concise with what the user is expecting. - 'AppendToUserEnv' append to the start to give the new value the highest priority. --- .../clients/EnvironmentVariableClient.cs | 49 +++++++++---------- .../features/godot/domain/GodotRepository.cs | 17 +++++-- 2 files changed, 37 insertions(+), 29 deletions(-) diff --git a/GodotEnv/src/common/clients/EnvironmentVariableClient.cs b/GodotEnv/src/common/clients/EnvironmentVariableClient.cs index 5a1a70b..1c1d70e 100644 --- a/GodotEnv/src/common/clients/EnvironmentVariableClient.cs +++ b/GodotEnv/src/common/clients/EnvironmentVariableClient.cs @@ -70,7 +70,7 @@ public async Task AppendToUserEnv(string name, string value) { var tokens = currentValue.Split(';').ToList(); tokens = tokens.Where(t => !t.Contains(value, StringComparison.OrdinalIgnoreCase)).ToList(); - tokens.Add(value); + tokens.Insert(0, value); Environment.SetEnvironmentVariable( name, filter(tokens), EnvironmentVariableTarget.User ); @@ -79,18 +79,17 @@ public async Task AppendToUserEnv(string name, string value) { name, EnvironmentVariableTarget.User ) ?? ""; break; - // TODO: Treat case where exported var is a composite value + // In case the path assigned to variable changes, the previous one will remain in the file but with lower priority. case OSType.MacOS: var zshRcPath = FileClient.Combine(FileClient.UserDirectory, ".zshrc"); FileClient.AddLinesToFileIfNotPresent( - zshRcPath, $"export {name}=\"{value}\"" + zshRcPath, $"export {name}=\"{value}:${name}\"" ); break; case OSType.Linux: - var bashRcPath = - FileClient.Combine(FileClient.UserDirectory, ".bashrc"); + var bashRcPath = FileClient.Combine(FileClient.UserDirectory, ".bashrc"); FileClient.AddLinesToFileIfNotPresent( - bashRcPath, $"export {name}=\"{value}\"" + bashRcPath, $"export {name}=\"{value}:${name}\"" ); break; case OSType.Unknown: @@ -100,34 +99,32 @@ public async Task AppendToUserEnv(string name, string value) { } public string GetUserEnv(string name) { + var shell = Computer.CreateShell(FileClient.AppDataDirectory); + switch (FileClient.OS) { case OSType.Windows: return Environment.GetEnvironmentVariable( name, EnvironmentVariableTarget.User ) ?? ""; - case OSType.MacOS: - var zshRcPath = FileClient.Combine(FileClient.UserDirectory, ".zshrc"); - return ExtractBashEnvVarFromLine( - FileClient.FindLineBeginningWithPrefix( - zshRcPath, $"export {name}=" - ), - name - ); - case OSType.Linux: - var bashRcPath = - FileClient.Combine(FileClient.UserDirectory, ".bashrc"); - return ExtractBashEnvVarFromLine( - FileClient.FindLineBeginningWithPrefix( - bashRcPath, $"export {name}=" - ), - name - ); + // It's important to use the user's default shell to get the env-var value here. + // Note the use of the '-i' flag to initialize an interactive shell. Properly loading ''rc file. + case OSType.MacOS: { + var task = shell.Run( + "zsh", ["-ic", $"echo ${name}"] + ); + task.Wait(); + return task.Result.StandardOutput; + } + case OSType.Linux: { + var task = shell.Run( + "bash", ["-ic", $"echo ${name}"] + ); + task.Wait(); + return task.Result.StandardOutput; + } case OSType.Unknown: default: return ""; } } - - private static string ExtractBashEnvVarFromLine(string line, string name) => - line.Replace($"export {name}=", "").Replace("\"", "").Trim(); } diff --git a/GodotEnv/src/features/godot/domain/GodotRepository.cs b/GodotEnv/src/features/godot/domain/GodotRepository.cs index d740158..63eef02 100644 --- a/GodotEnv/src/features/godot/domain/GodotRepository.cs +++ b/GodotEnv/src/features/godot/domain/GodotRepository.cs @@ -149,6 +149,10 @@ public IEnvironmentVariableClient EnvironmentVariableClient { FileClient.AppDataDirectory, Defaults.GODOT_PATH, Defaults.GODOT_CACHE_PATH ); + public string GodotBinPath => FileClient.Combine( + FileClient.AppDataDirectory, Defaults.GODOT_PATH, Defaults.GODOT_BIN_PATH + ); + public string GodotSymlinkPath => FileClient.Combine( FileClient.AppDataDirectory, Defaults.GODOT_PATH, Defaults.GODOT_BIN_PATH, Defaults.GODOT_BIN_NAME ); @@ -158,7 +162,7 @@ public IEnvironmentVariableClient EnvironmentVariableClient { ); public string GodotSharpSymlinkPath => FileClient.Combine( - FileClient.AppDataDirectory, Defaults.GODOT_PATH, Defaults.GODOT_SHARP_PATH + FileClient.AppDataDirectory, Defaults.GODOT_PATH, Defaults.GODOT_BIN_PATH, Defaults.GODOT_SHARP_PATH ); public string GodotSymlinkTarget => FileClient.FileSymlinkTarget( @@ -360,6 +364,14 @@ await ZipClient.ExtractToDirectory( public async Task UpdateGodotSymlink( GodotInstallation installation, ILog log ) { + if (FileClient.IsFileSymlink(GodotBinPath)) { // Removes old 'bin' file-symlink. + await FileClient.DeleteFile(GodotBinPath); + } + + if (!FileClient.DirectoryExists(GodotBinPath)) { + FileClient.CreateDirectory(GodotBinPath); + } + // Create or update the symlink to the new version of Godot. await FileClient.CreateSymlink(GodotSymlinkPath, installation.ExecutionPath); await CreateShortcuts(installation); @@ -499,8 +511,7 @@ public async Task AddOrUpdateGodotEnvVariable(ILog log) { log.Print(""); } - public string GetGodotEnvVariable() => - EnvironmentVariableClient.GetUserEnv(Defaults.GODOT_ENV_VAR_NAME); + public string GetGodotEnvVariable() => EnvironmentVariableClient.GetUserEnv(Defaults.GODOT_ENV_VAR_NAME); public List GetInstallationsList() { var installations = new List();