Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System;
using System.IO;
using System.Linq;
using System.Text.Json.Nodes;
using Fallout.Cli.Prompts;
using Fallout.Common;
using Fallout.Common.Execution;
using Fallout.Common.IO;
Expand All @@ -10,37 +10,48 @@
using Fallout.Common.Utilities;
using static Fallout.Common.Constants;

namespace Fallout.Cli;
namespace Fallout.Cli.Commands;

partial class Program
/// <summary>
/// <c>fallout :update</c>: updates the build scripts, build project, configuration file and global.json.
/// </summary>
public sealed class UpdateCommand : IFalloutCommand
{
public static int Update(string[] args, AbsolutePath rootDirectory, AbsolutePath buildScript)
private readonly IConsolePrompts _prompts;

public UpdateCommand(IConsolePrompts prompts) => _prompts = prompts;

public string Name => "update";

// GetConfiguration / WriteBuildScripts / WriteConfigurationFile / BUILD_PROJECT_FILE remain on
// Program as internal residual until the #392 collapse PR extracts them into services.
public int Execute(string[] args, AbsolutePath rootDirectory, AbsolutePath buildScript)
{
PrintInfo();
Program.PrintInfo();
Logging.Configure();

Assert.NotNull(rootDirectory);

if (buildScript != null)
{
ConfirmExecution("Update build scripts", () => UpdateBuildScripts(rootDirectory, buildScript));
ConfirmExecution("Update build project", () => UpdateBuildProject(buildScript));
_prompts.ConfirmExecution("Update build scripts", () => UpdateBuildScripts(rootDirectory, buildScript));
_prompts.ConfirmExecution("Update build project", () => UpdateBuildProject(buildScript));
}

ConfirmExecution("Update configuration file", () => UpdateConfigurationFile(rootDirectory));
ConfirmExecution("Update global.json", () => UpdateGlobalJsonFile(rootDirectory));
_prompts.ConfirmExecution("Update configuration file", () => UpdateConfigurationFile(rootDirectory));
_prompts.ConfirmExecution("Update global.json", () => UpdateGlobalJsonFile(rootDirectory));

ShowCompletion("Updates");
_prompts.ShowCompletion("Updates");

return 0;
}

private static void UpdateBuildScripts(AbsolutePath rootDirectory, AbsolutePath buildScript)
{
var configuration = GetConfiguration(buildScript, evaluate: true);
var buildProjectFile = (AbsolutePath) configuration[BUILD_PROJECT_FILE];
var configuration = Program.GetConfiguration(buildScript, evaluate: true);
var buildProjectFile = (AbsolutePath) configuration[Program.BUILD_PROJECT_FILE];

WriteBuildScripts(
Program.WriteBuildScripts(
scriptDirectory: buildScript.Parent,
rootDirectory,
buildDirectory: buildProjectFile.NotNull().Parent,
Expand All @@ -49,8 +60,8 @@ private static void UpdateBuildScripts(AbsolutePath rootDirectory, AbsolutePath

private static void UpdateBuildProject(AbsolutePath buildScript)
{
var configuration = GetConfiguration(buildScript, evaluate: true);
var projectFile = configuration[BUILD_PROJECT_FILE];
var configuration = Program.GetConfiguration(buildScript, evaluate: true);
var projectFile = configuration[Program.BUILD_PROJECT_FILE];
ProjectModelTasks.Initialize();
ProjectUpdater.Update(projectFile);
}
Expand All @@ -64,7 +75,7 @@ private static void UpdateConfigurationFile(AbsolutePath rootDirectory)
var solutionFile = rootDirectory / configurationFile.ReadAllLines().FirstOrDefault(x => !x.IsNullOrEmpty());
configurationFile.DeleteFile();

WriteConfigurationFile(rootDirectory, solutionFile);
Program.WriteConfigurationFile(rootDirectory, solutionFile);
Host.Warning($"The previous {FalloutFileName} file was transformed to a {FalloutDirectoryName} directory.");
Host.Warning($"The .tmp directory can be cleared, as it is moved to {FalloutDirectoryName}/temp as well.");
if (solutionFile != null)
Expand Down
5 changes: 4 additions & 1 deletion src/Fallout.Cli/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,10 @@ private static void RegisterCommands(IServiceCollection services)

// Legacy handlers still living on Program, adapted until they are extracted into command
// types. Each conversion deletes one line here plus its Program.X.cs partial.
services.AddSingleton<IFalloutCommand>(new DelegateCommand("update", Update));
services.AddSingleton<IFalloutCommand, UpdateCommand>();

// Legacy handlers still living on Program, adapted until they are extracted into command
// types. Each conversion deletes one line here plus its Program.X.cs partial.
services.AddSingleton<IFalloutCommand>(new DelegateCommand("cake-convert", CakeConvert));
services.AddSingleton<IFalloutCommand>(new DelegateCommand("cake-clean", CakeClean));
services.AddSingleton<IFalloutCommand>(new DelegateCommand("secrets", Secrets));
Expand Down
35 changes: 35 additions & 0 deletions tests/Fallout.Cli.Tests/Commands/FakeConsolePrompts.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using Fallout.Cli.Prompts;

namespace Fallout.Cli.Tests.Commands;

/// <summary>
/// Configurable <see cref="IConsolePrompts"/> test double for exercising command interaction logic
/// without a real console.
/// </summary>
internal sealed class FakeConsolePrompts : IConsolePrompts
{
/// <summary>Answer returned by <see cref="PromptForConfirmation"/>.</summary>
public bool ConfirmationResult { get; init; }

/// <summary>When false, <see cref="ConfirmExecution"/> does not run its action (simulates a decline).</summary>
public bool InvokeConfirmedActions { get; init; }

/// <summary>Titles passed to <see cref="ShowCompletion"/>, in order.</summary>
public List<string> Completions { get; } = new();

public bool PromptForConfirmation(string question) => ConfirmationResult;
public void ShowInput(string emoji, string title, string value) { }
public void ShowCompletion(string title) => Completions.Add(title);
public void ClearPreviousLine() { }
public string PromptForInput(string question, string defaultValue = null) => defaultValue;
public string PromptForSecret(string title, int? minLength = null) => string.Empty;
public T PromptForChoice<T>(string question, params (T Value, string Description)[] choices) => default;

public void ConfirmExecution(string title, Action action)
{
if (InvokeConfirmedActions)
action();
}
}
35 changes: 35 additions & 0 deletions tests/Fallout.Cli.Tests/Commands/UpdateCommandTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System;
using System.IO;
using Fallout.Cli.Commands;
using Fallout.Common.IO;
using FluentAssertions;
using Xunit;

namespace Fallout.Cli.Tests.Commands;

public class UpdateCommandTests
{
[Fact]
public void Name_IsUpdate()
=> new UpdateCommand(new FakeConsolePrompts()).Name.Should().Be("update");

[Fact]
public void Execute_NoBuildScript_DeclineAll_ReturnsZeroAndReportsCompletion()
{
var dir = (AbsolutePath)Path.Combine(Path.GetTempPath(), "fallout-update-" + Guid.NewGuid().ToString("N"));
dir.CreateDirectory();
var prompts = new FakeConsolePrompts { InvokeConfirmedActions = false };
try
{
// No build script and every confirmation declined → no update steps run, but the command
// still completes cleanly.
new UpdateCommand(prompts).Execute([], dir, buildScript: null).Should().Be(0);

prompts.Completions.Should().Contain("Updates");
}
finally
{
Directory.Delete(dir, recursive: true);
}
}
}