コード例 #1
0
ファイル: ProfileVm.cs プロジェクト: sharpsteve/Synthesis
        public ProfileVm(
            ILifetimeScope scope,
            IPatcherInitializationVm initVm,
            IProfileDataFolderVm dataFolder,
            IProfileIdentifier ident,
            IProfileNameVm nameProvider,
            IProfileLoadOrder loadOrder,
            IProfileDirectories dirs,
            IProfileVersioning versioning,
            IProfileDisplayControllerVm profileDisplay,
            ILockToCurrentVersioning lockSetting,
            ISelectedProfileControllerVm selProfile,
            IProfileExporter exporter,
            IProfileGroupsList groupsList,
            IEnvironmentErrorsVm environmentErrors,
            OverallErrorVm overallErrorVm,
            StartRun startRun,
            ILogger logger)
        {
            Scope              = scope;
            Init               = initVm;
            OverallErrorVm     = overallErrorVm;
            NameVm             = nameProvider;
            Groups             = groupsList.Groups;
            DataFolderOverride = dataFolder;
            Versioning         = versioning;
            LockSetting        = lockSetting;
            Exporter           = exporter;
            DisplayController  = profileDisplay;
            _startRun          = startRun;
            _logger            = logger;
            ID      = ident.ID;
            Release = ident.Release;

            GroupsDisplay = new SourceListUiFunnel <GroupVm>(Groups, this);

            ProfileDirectory = dirs.ProfileDirectory;
            WorkingDirectory = dirs.WorkingDirectory;

            EnvironmentErrors = environmentErrors;

            _dataFolder = dataFolder.WhenAnyValue(x => x.Path)
                          .ToGuiProperty <DirectoryPath>(this, nameof(DataFolder), string.Empty, deferSubscription: true);

            LoadOrder = loadOrder.LoadOrder;

            var enabledGroups = Groups.Connect()
                                .ObserveOnGui()
                                .FilterOnObservable(p => p.WhenAnyValue(x => x.IsOn), scheduler: RxApp.MainThreadScheduler)
                                .RefCount();

            var enabledGroupModKeys = enabledGroups
                                      .Transform(x => x.ModKey)
                                      .QueryWhenChanged(q => q.ToHashSet())
                                      .Replay(1).RefCount();

            _blockingError = Observable.CombineLatest(
                dataFolder.WhenAnyValue(x => x.DataFolderResult),
                loadOrder.WhenAnyValue(x => x.State),
                enabledGroups
                .QueryWhenChanged(q => q)
                .StartWith(Noggog.ListExt.Empty <GroupVm>()),
                enabledGroups
                .FilterOnObservable(g => g.WhenAnyValue(x => x.State).Select(x => x.IsHaltingError))
                .QueryWhenChanged(q => q)
                .StartWith(Noggog.ListExt.Empty <GroupVm>()),
                LoadOrder.Connect()
                .FilterOnObservable(
                    x =>
            {
                return(Observable.CombineLatest(
                           x.WhenAnyValue(y => y.Exists)
                           .DistinctUntilChanged(),
                           enabledGroupModKeys
                           .Select(groupModKeys => groupModKeys.Contains(x.ModKey)),
                           (exists, isEnabledGroupKey) => !exists && !isEnabledGroupKey));
            },
                    scheduler: RxApp.MainThreadScheduler)
                .QueryWhenChanged(q => q)
                .StartWith(Noggog.ListExt.Empty <ReadOnlyModListingVM>())
                .Throttle(TimeSpan.FromMilliseconds(200), RxApp.MainThreadScheduler),
                this.WhenAnyValue(x => x.IgnoreMissingMods),
                (dataFolder, loadOrder, enabledGroups, erroredEnabledGroups, missingMods, ignoreMissingMods) =>
            {
                if (enabledGroups.Count == 0)
                {
                    return(GetResponse <ViewModel> .Fail("There are no enabled groups to run."));
                }
                if (!dataFolder.Succeeded)
                {
                    return(dataFolder.BubbleFailure <ViewModel>());
                }
                if (!loadOrder.Succeeded)
                {
                    return(loadOrder.BubbleFailure <ViewModel>());
                }
                if (!ignoreMissingMods && missingMods.Count > 0)
                {
                    return(GetResponse <ViewModel> .Fail($"Load order had mods that were missing:{Environment.NewLine}{string.Join(Environment.NewLine, missingMods.Select(x => x.ModKey))}"));
                }
                if (erroredEnabledGroups.Count > 0)
                {
                    var errGroup = erroredEnabledGroups.First();
                    return(GetResponse <ViewModel> .Fail(errGroup, $"\"{errGroup.Name}\" has a blocking error: {errGroup.State}"));
                }
                return(GetResponse <ViewModel> .Succeed(null !));
            })
コード例 #2
0
ファイル: GitPatcherVm.cs プロジェクト: sharpsteve/Synthesis
        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;
            });
        }
