Skip to content

Commit 5975b6e

Browse files
committed
plugin env paths correction after update or mode change
1 parent d297779 commit 5975b6e

File tree

6 files changed

+133
-61
lines changed

6 files changed

+133
-61
lines changed

Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs

Lines changed: 121 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using Flow.Launcher.Core.Plugin;
1+
using Flow.Launcher.Infrastructure;
22
using Flow.Launcher.Infrastructure.Logger;
33
using Flow.Launcher.Infrastructure.UserSettings;
44
using Flow.Launcher.Plugin;
@@ -7,11 +7,12 @@
77
using System.Collections.Generic;
88
using System.IO;
99
using System.Linq;
10+
using System.Text.RegularExpressions;
1011
using System.Windows.Forms;
1112

1213
namespace Flow.Launcher.Core.ExternalPlugins.Environments
1314
{
14-
internal abstract class AbstractPluginEnvironment
15+
public abstract class AbstractPluginEnvironment
1516
{
1617
internal abstract string Language { get; }
1718

@@ -31,6 +32,12 @@ internal abstract class AbstractPluginEnvironment
3132

3233
internal PluginsSettings PluginSettings;
3334

35+
private const string updatePythonIndicatorFilename = ".updatePythonPath";
36+
37+
private const string updateNodeIndicatorFilename = ".updateNodePath";
38+
39+
private const string appDataRegex = @"app-\d\.\d\.\d";
40+
3441
internal AbstractPluginEnvironment(List<PluginMetadata> pluginMetadataList, PluginsSettings pluginSettings)
3542
{
3643
PluginMetadataList = pluginMetadataList;
@@ -149,5 +156,117 @@ private string GetFileFromDialog(string title, string filter = "")
149156
return string.Empty;
150157
}
151158
}
159+
160+
public static void IndicatePluginEnvPathsUpdate(Settings settings, string newVer)
161+
{
162+
var appVer = $"app-{newVer}";
163+
var updatePythonIndicatorFilePath
164+
= Regex.Replace(Path.Combine(DataLocation.PluginEnvironments, updatePythonIndicatorFilename), appDataRegex, appVer);
165+
var updateNodeIndicatorFilePath
166+
= Regex.Replace(Path.Combine(DataLocation.PluginEnvironments, updateNodeIndicatorFilename), appDataRegex, appVer);
167+
168+
if (!string.IsNullOrEmpty(settings.PluginSettings.PythonExecutablePath)
169+
&& settings.PluginSettings.PythonExecutablePath.StartsWith(DataLocation.PluginEnvironments))
170+
using (var _ = File.CreateText(updatePythonIndicatorFilePath)) { }
171+
172+
if (!string.IsNullOrEmpty(settings.PluginSettings.NodeExecutablePath)
173+
&& settings.PluginSettings.NodeExecutablePath.StartsWith(DataLocation.PluginEnvironments))
174+
using (var _ = File.CreateText(updateNodeIndicatorFilePath)) { }
175+
}
176+
177+
public static void PreStartPluginFilePathCorrection(Settings settings)
178+
{
179+
PreStartCorrectionAfterUpdate(settings);
180+
PreStartCorrectionAfterModeChange(settings);
181+
}
182+
183+
private static void PreStartCorrectionAfterUpdate(Settings settings)
184+
{
185+
// After updating flow, update plugin env paths.
186+
var appVer = $"app-{Constant.Version}";
187+
var updatePythonIndicatorFilePath = Path.Combine(DataLocation.PluginEnvironments, updatePythonIndicatorFilename);
188+
var updateNodeIndicatorFilePath = Path.Combine(DataLocation.PluginEnvironments, updateNodeIndicatorFilename);
189+
190+
if (File.Exists(updatePythonIndicatorFilePath))
191+
{
192+
settings.PluginSettings.PythonExecutablePath
193+
= Regex.Replace(settings.PluginSettings.PythonExecutablePath, appDataRegex, appVer);
194+
195+
File.Delete(updatePythonIndicatorFilePath);
196+
}
197+
198+
if (File.Exists(updateNodeIndicatorFilePath))
199+
{
200+
settings.PluginSettings.NodeExecutablePath
201+
= Regex.Replace(settings.PluginSettings.NodeExecutablePath, appDataRegex, appVer);
202+
203+
File.Delete(updateNodeIndicatorFilePath);
204+
}
205+
}
206+
207+
private static void PreStartCorrectionAfterModeChange(Settings settings)
208+
{
209+
// After enabling/disabling portable mode, update plugin env paths.
210+
if (DataLocation.PortableDataLocationInUse())
211+
{
212+
// When user is using portable but has moved flow to a different location
213+
if (IsUsingPortablePath(settings.PluginSettings.PythonExecutablePath, DataLocation.PythonEnvironmentName)
214+
&& !settings.PluginSettings.PythonExecutablePath.StartsWith(DataLocation.PortableDataPath))
215+
{
216+
settings.PluginSettings.PythonExecutablePath
217+
= GetUpdatedPortablePath(settings.PluginSettings.PythonExecutablePath, DataLocation.PythonEnvironmentName);
218+
}
219+
220+
if (IsUsingPortablePath(settings.PluginSettings.NodeExecutablePath, DataLocation.NodeEnvironmentName)
221+
&& !settings.PluginSettings.NodeExecutablePath.StartsWith(DataLocation.PortableDataPath))
222+
{
223+
settings.PluginSettings.NodeExecutablePath
224+
= GetUpdatedPortablePath(settings.PluginSettings.NodeExecutablePath, DataLocation.NodeEnvironmentName);
225+
}
226+
227+
// When user has switched from roaming to portable
228+
if (IsUsingRoamingPath(settings.PluginSettings.PythonExecutablePath))
229+
{
230+
settings.PluginSettings.PythonExecutablePath
231+
= settings.PluginSettings.PythonExecutablePath.Replace(DataLocation.RoamingDataPath, DataLocation.PortableDataPath);
232+
}
233+
234+
if (IsUsingRoamingPath(settings.PluginSettings.NodeExecutablePath))
235+
{
236+
settings.PluginSettings.NodeExecutablePath
237+
= settings.PluginSettings.NodeExecutablePath.Replace(DataLocation.RoamingDataPath, DataLocation.PortableDataPath);
238+
}
239+
}
240+
else
241+
{
242+
if (IsUsingPortablePath(settings.PluginSettings.PythonExecutablePath, DataLocation.PythonEnvironmentName))
243+
settings.PluginSettings.PythonExecutablePath
244+
= GetUpdatedPortablePath(settings.PluginSettings.PythonExecutablePath, DataLocation.PythonEnvironmentName);
245+
246+
if (IsUsingPortablePath(settings.PluginSettings.NodeExecutablePath, DataLocation.NodeEnvironmentName))
247+
settings.PluginSettings.NodeExecutablePath
248+
= GetUpdatedPortablePath(settings.PluginSettings.NodeExecutablePath, DataLocation.NodeEnvironmentName);
249+
}
250+
}
251+
252+
private static bool IsUsingPortablePath(string filePath, string pluginEnvironmentName)
253+
{
254+
var portableAppEnvLocation = $"UserData\\{DataLocation.PluginEnvironments}\\{pluginEnvironmentName}";
255+
256+
return filePath.Contains(portableAppEnvLocation);
257+
}
258+
259+
private static bool IsUsingRoamingPath(string filePath)
260+
{
261+
return filePath.StartsWith(DataLocation.RoamingDataPath);
262+
}
263+
264+
private static string GetUpdatedPortablePath(string filePath, string pluginEnvironmentName)
265+
{
266+
var index = filePath.IndexOf(DataLocation.PluginEnvironments);
267+
// get the substring after "Environments" because we can not determine it
268+
var updatedPath = filePath.Substring(index + DataLocation.PluginEnvironments.Count());
269+
return $"{DataLocation.PluginEnvironmentsPath}{updatedPath}";
270+
}
152271
}
153272
}

