diff --git a/modules/KoreBuild.Tasks/module.targets b/modules/KoreBuild.Tasks/module.targets index 6ef4699..f2c9c61 100644 --- a/modules/KoreBuild.Tasks/module.targets +++ b/modules/KoreBuild.Tasks/module.targets @@ -9,6 +9,7 @@ false + $(RepositoryRoot)build\dependencies.props @@ -77,23 +78,24 @@ - + + @@ -102,7 +104,7 @@ diff --git a/tools/KoreBuild.Console/Commands/CommandBase.cs b/tools/KoreBuild.Console/Commands/CommandBase.cs index 35f702d..bb8fcc8 100644 --- a/tools/KoreBuild.Console/Commands/CommandBase.cs +++ b/tools/KoreBuild.Console/Commands/CommandBase.cs @@ -18,7 +18,7 @@ namespace KoreBuild.Console.Commands application.OnExecute( () => { - if(IsValid()) + if (IsValid()) { return Execute(); } diff --git a/tools/KoreBuild.Console/Commands/DependenciesGenerateCommand.cs b/tools/KoreBuild.Console/Commands/DependenciesGenerateCommand.cs new file mode 100644 index 0000000..4122078 --- /dev/null +++ b/tools/KoreBuild.Console/Commands/DependenciesGenerateCommand.cs @@ -0,0 +1,72 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using System.IO; +using Microsoft.Extensions.CommandLineUtils; + +namespace KoreBuild.Console.Commands +{ + internal class DependenciesGenerateCommand : SubCommandBase + { + private CommandOption _configOpt; + private CommandOption _fileOpt; + + public override void Configure(CommandLineApplication application) + { + application.Description = "Generates a build/dependencies.props file and updates csproj files to use variables"; + application.ExtendedHelpText = @" +MORE INFO: + + This command will generate a dependencies.props file and adjust all PackageReference's in csproj files + to use the MSBuild variables it generates. + + Example output: + + + + 1.0.0 + + +"; + + _configOpt = application.Option("-c|--configuration ", "The MSBuild configuration. Defaults to 'Debug'.", CommandOptionType.SingleValue); + _fileOpt = application.Option("--deps-file ", "The dependencies.props file to upgrade.", CommandOptionType.SingleValue); + + base.Configure(application); + } + + protected override int Execute() + { + var args = new List + { + "msbuild", + Path.Combine(KoreBuildDir, "KoreBuild.proj"), + "-t:GenerateDependenciesPropsFile", + }; + + if (_configOpt.HasValue()) + { + args.Add("-p:Configuration=" + _configOpt.Value()); + } + + if (_fileOpt.HasValue()) + { + var filePath = _fileOpt.Value(); + if (!Path.IsPathRooted(filePath)) + { + filePath = Path.GetFullPath(filePath); + } + + args.Add("-p:DependencyVersionsFile=" + filePath); + } + + if (Reporter.IsVerbose) + { + args.Add("-v:n"); + } + + return RunDotnet(args, RepoPath); + } + } +} diff --git a/tools/KoreBuild.Console/Commands/DependenciesUpgradeCommand.cs b/tools/KoreBuild.Console/Commands/DependenciesUpgradeCommand.cs new file mode 100644 index 0000000..0c87df7 --- /dev/null +++ b/tools/KoreBuild.Console/Commands/DependenciesUpgradeCommand.cs @@ -0,0 +1,88 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using System.IO; +using Microsoft.Extensions.CommandLineUtils; + +namespace KoreBuild.Console.Commands +{ + internal class DependenciesUpgradeCommand : SubCommandBase + { + private CommandOption _sourceOpt; + private CommandOption _packageIdOpt; + private CommandOption _packageVersionOpt; + private CommandOption _fileOpt; + + public override void Configure(CommandLineApplication application) + { + application.Description = "Upgrades the build/dependencies.props file to the latest package versions"; + application.ExtendedHelpText = @" +MORE INFO: + + The upgrade uses a 'lineup' package as the source of information about which versions to use. + + A lineup package is simply a nuget package that contains a file in build/dependencies.props. + Just like the version of the file in this local repo, this file is an MSBuild project file + with a list of MSBuild variables. Example: + + + + 1.0.0 + + +"; + + _sourceOpt = application.Option("-s|--source ", + "Specifies a NuGet package source to use to upgrade dependencies to the latest lineup package.", CommandOptionType.SingleValue); + _packageIdOpt = application.Option("--id ", "Specifies the lineup package id to use.", CommandOptionType.SingleValue); + _packageVersionOpt = application.Option("--version ", "Specifies the lineup package version to use.", CommandOptionType.SingleValue); + _fileOpt = application.Option("--deps-file ", "The dependencies.props file to upgrade.", CommandOptionType.SingleValue); + + base.Configure(application); + } + + protected override int Execute() + { + var args = new List + { + "msbuild", + Path.Combine(KoreBuildDir, "KoreBuild.proj"), + "-t:UpgradeDependencies", + }; + + if (_sourceOpt.HasValue()) + { + args.Add("-p:LineupPackageRestoreSource=" + _sourceOpt.Value()); + } + + if (_packageIdOpt.HasValue()) + { + args.Add("-p:LineupPackageId=" + _packageIdOpt.Value()); + } + + if (_packageVersionOpt.HasValue()) + { + args.Add("-p:LineupPackageVersion=" + _packageVersionOpt.Value()); + } + + if (_fileOpt.HasValue()) + { + var filePath = _fileOpt.Value(); + if (!Path.IsPathRooted(filePath)) + { + filePath = Path.GetFullPath(filePath); + } + + args.Add("-p:DependencyVersionsFile=" + filePath); + } + + if (Reporter.IsVerbose) + { + args.Add("-v:n"); + } + + return RunDotnet(args, RepoPath); + } + } +} diff --git a/tools/KoreBuild.Console/Commands/RootCommand.cs b/tools/KoreBuild.Console/Commands/RootCommand.cs index a825253..00bc3a8 100644 --- a/tools/KoreBuild.Console/Commands/RootCommand.cs +++ b/tools/KoreBuild.Console/Commands/RootCommand.cs @@ -12,10 +12,36 @@ namespace KoreBuild.Console.Commands { application.FullName = "korebuild"; - application.Command("install-tools", new InstallToolsCommand().Configure, throwOnUnexpectedArg:false); - application.Command("msbuild", new MSBuildCommand().Configure, throwOnUnexpectedArg:false); + application.Command("install-tools", new InstallToolsCommand().Configure, throwOnUnexpectedArg: false); + application.Command("msbuild", new MSBuildCommand().Configure, throwOnUnexpectedArg: false); application.Command("docker-build", new DockerBuildCommand().Configure, throwOnUnexpectedArg: false); + // Commands that upgrade things + application.Command("upgrade", c => + { + c.HelpOption("-h|--help"); + c.Command("deps", new DependenciesUpgradeCommand().Configure); + + c.OnExecute(() => + { + c.ShowHelp(); + return 2; + }); + }); + + // Commands that generate code and files + application.Command("generate", c => + { + c.HelpOption("-h|--help"); + c.Command("deps", new DependenciesGenerateCommand().Configure); + + c.OnExecute(() => + { + c.ShowHelp(); + return 2; + }); + }); + application.VersionOption("--version", GetVersion); base.Configure(application); diff --git a/tools/KoreBuild.Console/Commands/SubCommandBase.cs b/tools/KoreBuild.Console/Commands/SubCommandBase.cs index b7f1d3f..6efcc4e 100644 --- a/tools/KoreBuild.Console/Commands/SubCommandBase.cs +++ b/tools/KoreBuild.Console/Commands/SubCommandBase.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; @@ -23,8 +24,20 @@ namespace KoreBuild.Console.Commands private CommandOption _verbose; private string _koreBuildDir; + private CommandOption _korebuildOverrideOpt; + + public string KoreBuildDir + { + get + { + if (_koreBuildDir == null) + { + _koreBuildDir = FindKoreBuildDirectory(); + } + return _koreBuildDir; + } + } - public string KoreBuildDir => _koreBuildDir; public string ConfigDirectory => Path.Combine(KoreBuildDir, "config"); public string RepoPath => _repoPathOption.HasValue() ? _repoPathOption.Value() : Directory.GetCurrentDirectory(); public string DotNetHome => GetDotNetHome(); @@ -35,10 +48,12 @@ namespace KoreBuild.Console.Commands public override void Configure(CommandLineApplication application) { - _koreBuildDir = FindKoreBuildDirectory(); - base.Configure(application); + _korebuildOverrideOpt = application.Option("--korebuild-override ", "Where is KoreBuild?", CommandOptionType.SingleValue); + // for local development only + _korebuildOverrideOpt.ShowInHelpText = false; + _verbose = application.Option("-v|--verbose", "Show verbose output", CommandOptionType.NoValue); _toolsSourceOption = application.Option("--tools-source", "The source to draw tools from.", CommandOptionType.SingleValue); _repoPathOption = application.Option("--repo-path", "The path to the repo to work on.", CommandOptionType.SingleValue); @@ -57,16 +72,29 @@ namespace KoreBuild.Console.Commands return base.IsValid(); } - protected int RunDotnet(string[] arugments) + protected int RunDotnet(params string[] arguments) + => RunDotnet(arguments, Directory.GetCurrentDirectory()); + + protected int RunDotnet(IEnumerable arguments, string workingDir) { - var args = ArgumentEscaper.EscapeAndConcatenate(arugments); + var args = ArgumentEscaper.EscapeAndConcatenate(arguments); + + // use the dotnet.exe file used to start this process + var dotnet = DotNetMuxer.MuxerPath; + // if it could not be found, fallback to detecting DOTNET_HOME or PATH + dotnet = string.IsNullOrEmpty(dotnet) || !Path.IsPathRooted(dotnet) + ? GetDotNetExecutable() + : dotnet; var psi = new ProcessStartInfo { - FileName = GetDotNetExecutable(), - Arguments = args + FileName = dotnet, + Arguments = args, + WorkingDirectory = workingDir, }; + Reporter.Verbose($"Executing '{psi.FileName} {psi.Arguments}'"); + var process = Process.Start(psi); process.WaitForExit(); @@ -116,6 +144,11 @@ namespace KoreBuild.Console.Commands private string FindKoreBuildDirectory() { + if (_korebuildOverrideOpt.HasValue()) + { + return Path.GetFullPath(_korebuildOverrideOpt.Value()); + } + var executingDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); var root = Directory.GetDirectoryRoot(executingDir); while (executingDir != root) diff --git a/tools/KoreBuild.Console/Reporter/IReporter.cs b/tools/KoreBuild.Console/Reporter/IReporter.cs index f5de0ad..e572614 100644 --- a/tools/KoreBuild.Console/Reporter/IReporter.cs +++ b/tools/KoreBuild.Console/Reporter/IReporter.cs @@ -9,5 +9,6 @@ namespace Microsoft.Extensions.Tools.Internal void Output(string message); void Warn(string message); void Error(string message); + bool IsVerbose { get; } } }