public PatcherConfigurationWatcher(
     IFileSystem fileSystem,
     IPatcherCustomizationImporter customizationImporter,
     IRunnableStateProvider runnableStateProvider)
 {
     Customization = runnableStateProvider.WhenAnyValue(x => x.State)
                     .Select(x =>
     {
         if (x.RunnableState.Failed)
         {
             return(Observable.Return(default(PatcherCustomization?)));
         }
         var confPath = Path.Combine(Path.GetDirectoryName(x.Item.ProjPath) !, Constants.MetaFileName);
         return(Noggog.ObservableExt.WatchFile(confPath)
                .StartWith(Unit.Default)
                .Select(_ =>
         {
             try
             {
                 if (!fileSystem.File.Exists(confPath))
                 {
                     return default;
                 }
                 return customizationImporter.Import(confPath);
             }
             catch (Exception)
             {
                 return default(PatcherCustomization?);
             }
         }));
     })
                     .Switch()
                     .Replay(1)
                     .RefCount();
 }
예제 #2
0
        public NugetDiffProviderVm(
            IRunnableStateProvider runnableStateProvider,
            IGitNugetTargetingVm nugetTargetingVm)
        {
            var cleanState = runnableStateProvider.WhenAnyValue(x => x.State)
                             .Select(x => x.Item ?? default(RunnerRepoInfo?));

            _MutagenVersionDiff = Observable.CombineLatest(
                cleanState.Select(x => x?.ListedVersions.Mutagen),
                nugetTargetingVm.ActiveNugetVersion.Select(x => x.Value?.Mutagen.Version),
                (matchVersion, selVersion) => new NugetVersionDiff(matchVersion, selVersion))
                                  .ToGuiProperty(this, nameof(MutagenVersionDiff), new NugetVersionDiff(null, null), deferSubscription: true);

            _SynthesisVersionDiff = Observable.CombineLatest(
                cleanState.Select(x => x?.ListedVersions.Synthesis),
                nugetTargetingVm.ActiveNugetVersion.Select(x => x.Value?.Synthesis.Version),
                (matchVersion, selVersion) => new NugetVersionDiff(matchVersion, selVersion))
                                    .ToGuiProperty(this, nameof(SynthesisVersionDiff), new NugetVersionDiff(null, null), deferSubscription: true);
        }
예제 #3
0
        public GitPatcherState(
            IDriverRepositoryPreparationFollower driverRepositoryPreparation,
            IRunnerRepositoryPreparation runnerRepositoryState,
            IRunnableStateProvider runnableStateProvider,
            IPatcherRunnabilityCliState runnabilityCliState,
            IInstalledSdkFollower dotNetInstalled,
            IEnvironmentErrorsVm envErrors,
            IMissingMods missingMods,
            ILogger logger)
        {
            State = Observable.CombineLatest(
                driverRepositoryPreparation.DriverInfo
                .Select(x => x.ToUnit()),
                runnerRepositoryState.State,
                runnableStateProvider.WhenAnyValue(x => x.State)
                .Select(x => x.ToUnit()),
                runnabilityCliState.Runnable,
                dotNetInstalled.DotNetSdkInstalled
                .Select(x => (x, true))
                .StartWith((new DotNetVersion(string.Empty, false), false)),
                envErrors.WhenAnyFallback(x => x.ActiveError !.ErrorString),
                missingMods.Missing
                .QueryWhenChanged()
                .Throttle(TimeSpan.FromMilliseconds(200), RxApp.MainThreadScheduler)
                .StartWith(ListExt.Empty <ModKey>()),
                (driver, runner, checkout, runnability, dotnet, envError, reqModsMissing) =>
            {
                if (driver.IsHaltingError)
                {
                    return(driver);
                }
                if (runner.IsHaltingError)
                {
                    return(runner);
                }
                if (!dotnet.Item2)
                {
                    return(new ConfigurationState(ErrorResponse.Fail("Determining DotNet SDK installed"))
                    {
                        IsHaltingError = false
                    });
                }

                if (!dotnet.Item1.Acceptable)
                {
                    return(new ConfigurationState(ErrorResponse.Fail("No DotNet SDK installed")));
                }
                if (envError != null)
                {
                    return(new ConfigurationState(ErrorResponse.Fail(envError)));
                }

                if (reqModsMissing.Count > 0)
                {
                    return(new ConfigurationState(ErrorResponse.Fail(
                                                      $"Required mods missing from load order:{Environment.NewLine}{string.Join(Environment.NewLine, reqModsMissing)}")));
                }

                if (runnability.RunnableState.Failed)
                {
                    return(runnability.BubbleError());
                }

                if (checkout.RunnableState.Failed)
                {
                    return(checkout.BubbleError());
                }

                logger.Information("State returned success!");
                return(ConfigurationState.Success);
            })
                    .Replay(1)
                    .RefCount();
        }