Flow.Launcher.Core/ExternalPlugins/Environments/PythonEnvironment.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ internal class PythonEnvironment : AbstractPluginEnvironment
1212
{
1313
internal override string Language => AllowedLanguage.Python;
1414

15-
internal override string EnvName => "Python";
15+
internal override string EnvName => DataLocation.PythonEnvironmentName;
1616

17-
internal override string EnvPath => Path.Combine(DataLocation.PluginEnvironments, EnvName);
17+
internal override string EnvPath => Path.Combine(DataLocation.PluginEnvironmentsPath, EnvName);
1818

1919
internal override string InstallPath => Path.Combine(EnvPath, "PythonEmbeddable-v3.8.9");
2020

Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptEnvironment.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ internal class TypeScriptEnvironment : AbstractPluginEnvironment
1212
{
1313
internal override string Language => AllowedLanguage.TypeScript;
1414

15-
internal override string EnvName => "Node.js";
15+
internal override string EnvName => DataLocation.NodeEnvironmentName;
1616

17-
internal override string EnvPath => Path.Combine(DataLocation.PluginEnvironments, EnvName);
17+
internal override string EnvPath => Path.Combine(DataLocation.PluginEnvironmentsPath, EnvName);
1818

1919
internal override string InstallPath => Path.Combine(EnvPath, "Node-v16.18.0");
2020
internal override string ExecutablePath => Path.Combine(InstallPath, "node-v16.18.0-win-x64\\node.exe");

Flow.Launcher.Core/Updater.cs

Lines changed: 2 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -17,21 +17,14 @@
1717
using Flow.Launcher.Plugin;
1818
using System.Text.Json.Serialization;
1919
using System.Threading;
20-
using System.IO;
21-
using System.Text.RegularExpressions;
20+
using Flow.Launcher.Core.ExternalPlugins.Environments;
2221

2322
namespace Flow.Launcher.Core
2423
{
2524
public class Updater
2625
{
2726
public string GitHubRepository { get; }
2827

29-
private string updatePythonIndicatorFilename = ".updatePythonPath";
30-
31-
private string updateNodeIndicatorFilename = ".updateNodePath";
32-
33-
private string appDataRegex = @"app-\d\.\d\.\d";
34-
3528
public Updater(string gitHubRepository)
3629
{
3730
GitHubRepository = gitHubRepository;
@@ -82,7 +75,7 @@ public async Task UpdateAppAsync(IPublicAPI api, Settings settings, bool silentU
8275
DataLocation.PortableDataPath,
8376
targetDestination));
8477

85-
UpdatePluginEnvPaths(settings, newReleaseVersion.ToString());
78+
AbstractPluginEnvironment.IndicatePluginEnvPathsUpdate(settings, newReleaseVersion.ToString());
8679
}
8780
else
8881
{
@@ -154,45 +147,5 @@ public string NewVersionTips(string version)
154147

155148
return tips;
156149
}
157-
158-
private void UpdatePluginEnvPaths(Settings settings, string newVer)
159-
{
160-
var appVer = $"app-{newVer}";
161-
var updatePythonIndicatorFilePath
162-
= Regex.Replace(Path.Combine(DataLocation.PluginEnvironments, updatePythonIndicatorFilename), appDataRegex, appVer);
163-
var updateNodeIndicatorFilePath
164-
= Regex.Replace(Path.Combine(DataLocation.PluginEnvironments, updateNodeIndicatorFilename), appDataRegex, appVer);
165-
166-
if (!string.IsNullOrEmpty(settings.PluginSettings.PythonExecutablePath)
167-
&& settings.PluginSettings.PythonExecutablePath.StartsWith(DataLocation.PluginEnvironments))
168-
using (var _ = File.CreateText(updatePythonIndicatorFilePath)){}
169-
170-
if (!string.IsNullOrEmpty(settings.PluginSettings.NodeExecutablePath)
171-
&& settings.PluginSettings.NodeExecutablePath.StartsWith(DataLocation.PluginEnvironments))
172-
using (var _ = File.CreateText(updateNodeIndicatorFilePath)) { }
173-
}
174-
175-
public void PreStartSetupAfterAppUpdate(Settings settings)
176-
{
177-
var appVer = $"app-{Constant.Version}";
178-
var updatePythonIndicatorFilePath = Path.Combine(DataLocation.PluginEnvironments, updatePythonIndicatorFilename);
179-
var updateNodeIndicatorFilePath = Path.Combine(DataLocation.PluginEnvironments, updateNodeIndicatorFilename);
180-
181-
if (File.Exists(updatePythonIndicatorFilePath))
182-
{
183-
settings.PluginSettings.PythonExecutablePath
184-
= Regex.Replace(settings.PluginSettings.PythonExecutablePath, appDataRegex, appVer);
185-
186-
File.Delete(updatePythonIndicatorFilePath);
187-
}
188-
189-
if (File.Exists(updateNodeIndicatorFilePath))
190-
{
191-
settings.PluginSettings.NodeExecutablePath
192-
= Regex.Replace(settings.PluginSettings.NodeExecutablePath, appDataRegex, appVer);
193-
194-
File.Delete(updateNodeIndicatorFilePath);
195-
}
196-
}
197150
}
198151
}

Flow.Launcher.Infrastructure/UserSettings/DataLocation.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
using System;
2-
using System.Collections.Generic;
32
using System.IO;
4-
using System.Linq;
5-
using System.Text;
6-
using System.Threading.Tasks;
73

84
namespace Flow.Launcher.Infrastructure.UserSettings
95
{
@@ -32,6 +28,9 @@ public static bool PortableDataLocationInUse()
3228
public static readonly string PluginsDirectory = Path.Combine(DataDirectory(), Constant.Plugins);
3329
public static readonly string PluginSettingsDirectory = Path.Combine(DataDirectory(), "Settings", Constant.Plugins);
3430

35-
public static readonly string PluginEnvironments = Path.Combine(DataDirectory(), "Environments");
31+
public const string PythonEnvironmentName = "Python";
32+
public const string NodeEnvironmentName = "Node.js";
33+
public const string PluginEnvironments = "Environments";
34+
public static readonly string PluginEnvironmentsPath = Path.Combine(DataDirectory(), PluginEnvironments);
3635
}
3736
}

Flow.Launcher/App.xaml.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Windows;
77
using Flow.Launcher.Core;
88
using Flow.Launcher.Core.Configuration;
9+
using Flow.Launcher.Core.ExternalPlugins.Environments;
910
using Flow.Launcher.Core.Plugin;
1011
using Flow.Launcher.Core.Resource;
1112
using Flow.Launcher.Helper;
@@ -61,7 +62,7 @@ await Stopwatch.NormalAsync("|App.OnStartup|Startup cost", async () =>
6162
_settingsVM = new SettingWindowViewModel(_updater, _portable);
6263
_settings = _settingsVM.Settings;
6364

64-
_updater.PreStartSetupAfterAppUpdate(_settings);
65+
AbstractPluginEnvironment.PreStartPluginFilePathCorrection(_settings);
6566

6667
_alphabet.Initialize(_settings);
6768
_stringMatcher = new StringMatcher(_alphabet);

0 commit comments

Comments
 (0)