From 2ca801bd41210135979e24b9e0904a286fc5b142 Mon Sep 17 00:00:00 2001 From: Chrison Simtian Date: Wed, 17 Jun 2026 21:58:31 +1200 Subject: [PATCH] Convert :add-package to AddPackageCommand Lift the :add-package handler into a standalone IFalloutCommand type. The shared AddOrReplacePackage helper and PACKAGE_TYPE_*/BUILD_PROJECT_FILE constants stay on Program as residual (still used by cake and tests) until the #392 collapse PR moves them into services. Replaces the DelegateCommand adapter. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/Fallout.Cli/Commands/AddPackageCommand.cs | 50 +++++++++++++++++++ src/Fallout.Cli/Program.AddPackage.cs | 33 +----------- src/Fallout.Cli/Program.cs | 2 +- 3 files changed, 53 insertions(+), 32 deletions(-) create mode 100644 src/Fallout.Cli/Commands/AddPackageCommand.cs diff --git a/src/Fallout.Cli/Commands/AddPackageCommand.cs b/src/Fallout.Cli/Commands/AddPackageCommand.cs new file mode 100644 index 00000000..2e4879ad --- /dev/null +++ b/src/Fallout.Cli/Commands/AddPackageCommand.cs @@ -0,0 +1,50 @@ +using System.Linq; +using Fallout.Common; +using Fallout.Common.Execution; +using Fallout.Common.IO; +using Fallout.Solutions; +using Fallout.Common.Tooling; +using Fallout.Common.Tools.DotNet; + +namespace Fallout.Cli.Commands; + +/// +/// fallout :add-package: adds (or upgrades) a NuGet package reference in the build project. +/// +public sealed class AddPackageCommand : IFalloutCommand +{ + public string Name => "add-package"; + + public int Execute(string[] args, AbsolutePath rootDirectory, AbsolutePath buildScript) + { + Program.PrintInfo(); + Logging.Configure(); + Telemetry.AddPackage(); + ProjectModelTasks.Initialize(); + + var packageId = args.ElementAt(0); + var packageVersion = + (EnvironmentInfo.GetNamedArgument("version") ?? + args.ElementAtOrDefault(1) ?? + NuGetVersionResolver.GetLatestVersion(packageId, includePrereleases: false).GetAwaiter().GetResult() ?? + NuGetPackageResolver.GetGlobalInstalledPackage(packageId, version: null, packagesConfigFile: null)?.Version.ToString()) + .NotNull("packageVersion != null"); + + // GetConfiguration / AddOrReplacePackage / BUILD_PROJECT_FILE / PACKAGE_TYPE_* are shared + // helpers still on Program; they move into services in the final #392 collapse PR. + var configuration = Program.GetConfiguration(buildScript, evaluate: true); + var buildProjectFile = configuration[Program.BUILD_PROJECT_FILE]; + Host.Information($"Installing {packageId}/{packageVersion} to {buildProjectFile} ..."); + Program.AddOrReplacePackage(packageId, packageVersion, Program.PACKAGE_TYPE_DOWNLOAD, buildProjectFile); + DotNetTasks.DotNet($"restore {buildProjectFile}"); + + var installedPackage = NuGetPackageResolver.GetGlobalInstalledPackage(packageId, packageVersion, packagesConfigFile: null) + .NotNull("installedPackage != null"); + var hasToolsDirectory = installedPackage.Directory.GlobDirectories("tools").Any(); + if (!hasToolsDirectory) + Program.AddOrReplacePackage(packageId, packageVersion, Program.PACKAGE_TYPE_REFERENCE, buildProjectFile); + + Host.Information($"Done installing {packageId}/{packageVersion} to {buildProjectFile}"); + return 0; + } +} diff --git a/src/Fallout.Cli/Program.AddPackage.cs b/src/Fallout.Cli/Program.AddPackage.cs index 29efb84b..87852ae4 100644 --- a/src/Fallout.Cli/Program.AddPackage.cs +++ b/src/Fallout.Cli/Program.AddPackage.cs @@ -14,37 +14,8 @@ partial class Program public const string PACKAGE_TYPE_DOWNLOAD = "PackageDownload"; public const string PACKAGE_TYPE_REFERENCE = "PackageReference"; - public static int AddPackage(string[] args, AbsolutePath rootDirectory, AbsolutePath buildScript) - { - PrintInfo(); - Logging.Configure(); - Telemetry.AddPackage(); - ProjectModelTasks.Initialize(); - - var packageId = args.ElementAt(0); - var packageVersion = - (EnvironmentInfo.GetNamedArgument("version") ?? - args.ElementAtOrDefault(1) ?? - NuGetVersionResolver.GetLatestVersion(packageId, includePrereleases: false).GetAwaiter().GetResult() ?? - NuGetPackageResolver.GetGlobalInstalledPackage(packageId, version: null, packagesConfigFile: null)?.Version.ToString()) - .NotNull("packageVersion != null"); - - var configuration = GetConfiguration(buildScript, evaluate: true); - var buildProjectFile = configuration[BUILD_PROJECT_FILE]; - Host.Information($"Installing {packageId}/{packageVersion} to {buildProjectFile} ..."); - AddOrReplacePackage(packageId, packageVersion, PACKAGE_TYPE_DOWNLOAD, buildProjectFile); - DotNetTasks.DotNet($"restore {buildProjectFile}"); - - var installedPackage = NuGetPackageResolver.GetGlobalInstalledPackage(packageId, packageVersion, packagesConfigFile: null) - .NotNull("installedPackage != null"); - var hasToolsDirectory = installedPackage.Directory.GlobDirectories("tools").Any(); - if (!hasToolsDirectory) - AddOrReplacePackage(packageId, packageVersion, PACKAGE_TYPE_REFERENCE, buildProjectFile); - - Host.Information($"Done installing {packageId}/{packageVersion} to {buildProjectFile}"); - return 0; - } - + // Residual after the :add-package command moved to AddPackageCommand: this helper is shared with + // cake and moves into a package service in the #392 collapse PR. internal static void AddOrReplacePackage(string packageId, string packageVersion, string packageType, string buildProjectFile) { var buildProject = ProjectModelTasks.ParseProject(buildProjectFile).NotNull(); diff --git a/src/Fallout.Cli/Program.cs b/src/Fallout.Cli/Program.cs index 43ac5823..cbd1dcab 100644 --- a/src/Fallout.Cli/Program.cs +++ b/src/Fallout.Cli/Program.cs @@ -56,12 +56,12 @@ private static void RegisterCommands(IServiceCollection services) services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); // 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(new DelegateCommand("setup", Setup)); services.AddSingleton(new DelegateCommand("update", Update)); - services.AddSingleton(new DelegateCommand("add-package", AddPackage)); services.AddSingleton(new DelegateCommand("cake-convert", CakeConvert)); services.AddSingleton(new DelegateCommand("cake-clean", CakeClean)); services.AddSingleton(new DelegateCommand("secrets", Secrets));