예제 #4
0
        public GitStatusDisplay(
            IRunnableStateProvider runnableStateProvider,
            ICompilationProvider compilationProvider,
            IPatcherRunnabilityCliState runnabilityCliState,
            IDriverRepositoryPreparationFollower driverRepositoryPreparation)
        {
            StatusDisplay = Observable.CombineLatest(
                driverRepositoryPreparation.DriverInfo,
                runnableStateProvider.WhenAnyValue(x => x.State),
                compilationProvider.State,
                runnabilityCliState.Runnable,
                (driver, runnable, comp, runnability) =>
            {
                if (driver.RunnableState.Failed)
                {
                    if (driver.IsHaltingError)
                    {
                        return(new StatusRecord(
                                   Text: "Blocking Error",
                                   Processing: false,
                                   Blocking: true,
                                   Command: null));
                    }

                    return(new StatusRecord(
                               Text: "Analyzing repository",
                               Processing: true,
                               Blocking: false,
                               Command: null));
                }

                if (runnable.RunnableState.Failed)
                {
                    if (runnable.IsHaltingError)
                    {
                        return(new StatusRecord(
                                   Text: "Blocking Error",
                                   Processing: false,
                                   Blocking: true,
                                   Command: null));
                    }

                    return(new StatusRecord(
                               Text: "Checking out desired state",
                               Processing: true,
                               Blocking: false,
                               Command: null));
                }

                if (comp.RunnableState.Failed)
                {
                    if (comp.IsHaltingError)
                    {
                        return(new StatusRecord(
                                   Text: "Blocking Error",
                                   Processing: false,
                                   Blocking: true,
                                   Command: null));
                    }

                    return(new StatusRecord(
                               Text: "Compiling",
                               Processing: true,
                               Blocking: false,
                               Command: null));
                }

                if (runnability.RunnableState.Failed)
                {
                    if (runnability.IsHaltingError)
                    {
                        return(new StatusRecord(
                                   Text: "Blocking Error",
                                   Processing: false,
                                   Blocking: true,
                                   Command: null));
                    }

                    return(new StatusRecord(
                               Text: "Checking runnability",
                               Processing: true,
                               Blocking: false,
                               Command: null));
                }

                return(new StatusRecord(
                           Text: "Ready",
                           Processing: false,
                           Blocking: false,
                           Command: null));
            })
                            .Replay(1)
                            .RefCount();
        }