コード例 #3
0
        public GitPatcherTargetingVm(
            ILockToCurrentVersioning lockToCurrentVersioning,
            IDriverRepositoryPreparationFollower driverRepositoryPreparation)
        {
            var targetOriginBranchName = this.WhenAnyValue(x => x.TargetBranchName)
                                         .Select(x => $"origin/{x}")
                                         .Replay(1).RefCount();

            // Set latest checkboxes to drive user input
            driverRepositoryPreparation.DriverInfo
            .FlowSwitch(this.WhenAnyValue(x => x.BranchFollowMain))
            .Throttle(TimeSpan.FromMilliseconds(150), RxApp.MainThreadScheduler)
            .Subscribe(state =>
            {
                if (state.RunnableState.Succeeded)
                {
                    this.TargetBranchName = state.Item.MasterBranchName;
                }
            })
            .DisposeWith(this);

            Observable.CombineLatest(
                driverRepositoryPreparation.DriverInfo,
                targetOriginBranchName,
                (Driver, TargetBranch) => (Driver, TargetBranch))
            .FlowSwitch(
                Observable.CombineLatest(
                    this.WhenAnyValue(x => x.BranchAutoUpdate),
                    this.WhenAnyValue(x => x.PatcherVersioning),
                    (autoBranch, versioning) => autoBranch && versioning == PatcherVersioningEnum.Branch))
            .Throttle(TimeSpan.FromMilliseconds(150), RxApp.MainThreadScheduler)
            .Subscribe(x =>
            {
                if (x.Driver.RunnableState.Succeeded &&
                    x.Driver.Item.BranchShas.TryGetValue(x.TargetBranch, out var sha))
                {
                    this.TargetCommit = sha;
                }
            })
            .DisposeWith(this);

            driverRepositoryPreparation.DriverInfo
            .Select(x =>
                    x.RunnableState.Failed ? default : x.Item.Tags.OrderByDescending(x => x.Index).FirstOrDefault())
            .FlowSwitch(
                Observable.CombineLatest(
                    this.WhenAnyValue(x => x.TagAutoUpdate),
                    lockToCurrentVersioning.WhenAnyValue(x => x.Lock),
                    this.WhenAnyValue(x => x.PatcherVersioning),
                    (autoTag, locked, versioning) => !locked && autoTag && versioning == PatcherVersioningEnum.Tag))
            .Throttle(TimeSpan.FromMilliseconds(150), RxApp.MainThreadScheduler)
            .Subscribe(x =>
            {
                this.TargetTag    = x?.Name ?? string.Empty;
                this.TargetCommit = x?.Sha ?? string.Empty;
            })
            .DisposeWith(this);

            var targetBranchSha = Observable.CombineLatest(
                driverRepositoryPreparation.DriverInfo
                .Select(x => x.RunnableState.Failed ? default : x.Item.BranchShas),
                targetOriginBranchName,
                (dict, branch) => dict?.GetOrDefault(branch))
                                  .Replay(1)
                                  .RefCount();

            var targetTag = Observable.CombineLatest(
                driverRepositoryPreparation.DriverInfo
                .Select(x => x.RunnableState.Failed ? default : x.Item.Tags),
                this.WhenAnyValue(x => x.TargetTag),
                (tags, tag) => tags?
                .Where(tagItem => tagItem.Name == tag)
                .FirstOrDefault())
                            .Replay(1)
                            .RefCount();

            // Set up empty target autofill
            // Usually for initial bootstrapping
            Observable.CombineLatest(
                targetBranchSha,
                this.WhenAnyValue(x => x.TargetCommit),
                (targetBranchSha, targetCommit) => (targetBranchSha, targetCommit))
            .Throttle(TimeSpan.FromMilliseconds(200), RxApp.MainThreadScheduler)
            .Where(x => x.targetBranchSha != null && TargetCommit.IsNullOrWhitespace())
            .Subscribe(x => { this.TargetCommit = x.targetBranchSha ?? string.Empty; })
            .DisposeWith(this);
            Observable.CombineLatest(
                targetTag,
                this.WhenAnyValue(x => x.TargetCommit),
                (targetTagSha, targetCommit) => (targetTagSha, targetCommit))
            .Throttle(TimeSpan.FromMilliseconds(200), RxApp.MainThreadScheduler)
            .Where(x => x.targetTagSha != null && TargetCommit.IsNullOrWhitespace())
            .Subscribe(x => { this.TargetCommit = x.targetTagSha?.Sha ?? string.Empty; })
            .DisposeWith(this);

            // Set up update available systems
            UpdateToBranchCommand = NoggogCommand.CreateFromObject(
                objectSource: Observable.CombineLatest(
                    targetBranchSha,
                    this.WhenAnyValue(x => x.TargetCommit),
                    (branch, target) => (BranchSha: branch, Current: target)),
                canExecute: o => o.BranchSha != null && o.BranchSha != o.Current,
                extraCanExecute: this.WhenAnyValue(x => x.PatcherVersioning)
                .Select(vers => vers == PatcherVersioningEnum.Branch),
                execute: o => { this.TargetCommit = o.BranchSha !; },
                this);

            UpdateToTagCommand = NoggogCommand.CreateFromObject(
                objectSource: Observable.CombineLatest(
                    targetTag,
                    Observable.CombineLatest(
                        this.WhenAnyValue(x => x.TargetCommit),
                        this.WhenAnyValue(x => x.TargetTag),
                        (TargetSha, TargetTag) => (TargetSha, TargetTag)),
                    (tag, target) => (TagSha: tag?.Sha, Tag: tag?.Name, Current: target)),
                canExecute: o => (o.TagSha != null && o.Tag != null) &&
                (o.TagSha != o.Current.TargetSha || o.Tag != o.Current.TargetTag),
                extraCanExecute: this.WhenAnyValue(x => x.PatcherVersioning)
                .Select(vers => vers == PatcherVersioningEnum.Tag),
                execute: o =>
            {
                this.TargetTag    = o.Tag !;
                this.TargetCommit = o.TagSha !;
            },
                this);

            ActivePatcherVersion = Observable.CombineLatest(
                this.WhenAnyValue(x => x.PatcherVersioning),
                this.WhenAnyValue(x => x.TargetTag),
                this.WhenAnyValue(x => x.TargetCommit),
                targetOriginBranchName,
                Observable.CombineLatest(
                    this.WhenAnyValue(x => x.TagAutoUpdate),
                    lockToCurrentVersioning.WhenAnyValue(x => x.Lock),
                    (auto, locked) => !locked && auto),
                Observable.CombineLatest(
                    this.WhenAnyValue(x => x.BranchAutoUpdate),
                    lockToCurrentVersioning.WhenAnyValue(x => x.Lock),
                    (auto, locked) => !locked && auto),
                (versioning, tag, commit, branch, tagAuto, branchAuto) =>
            {
                return(GitPatcherVersioning.Factory(
                           versioning: versioning,
                           tag: tag,
                           commit: commit,
                           branch: branch,
                           autoTag: tagAuto,
                           autoBranch: branchAuto));
            })
                                   .DistinctUntilChanged()
                                   .Replay(1)
                                   .RefCount();
        }