1
- using Flow . Launcher . Core . Plugin ;
1
+ using Flow . Launcher . Infrastructure ;
2
2
using Flow . Launcher . Infrastructure . Logger ;
3
3
using Flow . Launcher . Infrastructure . UserSettings ;
4
4
using Flow . Launcher . Plugin ;
7
7
using System . Collections . Generic ;
8
8
using System . IO ;
9
9
using System . Linq ;
10
+ using System . Text . RegularExpressions ;
10
11
using System . Windows . Forms ;
11
12
12
13
namespace Flow . Launcher . Core . ExternalPlugins . Environments
13
14
{
14
- internal abstract class AbstractPluginEnvironment
15
+ public abstract class AbstractPluginEnvironment
15
16
{
16
17
internal abstract string Language { get ; }
17
18
@@ -31,6 +32,12 @@ internal abstract class AbstractPluginEnvironment
31
32
32
33
internal PluginsSettings PluginSettings ;
33
34
35
+ private const string updatePythonIndicatorFilename = ".updatePythonPath" ;
36
+
37
+ private const string updateNodeIndicatorFilename = ".updateNodePath" ;
38
+
39
+ private const string appDataRegex = @"app-\d\.\d\.\d" ;
40
+
34
41
internal AbstractPluginEnvironment ( List < PluginMetadata > pluginMetadataList , PluginsSettings pluginSettings )
35
42
{
36
43
PluginMetadataList = pluginMetadataList ;
@@ -149,5 +156,117 @@ private string GetFileFromDialog(string title, string filter = "")
149
156
return string . Empty ;
150
157
}
151
158
}
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
+ }
152
271
}
153
272
}
0 commit comments