Example #1
0
 public BackupDir(VirtualFileSystemPath oldDir, string backupFolderPrefix)
 {
     myOldDir    = oldDir;
     myBackupDir = VirtualFileSystemDefinition.CreateTemporaryDirectory(InteractionContext.SolutionContext, null, backupFolderPrefix);
     myOldDir.CopyDirectory(myBackupDir);
     myOldDir.Delete();
 }
        private void InstallPluginInGame(Lifetime lifetime, UnrealPluginInstallInfo unrealPluginInstallInfo,
                                         Property <double> progress)
        {
            myLogger.Verbose("[UnrealLink]: Installing plugin in Game");
            var backupDir = VirtualFileSystemDefinition.CreateTemporaryDirectory(InteractionContext.SolutionContext, null, TMP_PREFIX);

            using var deleteTempFolders = new DeleteTempFolders(backupDir.Directory);

            var backupAllPlugins = BackupAllPlugins(unrealPluginInstallInfo);
            var success          = true;
            var size             = unrealPluginInstallInfo.ProjectPlugins.Count;
            var range            = 1.0 / size;

            for (int i = 0; i < unrealPluginInstallInfo.ProjectPlugins.Count; i++)
            {
                progress.Value = range * i;
                var installDescription = unrealPluginInstallInfo.ProjectPlugins[i];
                myLogger.Verbose($"[UnrealLink]: Installing plugin for {installDescription.ProjectName}");
                try
                {
                    if (InstallPlugin(lifetime, installDescription, unrealPluginInstallInfo.EngineRoot, progress,
                                      range))
                    {
                        continue;
                    }
                }
                catch (OperationCanceledException)
                {
                    // Operation was cancelled, don't need to do anything, fallback to break case
                }

                success = false;
                break;
            }

            if (success)
            {
                unrealPluginInstallInfo.EnginePlugin.IsPluginAvailable = false;
            }
            else
            {
                foreach (var backupAllPlugin in backupAllPlugins)
                {
                    backupAllPlugin.Restore();
                }
            }

            myUnrealHost.myModel.InstallPluginFinished(success);
        }
        private void InstallPluginInEngine(Lifetime lifetime, UnrealPluginInstallInfo unrealPluginInstallInfo,
                                           IProperty <double> progress)
        {
            var backupDir = VirtualFileSystemDefinition.CreateTemporaryDirectory(InteractionContext.SolutionContext, null, TMP_PREFIX);

            using var deleteTempFolders = new DeleteTempFolders(backupDir.Directory);

            var backupAllPlugins = BackupAllPlugins(unrealPluginInstallInfo);

            progress.Value = 0.0;
            bool success;

            try
            {
                success = InstallPlugin(lifetime, unrealPluginInstallInfo.EnginePlugin,
                                        unrealPluginInstallInfo.EngineRoot, progress, 1.0);
            }
            catch (OperationCanceledException)
            {
                success = false;
            }

            if (!success)
            {
                foreach (var backupAllPlugin in backupAllPlugins)
                {
                    backupAllPlugin.Restore();
                }
            }
            else
            {
                foreach (var installDescription in unrealPluginInstallInfo.ProjectPlugins)
                {
                    installDescription.IsPluginAvailable = false;
                }
            }

            myUnrealHost.myModel.InstallPluginFinished(success);
        }
        private bool InstallPlugin(Lifetime lifetime,
                                   UnrealPluginInstallInfo.InstallDescription installDescription,
                                   VirtualFileSystemPath engineRoot, IProperty <double> progressProperty, double range)
        {
            using var def = new LifetimeDefinition();
            var ZIP_STEP   = 0.1 * range;
            var PATCH_STEP = 0.1 * range;
            var BUILD_STEP = 0.7 * range;

            var pluginRootFolder = installDescription.UnrealPluginRootFolder;

            var editorPluginPathFile = myPathsProvider.PathToPackedPlugin;
            var pluginTmpDir         = VirtualFileSystemDefinition.CreateTemporaryDirectory(InteractionContext.SolutionContext, null, TMP_PREFIX);

            def.Lifetime.OnTermination(() => { pluginTmpDir.Delete(); });
            try
            {
                ZipFile.ExtractToDirectory(editorPluginPathFile.FullPath, pluginTmpDir.FullPath);
                progressProperty.Value += ZIP_STEP;
            }
            catch (Exception exception)
            {
                myLogger.Warn(exception, $"[UnrealLink]: Couldn't extract {editorPluginPathFile} to {pluginTmpDir}");

                const string unzipFailTitle = "Failed to unzip new RiderLink plugin";
                var          unzipFailText  =
                    $"Failed to unzip new version of RiderLink ({editorPluginPathFile.FullPath}) to user folder ({pluginTmpDir.FullPath})\n" +
                    "Try restarting Rider in administrative mode";

                myUnrealHost.myModel.RiderLinkInstallMessage(new InstallMessage(unzipFailTitle, ContentType.Error));
                myUnrealHost.myModel.RiderLinkInstallMessage(new InstallMessage(unzipFailText, ContentType.Error));
                return(false);
            }

            lifetime.ToCancellationToken().ThrowIfCancellationRequested();

            var upluginFile       = UnrealPluginDetector.GetPathToUpluginFile(pluginTmpDir);
            var pluginBuildOutput = VirtualFileSystemDefinition.CreateTemporaryDirectory(InteractionContext.SolutionContext, null, TMP_PREFIX);

            def.Lifetime.OnTermination(() => { pluginBuildOutput.Delete(); });
            var buildProgress = progressProperty.Value;
            var isPluginBuilt = BuildPlugin(lifetime, upluginFile, pluginBuildOutput,
                                            engineRoot, value => progressProperty.SetValue(buildProgress + value * BUILD_STEP));

            if (!isPluginBuilt)
            {
                myLogger.Warn($"Failed to build RiderLink for any available project");
                const string failedBuildText = "Failed to build RiderLink plugin";
                myUnrealHost.myModel.RiderLinkInstallMessage(new InstallMessage(failedBuildText, ContentType.Error));
                return(false);
            }

            progressProperty.Value = buildProgress + BUILD_STEP;

            lifetime.ToCancellationToken().ThrowIfCancellationRequested();

            if (!PatchUpluginFileAfterInstallation(pluginBuildOutput))
            {
                const string failedToPatch   = "Failed to patch RiderLink.uplugin";
                var          failedPatchText = "Failed to set `EnableByDefault` to true in RiderLink.uplugin\n" +
                                               "You need to manually enable RiderLink in UnrealEditor";
                myUnrealHost.myModel.RiderLinkInstallMessage(new InstallMessage(failedToPatch, ContentType.Normal));
                myUnrealHost.myModel.RiderLinkInstallMessage(new InstallMessage(failedPatchText, ContentType.Normal));
            }

            progressProperty.Value += PATCH_STEP;

            lifetime.ToCancellationToken().ThrowIfCancellationRequested();

            pluginRootFolder.CreateDirectory().DeleteChildren();
            pluginBuildOutput.Copy(pluginRootFolder);

            installDescription.IsPluginAvailable = true;
            installDescription.PluginVersion     = myPathsProvider.CurrentPluginVersion;

            const string title = "RiderLink plugin installed";
            var          text  = $"RiderLink plugin was installed to: {pluginRootFolder}";

            myUnrealHost.myModel.RiderLinkInstallMessage(new InstallMessage(title, ContentType.Normal));
            myUnrealHost.myModel.RiderLinkInstallMessage(new InstallMessage(text, ContentType.Normal));

            var notification = new NotificationModel(title, text, true, RdNotificationEntryType.INFO,
                                                     new List <NotificationHyperlink>());

            mySolution.Locks.ExecuteOrQueue(Lifetime, "UnrealLink.InstallPlugin",
                                            () => { myNotificationsModel.Notification(notification); });

            var  cppUe4SolutionDetector = mySolution.GetComponent <CppUE4SolutionDetector>();
            bool isSln;

            using (mySolution.Locks.UsingReadLock())
            {
                isSln = cppUe4SolutionDetector.SupportRiderProjectModel != CppUE4ProjectModelSupportMode.UprojectOpened;
            }

            if (isSln)
            {
                mySolution.Locks.ExecuteOrQueue(Lifetime, "Refresh projects after RiderLink installation", () =>
                                                UnrealProjectsRefresher.RefreshProjects(Lifetime, mySolution, installDescription, engineRoot));
            }
            else
            {
                var actionTitle = "Update VirtualFileSystem after RiderLink installation";
                mySolution.Locks.Queue(Lifetime, actionTitle, () =>
                {
                    myLogger.Verbose(actionTitle);
                    var fileSystemModel = mySolution.GetProtocolSolution().GetFileSystemModel();
                    fileSystemModel.RefreshPaths.Start(lifetime,
                                                       new RdFsRefreshRequest(new List <string>()
                    {
                        pluginRootFolder.FullPath
                    }, true));
                });
            }
            return(true);
        }