예제 #5
0
        public GitPatcherVm(
            IGithubPatcherIdentifier ident,
            IPatcherNameVm nameVm,
            IProfileDisplayControllerVm selPatcher,
            IConfirmationPanelControllerVm confirmation,
            ISelectedProjectInputVm selectedProjectInput,
            IGitRemoteRepoPathInputVm remoteRepoPathInputVm,
            INavigateTo navigate,
            IAvailableTags availableTags,
            ILockToCurrentVersioning lockToCurrentVersioning,
            IAvailableProjects availableProjects,
            ICompilationProvider compilationProvider,
            IBaseRepoDirectoryProvider baseRepoDir,
            IGitStatusDisplay gitStatusDisplay,
            IDriverRepoDirectoryProvider driverRepoDirectoryProvider,
            IRunnerRepoDirectoryProvider runnerRepoDirectoryProvider,
            IGetRepoPathValidity getRepoPathValidity,
            IRepoClonesValidStateVm repoClonesValid,
            INugetDiffProviderVm nugetDiff,
            IGitPatcherState state,
            ILogger logger,
            IRunnableStateProvider runnableStateProvider,
            ILifetimeScope scope,
            IGitPatcherTargetingVm patcherTargeting,
            ICheckoutInputProvider checkoutInputProvider,
            IGitNugetTargetingVm nugetTargetingVm,
            IUpdateAllCommand updateAllCommand,
            IAttemptedCheckout attemptedCheckout,
            IPatcherIdProvider idProvider,
            ICopyOverExtraData copyOverExtraData,
            PatcherRenameActionVm.Factory renameFactory,
            DeleteUserData deleteUserData,
            PatcherUserSettingsVm.Factory settingsVmFactory,
            GithubPatcherSettings?settings = null)
            : base(
                scope, nameVm, selPatcher,
                confirmation, idProvider, renameFactory, settings)
        {
            _logger              = logger;
            _copyOverExtraData   = copyOverExtraData;
            SelectedProjectInput = selectedProjectInput;
            RemoteRepoPathInput  = remoteRepoPathInputVm;
            Locking              = lockToCurrentVersioning;
            RepoClonesValid      = repoClonesValid;
            NugetDiff            = nugetDiff;
            PatcherTargeting     = patcherTargeting;
            NugetTargeting       = nugetTargetingVm;
            UpdateAllCommand     = updateAllCommand;

            DeleteUserDataCommand = ReactiveCommand.Create(deleteUserData.Delete);

            ID = ident.Id;

            CopyInSettings(settings);

            LocalDriverRepoDirectory = driverRepoDirectoryProvider.Path.Path;
            LocalRunnerRepoDirectory = runnerRepoDirectoryProvider.Path.Path;

            _repoValidity = getRepoPathValidity.RepoPath
                            .Select(r => r.RunnableState)
                            .ToGuiProperty(this, nameof(RepoValidity), deferSubscription: true);

            AvailableProjects = availableProjects.Projects;

            AvailableTags = availableTags.Tags;

            _attemptedCheckout = checkoutInputProvider.Input
                                 .Select(attemptedCheckout.Attempted)
                                 .ToGuiProperty(this, nameof(AttemptedCheckout), deferSubscription: true);

            _runnableData = runnableStateProvider.WhenAnyValue(x => x.State.Item)
                            .ToGuiProperty(this, nameof(RunnableData), default(RunnerRepoInfo?), deferSubscription: true);

            _state = state.State
                     .ToGuiProperty(this, nameof(State), new ConfigurationState(ErrorResponse.Fail("Evaluating"))
            {
                IsHaltingError = false
            }, deferSubscription: true);

            OpenGitPageCommand = ReactiveCommand.Create(
                canExecute: this.WhenAnyValue(x => x.RepoValidity)
                .Select(x => x.Succeeded),
                execute: () => navigate.Navigate(RemoteRepoPathInput.RemoteRepoPath));

            OpenGitPageToVersionCommand = ReactiveCommand.Create(
                canExecute: this.WhenAnyFallback(x => x.RunnableData)
                .Select(x => x != null),
                execute: () =>
            {
                try
                {
                    if (RunnableData is not {
                    } runnable)
                    {
                        return;
                    }
                    navigate.Navigate(Path.Combine(RemoteRepoPathInput.RemoteRepoPath, "tree", runnable.Target.Target));
                }
                catch (Exception ex)
                {
                    _logger.Error(ex, "Error opening Git webpage");
                }
            });

            NavigateToInternalFilesCommand = ReactiveCommand.Create(() => navigate.Navigate(baseRepoDir.Path));

            PatcherSettings = settingsVmFactory(
                false,
                compilationProvider.State.Select(c =>
            {
                if (c.RunnableState.Failed)
                {
                    return(new PatcherUserSettingsVm.Inputs(c.RunnableState.BubbleFailure <FilePath>(), null, default));
                }
                return(new PatcherUserSettingsVm.Inputs(GetResponse <FilePath> .Succeed(c.Item.ProjPath), c.Item.TargetVersions.Synthesis, c.Item.MetaPath));
            })
                .DistinctUntilChanged())
                              .DisposeWith(this);

            _statusDisplay = gitStatusDisplay.StatusDisplay
                             .ToGuiProperty(this, nameof(StatusDisplay),
                                            new StatusRecord(
                                                Text: "Initializing",
                                                Processing: false,
                                                Blocking: false,
                                                Command: null), deferSubscription: true);

            SetToLastSuccessfulRunCommand = ReactiveCommand.Create(
                canExecute: this.WhenAnyValue(x => x.LastSuccessfulRun)
                .Select(x =>
            {
                return(x != null &&
                       !x.TargetRepo.IsNullOrWhitespace() &&
                       !x.ProjectSubpath.IsNullOrWhitespace() &&
                       !x.Commit.IsNullOrWhitespace() &&
                       !x.MutagenVersion.IsNullOrWhitespace() &&
                       !x.SynthesisVersion.IsNullOrWhitespace());
            }),
                execute: () =>
            {
                if (LastSuccessfulRun == null)
                {
                    return;
                }
                RemoteRepoPathInput.RemoteRepoPath         = LastSuccessfulRun.TargetRepo;
                this.SelectedProjectInput.ProjectSubpath   = LastSuccessfulRun.ProjectSubpath;
                this.PatcherTargeting.TargetCommit         = LastSuccessfulRun.Commit;
                this.NugetTargeting.ManualMutagenVersion   = LastSuccessfulRun.MutagenVersion;
                this.NugetTargeting.ManualSynthesisVersion = LastSuccessfulRun.SynthesisVersion;
                this.PatcherTargeting.PatcherVersioning    = PatcherVersioningEnum.Commit;
                this.NugetTargeting.SynthesisVersioning    = PatcherNugetVersioningEnum.Manual;
                this.NugetTargeting.MutagenVersioning      = PatcherNugetVersioningEnum.Manual;
            });
        }
