/// <summary>
        /// Determines whether or not there are diagnostics in Razor documents in the context's current project that this updater can address.
        /// </summary>
        /// <param name="context">The upgrade context containing the project to analyze.</param>
        /// <param name="inputs">The Razor documents within the context's current project that should be analyzed for possible source updates.</param>
        /// <param name="token">A cancellation token.</param>
        /// <returns>True if the Razor documents contain diagnostics that this updater can address, false otherwise.</returns>
        public async Task <IUpdaterResult> IsApplicableAsync(IUpgradeContext context, ImmutableArray <RazorCodeDocument> inputs, CancellationToken token)
        {
            if (context is null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            var project = GetProjectWithGeneratedCode(context.CurrentProject.Required(), inputs);

            _logger.LogDebug("Running upgrade analyzers on Razor files in {ProjectName}", project.Name);

            // Use mapped locations so that we only get a number of diagnostics corresponding to the number of cshtml locations that need fixed.
            var mappedDiagnostics = await GetDiagnosticsFromTargetFilesAsync(project, context, inputs.Select(GetGeneratedFilePath), new LocationAndIDComparer(true), token).ConfigureAwait(false);

            _logger.LogInformation("Identified {DiagnosticCount} diagnostics in Razor files in project {ProjectName}", mappedDiagnostics.Count(), project.Name);
            var diagnosticsByFile = mappedDiagnostics.GroupBy(d => d.Location.GetMappedLineSpan().Path);

            foreach (var diagnosticsGroup in diagnosticsByFile)
            {
                _logger.LogInformation("  {DiagnosticsCount} diagnostics need fixed in {FilePath}", diagnosticsGroup.Count(), diagnosticsGroup.Key);
            }

            return(new FileUpdaterResult(
                       RuleId,
                       RuleName: Id,
                       FullDescription: Title,
                       mappedDiagnostics.Any(),
                       diagnosticsByFile.Select(g => g.Key)));
        }
Exemplo n.º 2
0
        private async Task RunStepAsync(IUpgradeContext context, UpgradeStep step, CancellationToken token)
        {
            token.ThrowIfCancellationRequested();

            await _io.Output.WriteLineAsync();

            var commands = _commandProvider.GetCommands(step, context);
            var command  = await _input.ChooseAsync("Choose a command:", commands, token);

            // TODO : It might be nice to allow commands to show more details by having a 'status' property
            //        that can be shown here. Also, commands currently only return bools but, in the future,
            //        if they return more complex objects, custom handlers could be used to respond to the different
            //        commands' return values.
            if (!await ExecuteAndTimeCommand(context, step, command, token))
            {
                Console.ForegroundColor = ConsoleColor.Yellow;
                await _io.Output.WriteAsync($"Command ({command.CommandText}) did not succeed");

                Console.ResetColor();
            }
            else if (!await _input.WaitToProceedAsync(token))
            {
                _logger.LogWarning("Upgrade process was canceled. Quitting....");
            }

            token.ThrowIfCancellationRequested();
        }
Exemplo n.º 3
0
        protected override async Task <bool> IsApplicableImplAsync(IUpgradeContext context, CancellationToken token)
        {
            if (context is null)
            {
                return(false);
            }

            if (context.CurrentProject is null)
            {
                return(false);
            }

            var project = context.CurrentProject.Required();

            var components = await project.GetComponentsAsync(token).ConfigureAwait(false);

            if (components.HasFlag(ProjectComponents.XamarinAndroid) || components.HasFlag(ProjectComponents.XamariniOS))
            {
                return(true);
            }

            if (components.HasFlag(ProjectComponents.MauiAndroid) || components.HasFlag(ProjectComponents.MauiiOS) || components.HasFlag(ProjectComponents.Maui))
            {
                return(true);
            }

            if (!string.IsNullOrWhiteSpace(context.Properties.GetPropertyValue("componentFlag")))
            {
                return(true);
            }

            return(false);
        }
Exemplo n.º 4
0
        protected override async Task <UpgradeStepApplyResult> ApplyImplAsync(IUpgradeContext context, CancellationToken token)
        {
            if (context is null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (context.EntryPoints.Any())
            {
                return(new UpgradeStepApplyResult(UpgradeStepStatus.Complete, "Entrypoint already set."));
            }

            var selectedProject = await GetEntrypointAsync(context, token).ConfigureAwait(false);

            if (selectedProject is null)
            {
                return(new UpgradeStepApplyResult(UpgradeStepStatus.Failed, "No project was selected."));
            }
            else
            {
                context.EntryPoints = new[] { selectedProject };
                await _restorer.RestorePackagesAsync(context, selectedProject, token).ConfigureAwait(false);

                return(new UpgradeStepApplyResult(UpgradeStepStatus.Complete, $"Project {selectedProject.GetRoslynProject().Name} was selected."));
            }
        }
Exemplo n.º 5
0
 private async ValueTask <bool> ExecuteAndTimeCommand(IUpgradeContext context, UpgradeStep step, UpgradeCommand command, CancellationToken token)
 {
     using (_telemetry.TimeStep(command.Id, step))
     {
         return(await command.ExecuteAsync(context, token));
     }
 }
Exemplo n.º 6
0
        public async Task <bool> RunAsync(IUpgradeContext context, IProject project, CancellationToken token)
        {
            if (context is null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (project is null)
            {
                throw new ArgumentNullException(nameof(project));
            }

            var tfm = await _targetFrameworkSelector.SelectTargetFrameworkAsync(project, token).ConfigureAwait(false);

            // try-convert has no overloads to pass in properties
            SetEnvironmentVariables(context);

            var workspaceLoader  = new MSBuildConversionWorkspaceLoader(project.FileInfo.FullName, MSBuildConversionWorkspaceType.Project);
            var msbuildWorkspace = workspaceLoader.LoadWorkspace(project.FileInfo.FullName, noBackup: true, tfm.ToString(), keepCurrentTFMs: true, forceWeb: true);

            if (msbuildWorkspace.WorkspaceItems.Length is 0)
            {
                _logger.LogWarning("No projects were converted to SDK style");
                return(false);
            }

            foreach (var item in msbuildWorkspace.WorkspaceItems)
            {
                _logger.LogInformation("Converting project {Path} to SDK style", item.ProjectRootElement.FullPath);
                var converter = new Converter(item.UnconfiguredProject, item.SdkBaselineProject, item.ProjectRootElement, noBackup: true, forceRemoveCustomImports: true);
                converter.Convert(item.ProjectRootElement.FullPath);
            }

            return(true);
        }
Exemplo n.º 7
0
        protected override async Task <UpgradeStepApplyResult> ApplyImplAsync(IUpgradeContext context, CancellationToken token)
        {
            if (context is null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            try
            {
                var updaterResult = (FileUpdaterResult)(await _updater.ApplyAsync(context, _razorUpdaterStep.RazorDocuments, token).ConfigureAwait(false));
                if (updaterResult.Result)
                {
                    // Process Razor documents again after successfully applying an updater in case Razor files have changed
                    _razorUpdaterStep.ProcessRazorDocuments(updaterResult.FilePaths);

                    return(new UpgradeStepApplyResult(UpgradeStepStatus.Complete, string.Empty));
                }
                else
                {
                    return(new UpgradeStepApplyResult(UpgradeStepStatus.Failed, $"Failed to apply Razor updater \"{_updater.Title}\""));
                }
            }
#pragma warning disable CA1031 // Do not catch general exception types
            catch (Exception exc)
#pragma warning restore CA1031 // Do not catch general exception types
            {
                Logger.LogError(exc, "Unexpected exception while applying Razor updater \"{RazorUpdater}\"", _updater.Title);
                return(new UpgradeStepApplyResult(UpgradeStepStatus.Failed, $"Unexpected exception while applying Razor updater \"{_updater.Title}\": {exc}"));
            }
        }
Exemplo n.º 8
0
        /// <summary>
        /// Determines whether the RazorUpdaterStep applies to a given context. This doesn't
        /// consider whether there's actually any work to be done by Razor updaters. Rather, it
        /// determines whether it makes sense to even initialize the Razor updaters. So, it
        /// will return false if there are no cshtml files in the current project or if there
        /// are no Razor updaters available.
        /// </summary>
        /// <param name="context">The context to evaluate.</param>
        /// <param name="token">A token that can be used to cancel execution.</param>
        /// <returns>True if the Razor updater step might apply, false otherwise.</returns>
        protected override async Task <bool> IsApplicableImplAsync(IUpgradeContext context, CancellationToken token)
        {
            // The RazorUpdaterStep is only applicable when a project is loaded
            if (context?.CurrentProject is null)
            {
                return(false);
            }

            // The RazorUpdaterStep is only applicable when the project contans Razor files to update
            if (!GetRazorFileSystem(context.CurrentProject.Required()).EnumerateItems("/").Any())
            {
                return(false);
            }

            // The RazorUpdaterStep is applicable if it contains at least one applicable substep
            foreach (var subStep in SubSteps)
            {
                if (await subStep.IsApplicableAsync(context, token).ConfigureAwait(false))
                {
                    return(true);
                }
            }

            return(false);
        }
Exemplo n.º 9
0
        protected override async Task <UpgradeStepApplyResult> ApplyImplAsync(IUpgradeContext context, CancellationToken token)
        {
            if (context is null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            // Reload the workspace in case code fixes modified the project file
            await context.ReloadWorkspaceAsync(token).ConfigureAwait(false);

            // Apply any necessary cleanup to the project file
            var file = context.CurrentProject.Required().GetFile();

            file.Simplify();
            await file.SaveAsync(token).ConfigureAwait(false);

            if (Diagnostics.Any())
            {
                Logger.LogInformation("Source updates complete with {DiagnosticCount} diagnostics remaining which require manual updates", Diagnostics.Count());
                foreach (var diagnostic in Diagnostics)
                {
                    Logger.LogWarning("Manual updates needed to address: {DiagnosticId}@{DiagnosticLocation}: {DiagnosticMessage}", diagnostic.Id, diagnostic.Location, diagnostic.GetMessage());
                }
            }

            return(new UpgradeStepApplyResult(UpgradeStepStatus.Complete, string.Empty));
        }
        public async Task <bool> ApplyAsync(IUpgradeContext context, ImmutableArray <ConfigFile> configFiles, CancellationToken token)
        {
            if (context is null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            try
            {
                var project = context.CurrentProject.Required();

                var viewImportsContents = new List <string>(_viewImportsPath is null
                    ? new[] { string.Empty, ViewImportsInitialContent }
                    : await File.ReadAllLinesAsync(_viewImportsPath, token).ConfigureAwait(false));

                foreach (var ns in _namespacesToUpgrade.OrderByDescending(s => s))
                {
                    _logger.LogDebug("Namespace {Namespace} added to _ViewImports.cshtml", ns);
                    viewImportsContents.Insert(0, $"{RazorUsingPrefix}{ns}");
                }

                var path = _viewImportsPath ?? Path.Combine(project.Directory ?? string.Empty, ViewImportsRelativePath);
                await File.WriteAllLinesAsync(path, viewImportsContents, token).ConfigureAwait(false);

                _logger.LogInformation("View imports written to {ViewImportsPath}", path);

                return(true);
            }
            catch (IOException exc)
            {
                _logger.LogError(exc, "Unexpected exception accessing _ViewImports");
                return(false);
            }
        }
Exemplo n.º 11
0
        private static async Task FixUpProjectFileAsync(IUpgradeContext context, CancellationToken token)
        {
            var file = context.CurrentProject.Required().GetFile();

            file.Simplify();
            await file.SaveAsync(token).ConfigureAwait(false);
        }
Exemplo n.º 12
0
        public async Task <IDependencyAnalysisState> AnalyzeAsync(IUpgradeContext context, IProject?projectRoot, IReadOnlyCollection <TargetFrameworkMoniker> targetframeworks, CancellationToken token)
        {
            if (projectRoot is null)
            {
                _logger.LogError("No project available");
                throw new ArgumentNullException(nameof(projectRoot));
            }

            await _packageRestorer.RestorePackagesAsync(context, projectRoot, token).ConfigureAwait(false);

            var analysisState = new DependencyAnalysisState(projectRoot, projectRoot.NuGetReferences, targetframeworks);

            // Iterate through all package references in the project file
            foreach (var analyzer in _packageAnalyzers)
            {
                _logger.LogDebug("Analyzing packages with {AnalyzerName}", analyzer.Name);

                try
                {
                    await analyzer.AnalyzeAsync(projectRoot, analysisState, token).ConfigureAwait(false);
                }
#pragma warning disable CA1031 // Do not catch general exception types
                catch (Exception e)
#pragma warning restore CA1031 // Do not catch general exception types
                {
                    _logger.LogCritical("Package analysis failed (analyzer {AnalyzerName}: {Message}", analyzer.Name, e.Message);
                    analysisState.IsValid = false;
                }
            }

            return(analysisState);
        }
Exemplo n.º 13
0
        public async Task <IUpdaterResult> IsApplicableAsync(IUpgradeContext context, ImmutableArray <IProject> inputs, CancellationToken token)
        {
            if (context is null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            var fileLocations = new List <string>();

            foreach (var project in inputs)
            {
                if (await project.IsWinFormsProjectAsync(token).ConfigureAwait(false))
                {
                    _logger.LogWarning(this.Description);
                    fileLocations.Add(Path.Combine(project.FileInfo.DirectoryName, project.FileInfo.Name));
                }
            }

            return(new WinformsUpdaterResult(
                       RuleId,
                       RuleName: Id,
                       FullDescription: Title,
                       Result: fileLocations.Any(),
                       Message: this.Description,
                       FileLocations: fileLocations));
        }
Exemplo n.º 14
0
        /// <summary>
        /// This method runs when the Upgrade Assistant is considering this upgrade step to run next. The method needs to
        /// determine whether the step should be run (or if, for example, it has no work to do) and return an
        /// appropriate UpgradeStepInitializeResult. This method can also prepare stat that the upgrade step
        /// will need to execute.
        /// </summary>
        /// <param name="context">The upgrade context to evaluate.</param>
        /// <param name="token">A cancellation token.</param>
        /// <returns>An UpgradeStepInitializeResult representing the current state of the upgrade step.</returns>
        protected override Task <UpgradeStepInitializeResult> InitializeImplAsync(IUpgradeContext context, CancellationToken token)
        {
            if (context is null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            // The IProjectFile abstraction exposes the project file.
            var projectFile = context.CurrentProject.Required().GetFile();

            if (_options?.Authors is null)
            {
                _logger.LogDebug("No authors setting found in extension configuration. Authors will not be added to the project.");

                // UpgradeInitializeResult includes a step status, string with details on the status, and a BuildBreakRisk property
                // indicating to the user whether applying this step is likely to introduce build breaks into their project.
                var result = new UpgradeStepInitializeResult(UpgradeStepStatus.Complete, "No authors need added", BuildBreakRisk.None);
                return(Task.FromResult(result));
            }

            var existingAuthorsProperty = projectFile.GetPropertyValue(AuthorsPropertyName);

            if (existingAuthorsProperty is null || !existingAuthorsProperty.Contains(_options.Authors, StringComparison.OrdinalIgnoreCase))
            {
                _logger.LogDebug("Existing authors property ({Authors}) does not contain expected authors ({ExpectedAuthors})", existingAuthorsProperty, _options.Authors);

                // If a change is needed, InitializeImplAsync should return a result with UpgradeStepStatus.Incomplete, but not make the update
                // until the upgrade step's ApplyImplAsync method is called.
                var result = new UpgradeStepInitializeResult(UpgradeStepStatus.Incomplete, $"Expected authors {_options.Authors} need added to the projects Authors property", BuildBreakRisk.None);
                return(Task.FromResult(result));
            }
Exemplo n.º 15
0
        /// <summary>
        /// Determines whether this updater needs to run on a given set of RazorCodeDocuments. Will return true if there are @helper functions
        /// in any of the Razor documents and false otherwise.
        /// </summary>
        /// <param name="context">The upgrade context for the currently upgrading solution.</param>
        /// <param name="inputs">The Razor code documents being upgraded.</param>
        /// <param name="token">A cancellation token.</param>
        /// <returns>A FileUpdaterResult with a 'true' value if any documents contain a @helper and false otherwise. If true, the result will also include the paths of the documents containing a @helper.</returns>
        public Task <IUpdaterResult> IsApplicableAsync(IUpgradeContext context, ImmutableArray <RazorCodeDocument> inputs, CancellationToken token)
        {
            if (context is null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            var inputsWithHelpers = new List <string>();

            foreach (var input in inputs)
            {
                // Check whether any of the documents contain a @helper function
                if (_helperMatcher.GetHelperReplacements(input).Any())
                {
                    // If a @helper is present, log it to the console and store the path to return later
                    var path = input.Source.FilePath;
                    inputsWithHelpers.Add(path);
                }
            }

            // Log how many Razor documents had @helpers and return a corresponding FileUpdaterResult
            _logger.LogInformation("Found @helper functions in {Count} documents", inputsWithHelpers.Count);
            return(Task.FromResult <IUpdaterResult>(new FileUpdaterResult(
                                                        RuleId,
                                                        RuleName: Id,
                                                        FullDescription: Title,
                                                        inputsWithHelpers.Any(),
                                                        inputsWithHelpers)));
        }
Exemplo n.º 16
0
        public async Task <IUpdaterResult> IsApplicableAsync(IUpgradeContext context, ImmutableArray <IProject> inputs, CancellationToken token)
        {
            await Task.Yield();

            var filesToUpdate = new List <string>();

            foreach (var project in inputs)
            {
                foreach (var file in project.FindFiles(".xaml", ProjectItemType.None))
                {
                    var contents = File.ReadAllText(file);
                    if (contents.Contains("ReorderGridAnimation.Duration"))
                    {
                        filesToUpdate.Add(file);
                        continue;
                    }
                }
            }

            return(new WindowsDesktopUpdaterResult(
                       RuleID,
                       RuleName: Id,
                       FullDescription: Title,
                       filesToUpdate.Any(),
                       string.Empty,
                       filesToUpdate));
        }
        private UpgradeStepInitializeResult InitializeImpl(IUpgradeContext context)
        {
            if (context is null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (context.CurrentProject is not null)
            {
                return(new UpgradeStepInitializeResult(UpgradeStepStatus.Complete, "Current project is already selected.", BuildBreakRisk.None));
            }

            var projects = context.Projects.ToList();

            if (projects.All(p => IsCompleted(context, p)))
            {
                return(new UpgradeStepInitializeResult(UpgradeStepStatus.Complete, "No projects need upgrade", BuildBreakRisk.None));
            }

            if (projects.Count == 1)
            {
                var project = projects[0];
                context.SetCurrentProject(project);

                Logger.LogInformation("Setting only project in solution as the current project: {Project}", project.FilePath);

                return(new UpgradeStepInitializeResult(UpgradeStepStatus.Complete, "Selected only project.", BuildBreakRisk.None));
            }

            return(new UpgradeStepInitializeResult(UpgradeStepStatus.Incomplete, "No project is currently selected.", BuildBreakRisk.None));
        }
Exemplo n.º 18
0
        public async Task UpgradeAsync(IUpgradeContext context)
        {
            int currentVersion = GetCurrentVersion();

            if (CurrentVersion <= currentVersion)
            {
                return;
            }

            context.TotalSteps(CurrentVersion - currentVersion);
            await Task.Delay(500);

            if (currentVersion < 1)
            {
                context.StartingStep(currentVersion - 0, "Creating default categories.");
                await UpgradeVersion1();
            }

            if (currentVersion < 2)
            {
                context.StartingStep(currentVersion - 1, "Rebuilding internal database.");
                await UpgradeVersion2();
            }

            ApplicationDataContainer migrationContainer = GetMigrationContainer();

            migrationContainer.Values["Version"] = CurrentVersion;
        }
Exemplo n.º 19
0
 private static void SetEnvironmentVariables(IUpgradeContext context)
 {
     foreach (var(key, value) in context.GlobalProperties)
     {
         Environment.SetEnvironmentVariable(key, value);
     }
 }
        /// <summary>
        /// This method runs when the Upgrade Assistant is considering this upgrade step to run next. The method needs to
        /// determine whether the step should be run (or if, for example, it has no work to do) and return an
        /// appropriate UpgradeStepInitializeResult. This method can also prepare state that the upgrade step
        /// will need to execute. In the case of the FindReplaceStep, InitializeImplAsync will return an incomplete
        /// result if any source files in the project have strings that need replaced and false otherwise.
        /// </summary>
        /// <param name="context">The upgrade context to evaluate.</param>
        /// <param name="token">A cancellation token.</param>
        /// <returns>An UpgradeStepInitializeResult representing the current state of the upgrade step.</returns>
        protected override Task <UpgradeStepInitializeResult> InitializeImplAsync(IUpgradeContext context, CancellationToken token)
        {
            if (context is null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            // The IProject abstraction exposes a project.
            var currentProject = context.CurrentProject.Required();

            // Prepare state by identifying necessary replacements
            var compiledItems    = currentProject.FindFiles(ProjectItemType.Compile, ".cs");
            var stringsToReplace = StringsToReplace.Keys;

            _neededReplacements = new Dictionary <string, IEnumerable <string> >();
            foreach (var itemPath in compiledItems)
            {
                var contents  = File.ReadAllText(itemPath);
                var keysFound = stringsToReplace.Where(s => contents.Contains(s));
                if (keysFound.Any())
                {
                    Logger.LogDebug("Found {ReplacementCount} distinct strings needing replacement in {Path}", keysFound.Count(), itemPath);
                    _neededReplacements.Add(itemPath, keysFound);
                }
            }

            Logger.LogInformation("Found {FileCount} files needing string replacements", _neededReplacements.Count);

            // Return an appropriate UpgradeStepInitializeResult based on whether any replacements are needed
            return(Task.FromResult(_neededReplacements.Any()
                ? new UpgradeStepInitializeResult(UpgradeStepStatus.Incomplete, $"Replacements needed in {_neededReplacements.Count} files", BuildBreakRisk.Medium)
                : new UpgradeStepInitializeResult(UpgradeStepStatus.Complete, "No string replacements needed", BuildBreakRisk.None)));
        }
Exemplo n.º 21
0
        public async Task <UpgradeStepApplyResult> ApplyAsync(IUpgradeContext context, IProject project, CancellationToken token)
        {
            if (context is null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (project is null)
            {
                throw new ArgumentNullException(nameof(project));
            }

            var components = await project.GetComponentsAsync(token).ConfigureAwait(false);

            if (components.HasFlag(ProjectComponents.XamarinAndroid) || components.HasFlag(ProjectComponents.XamariniOS))
            {
                context.Properties.SetPropertyValue("componentFlag", components.ToString(), true);
            }

            var result = await RunTryConvertAsync(context, project, token).ConfigureAwait(false);

            await _restorer.RestorePackagesAsync(context, project, token).ConfigureAwait(false);

            return(result);
        }
 /// <summary>
 /// Returns true if the upgrade step is applicable to the current upgrade context state, otherwise false.
 /// If this returns true, the step will be shown in the list of steps to be applied. If this returns false,
 /// the step will not be shown in the list. This method is called every time an upgrade step is applied,
 /// so the applicability of the step may change over the course of the upgrade process.
 /// </summary>
 /// <param name="context">The upgrade context to evaluate for applicability.</param>
 /// <param name="token">A cancellation token.</param>
 /// <returns>True if the upgrade step should be displayed to the user; false otherwise.</returns>
 protected override Task <bool> IsApplicableImplAsync(IUpgradeContext context, CancellationToken token)
 {
     // Because this upgrade step works at the project level, it is only applicable if there is a current project available.
     // If, for example, the user hasn't selected which project to upgrade yet, then this step will not apply.
     // Also, the upgrade step only applies if string replacements have been supplied.
     return(Task.FromResult(context?.CurrentProject is not null && StringsToReplace.Any()));
 }
Exemplo n.º 23
0
        protected override Task <UpgradeStepInitializeResult> InitializeImplAsync(IUpgradeContext context, CancellationToken token)
        {
            if (context is null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            _projectDir = context.CurrentProject.Required().Directory;
            _backupPath ??= GetDefaultBackupPath(_projectDir);

            if (_skipBackup)
            {
                Logger.LogDebug("Backup upgrade step initalized as complete (backup skipped)");
                return(Task.FromResult(new UpgradeStepInitializeResult(UpgradeStepStatus.Skipped, "Backup skipped", BuildBreakRisk.None)));
            }
            else if (_backupPath is null)
            {
                Logger.LogDebug("No backup path specified");
                return(Task.FromResult(new UpgradeStepInitializeResult(UpgradeStepStatus.Failed, "Backup step cannot be applied without a backup location", BuildBreakRisk.None)));
            }
            else if (File.Exists(Path.Combine(_backupPath, FlagFileName)))
            {
                Logger.LogDebug("Backup upgrade step initalized as complete (already done)");
                return(Task.FromResult(new UpgradeStepInitializeResult(UpgradeStepStatus.Complete, "Existing backup found", BuildBreakRisk.None)));
            }
            else
            {
                Logger.LogDebug("Backup upgrade step initialized as incomplete");
                return(Task.FromResult(new UpgradeStepInitializeResult(UpgradeStepStatus.Incomplete, $"No existing backup found. Applying this step will copy the contents of {_projectDir} (including subfolders) to another folder.", BuildBreakRisk.None)));
            }
        }
        /// <summary>
        /// The ApplyImplAsync step is invoked when the user attempts to actually apply the upgrade step and should make
        /// necessary changes to the upgrade context. In the case of the FindReplaceStep, ApplyImplAsync will replace strings
        /// based on the results of the initialize method.
        /// </summary>
        /// <param name="context">The upgrade context to update.</param>
        /// <param name="token">A cancellation token.</param>
        /// <returns>A result indicating whether the upgrade step applied successfully or not.</returns>
        protected override Task <UpgradeStepApplyResult> ApplyImplAsync(IUpgradeContext context, CancellationToken token)
        {
            if (context is null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (_neededReplacements is null)
            {
                Logger.LogError("Could not apply FindReplaceStep because the step has not been properly initialized");
                return(Task.FromResult(new UpgradeStepApplyResult(UpgradeStepStatus.Failed, "FindReplaceStep cannot be applied before it is initialized")));
            }

            // Apply the necessary changes for this upgrade step
            foreach (var path in _neededReplacements.Keys)
            {
                Logger.LogTrace("Replacing strings in {FilePath}", path);
                var replacements = _neededReplacements[path];
                var contents     = File.ReadAllText(path);
                foreach (var key in replacements)
                {
                    contents = contents.Replace(key, StringsToReplace[key]);
                }

                File.WriteAllText(path, contents);
            }

            Logger.LogInformation("Strings replaced in {Count} files", _neededReplacements.Keys.Count);
            return(Task.FromResult(new UpgradeStepApplyResult(UpgradeStepStatus.Complete, $"Strings replaced in {_neededReplacements.Keys.Count} files")));
        }
Exemplo n.º 25
0
        protected override Task <UpgradeStepApplyResult> ApplyImplAsync(IUpgradeContext context, CancellationToken token)
        {
            context.IsComplete  = true;
            context.EntryPoints = Enumerable.Empty <IProject>();

            return(Task.FromResult(new UpgradeStepApplyResult(UpgradeStepStatus.Complete, "Upgrade complete")));
        }
Exemplo n.º 26
0
        private async Task <string?> ChooseBackupPath(IUpgradeContext context, CancellationToken token)
        {
            var customPath = default(string);
            var commands   = new[]
            {
                UpgradeCommand.Create($"Use default path [{_backupPath}]"),
                UpgradeCommand.Create("Enter custom path", async(ctx, token) =>
                {
                    customPath = await _userInput.AskUserAsync("Please enter a custom path for backups:").ConfigureAwait(false);
                    return(!string.IsNullOrEmpty(customPath));
                })
            };

            while (!token.IsCancellationRequested)
            {
                var result = await _userInput.ChooseAsync("Please choose a backup path", commands, token).ConfigureAwait(false);

                if (await result.ExecuteAsync(context, token).ConfigureAwait(false))
                {
                    // customPath may be set in the lambda above.
#pragma warning disable CA1508 // Avoid dead conditional code
                    return(customPath ?? _backupPath);

#pragma warning restore CA1508 // Avoid dead conditional code
                }
            }

            return(null);
        }
Exemplo n.º 27
0
        /// <summary>
        /// Determines whether the VisualBasicProjectUpdaterStep applies to a given context.
        /// </summary>
        /// <param name="context">The context to evaluate.</param>
        /// <param name="token">A token that can be used to cancel execution.</param>
        /// <returns>True if there are applicable substeps, false otherwise.</returns>
        protected override async Task <bool> IsApplicableImplAsync(IUpgradeContext context, CancellationToken token)
        {
            // The VisualBasicProjectUpdaterStep is only applicable when a project is loaded
            if (context?.CurrentProject is null)
            {
                return(false);
            }

            if (!(context?.CurrentProject.Language is Language.VisualBasic))
            {
                // this step only applies to VB projects
                return(false);
            }

            // The VisualBasicProjectUpdaterStep is applicable if it contains at least one applicable substep
            foreach (var subStep in SubSteps)
            {
                if (await subStep.IsApplicableAsync(context, token).ConfigureAwait(false))
                {
                    return(true);
                }
            }

            return(false);
        }
Exemplo n.º 28
0
        public IReadOnlyList <UpgradeCommand> GetCommands(UpgradeStep step, IUpgradeContext context)
        {
            if (step is null)
            {
                throw new ArgumentNullException(nameof(step));
            }

            if (context is null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            var commands = new List <UpgradeCommand>
            {
                new ApplyNextCommand(step),
                new SkipNextCommand(step),
                new SeeMoreDetailsCommand(step, ShowStepStatus)
            };

            if (context.Projects.Count() > 1 && context.CurrentProject is not null)
            {
                commands.Add(new SelectProjectCommand());
            }

            commands.Add(new ConfigureConsoleLoggingCommand(_userInput, _logSettings));
            commands.Add(_exit);
            return(commands);
        }
Exemplo n.º 29
0
        private async Task <IProject> GetProjectAsync(IUpgradeContext context, CancellationToken token)
        {
            const string SelectProjectQuestion = "Here is the recommended order to upgrade. Select enter to follow this list, or input the project you want to start with.";

            if (_orderedProjects is null)
            {
                throw new UpgradeException("Project selection step must be initialized before it is applied (null _orderedProjects)");
            }

            // No need for an IAsyncEnumerable here since the commands shouldn't be displayed until
            // all are available anyhow.
            var commands = new List <ProjectCommand>();

            foreach (var project in _orderedProjects)
            {
                commands.Add(await CreateProjectCommandAsync(project).ConfigureAwait(false));
            }

            var result = await _input.ChooseAsync(SelectProjectQuestion, commands, token).ConfigureAwait(false);

            return(result.Project);

            async Task <ProjectCommand> CreateProjectCommandAsync(IProject project)
            {
                var projectCompleted = await IsCompletedAsync(context, project, token).ConfigureAwait(false);

                var checks = await RunChecksAsync(project, token).ConfigureAwait(false);

                return(new ProjectCommand(project, projectCompleted, checks));
            }
        }
Exemplo n.º 30
0
        protected override async Task UpgradeOverrideAsync(IUpgradeContext context, int currentVersion)
        {
            if (currentVersion < 1)
            {
                context.StartingStep(0 - currentVersion, "Creating default categories.");
                EnsureReadModelDatabase();
                EnsureEventSourcingDatabase();
                await UpgradeVersion1();
            }

            if (currentVersion < 2)
            {
                context.StartingStep(1 - currentVersion, "Rebuilding internal database.");
                await UpgradeVersion2();
            }

            if (currentVersion < 3)
            {
                context.StartingStep(2 - currentVersion, "Creating default currencies.");
                await UpgradeVersion3();
            }

            if (currentVersion < 4)
            {
                context.StartingStep(3 - currentVersion, "Adding support for category icons.");
                await UpgradeVersion4();
            }

            if (currentVersion < 5)
            {
                context.StartingStep(4 - currentVersion, "Adding user info to entries.");
                await UpgradeVersion5();
            }
        }
 public void Upgrade(IUpgradeContext context)
 {
 }
 public void Upgrade(IUpgradeContext context)
 {
     this.IsUpgraded = true;
 }