예제 #6
0
        public CompilationProvider(
            IGitPatcherCompilation build,
            ILogger logger,
            IPrintErrorMessage printErrorMessage,
            IShortCircuitSettingsProvider shortCircuitSettingsProvider,
            IRunnableStateProvider runnableStateProvider)
        {
            State = runnableStateProvider.WhenAnyValue(x => x.State)
                    .CombineLatest(
                shortCircuitSettingsProvider.WhenAnyValue(x => x.Shortcircuit),
                (state, _) => state)
                    .Select(state =>
            {
                return(Observable.Create <ConfigurationState <RunnerRepoInfo> >(async(observer, cancel) =>
                {
                    if (state.RunnableState.Failed)
                    {
                        observer.OnNext(state);
                        return;
                    }

                    try
                    {
                        logger.Information("Compiling");
                        // Return early with the values, but mark not complete
                        observer.OnNext(new ConfigurationState <RunnerRepoInfo>(state.Item)
                        {
                            IsHaltingError = false,
                            RunnableState = ErrorResponse.Fail("Compiling")
                        });

                        // Compile to help prep
                        var compileResp = await build.Compile(state.Item, cancel).ConfigureAwait(false);
                        if (compileResp.Failed)
                        {
                            logger.Information("Compiling failed: {Reason}", compileResp.Reason);
                            var errs = new List <string>();
                            printErrorMessage.Print(compileResp.Reason,
                                                    $"{Path.GetDirectoryName(state.Item.ProjPath)}\\", (s, _) =>
                            {
                                errs.Add(s.ToString());
                            });
                            observer.OnNext(
                                GetResponse <RunnerRepoInfo> .Fail(string.Join(Environment.NewLine, errs)));
                            return;
                        }

                        // Return things again, without error
                        logger.Information("Finished compiling");
                        observer.OnNext(state);
                    }
                    catch (Exception ex)
                    {
                        logger.Error(ex, "Error compiling");
                        observer.OnNext(ErrorResponse.Fail($"Error compiling: {ex}").BubbleFailure <RunnerRepoInfo>());
                    }

                    observer.OnCompleted();
                }));
            })
                    .Switch()
                    .StartWith(new ConfigurationState <RunnerRepoInfo>(
                                   GetResponse <RunnerRepoInfo> .Fail("Compilation uninitialized")))
                    .Replay(1)
                    .RefCount();
        }