diff --git a/src/Cli/dotnet/Commands/CliCommandStrings.resx b/src/Cli/dotnet/Commands/CliCommandStrings.resx index 75c76f009030..191ee2ca1784 100644 --- a/src/Cli/dotnet/Commands/CliCommandStrings.resx +++ b/src/Cli/dotnet/Commands/CliCommandStrings.resx @@ -2524,4 +2524,16 @@ Proceed? Tool package download needs confirmation. Run in interactive mode or use the "--yes" command-line option to confirm. {Locked="--yes"} - + + The version of the package to create + + + VERSION + + + Sets properties for the pack operation + + + PROPERTY + + \ No newline at end of file diff --git a/src/Cli/dotnet/Commands/Pack/PackCommand.cs b/src/Cli/dotnet/Commands/Pack/PackCommand.cs index 2e566e7b4201..d2cbeaf97411 100644 --- a/src/Cli/dotnet/Commands/Pack/PackCommand.cs +++ b/src/Cli/dotnet/Commands/Pack/PackCommand.cs @@ -4,7 +4,10 @@ using System.CommandLine; using Microsoft.DotNet.Cli.Commands.Restore; using Microsoft.DotNet.Cli.Extensions; +using Microsoft.DotNet.Cli.NuGetPackageDownloader; using Microsoft.DotNet.Cli.Utils; +using NuGet.Commands; +using NuGet.Packaging.Core; namespace Microsoft.DotNet.Cli.Commands.Pack; @@ -23,7 +26,6 @@ public static PackCommand FromArgs(string[] args, string? msbuildPath = null) public static PackCommand FromParseResult(ParseResult parseResult, string? msbuildPath = null) { - parseResult.ShowHelpOrErrorIfAppropriate(); var msbuildArgs = parseResult.OptionValuesToBeForwarded(PackCommandParser.GetCommand()).Concat(parseResult.GetValue(PackCommandParser.SlnOrProjectArgument) ?? []); @@ -40,16 +42,68 @@ public static PackCommand FromParseResult(ParseResult parseResult, string? msbui CommonOptions.PropertiesOption, CommonOptions.RestorePropertiesOption, PackCommandParser.TargetOption); + return new PackCommand( parsedMSBuildArgs.CloneWithAdditionalProperties(projectLocator.GetCustomDefaultConfigurationValueIfSpecified()), noRestore, msbuildPath); } + public static int RunPackCommand(ParseResult parseResult) + { + var args = parseResult.GetValue(PackCommandParser.SlnOrProjectArgument)?.ToList() ?? new List(); + + if (args.Count != 1) + { + Console.Error.WriteLine("Error: Only one .nuspec file can be packed at at time"); + return 1; + } + + var nuspecPath = args[0]; + + var packArgs = new PackArgs() + { + Path = nuspecPath, + BasePath = Path.GetDirectoryName(nuspecPath), + Logger = new NuGetConsoleLogger(), + Exclude = new List() + }; + + var properties = parseResult.GetValue(PackCommandParser.PropertiesOption); + if (properties != null) + { + foreach (var prop in properties) + { + var split = prop.Split('=', 2); + if (split.Length == 2) + packArgs.Properties[split[0]] = split[1]; + } + } + + var version = parseResult.GetValue(PackCommandParser.VersionOption); + if (!string.IsNullOrEmpty(version)) + packArgs.Version = version; + + var packCommandRunner = new PackCommandRunner(packArgs, null); + if (!packCommandRunner.RunPackageBuild()) + return 1; + return 0; + } + + public static int Run(ParseResult parseResult) { parseResult.HandleDebugSwitch(); + parseResult.ShowHelpOrErrorIfAppropriate(); + + var args = parseResult.GetValue(PackCommandParser.SlnOrProjectArgument)?.ToList() ?? new List(); + + if (args.Count > 0 && Path.GetExtension(args[0]).Equals(".nuspec", StringComparison.OrdinalIgnoreCase)) + { + return RunPackCommand(parseResult); + } + // Fallback to MSBuild-based packing return FromParseResult(parseResult).Execute(); } } diff --git a/src/Cli/dotnet/Commands/Pack/PackCommandParser.cs b/src/Cli/dotnet/Commands/Pack/PackCommandParser.cs index 2f41d253061c..49d81c5608ec 100644 --- a/src/Cli/dotnet/Commands/Pack/PackCommandParser.cs +++ b/src/Cli/dotnet/Commands/Pack/PackCommandParser.cs @@ -5,6 +5,10 @@ using Microsoft.DotNet.Cli.Commands.Build; using Microsoft.DotNet.Cli.Commands.Restore; using Microsoft.DotNet.Cli.Extensions; +using Microsoft.DotNet.Cli.NuGetPackageDownloader; +using NuGet.Commands; +using NuGet.Common; +using static Microsoft.DotNet.Cli.Commands.Run.CSharpDirective; namespace Microsoft.DotNet.Cli.Commands.Pack; @@ -60,6 +64,20 @@ internal static class PackCommandParser public static readonly Option TargetOption = CommonOptions.RequiredMSBuildTargetOption("Pack", [("_IsPacking", "true")]); + public static readonly Option VersionOption = new ForwardedOption("--version") + { + Description = CliCommandStrings.PackCmdVersionDescription, + HelpName = CliCommandStrings.PackCmdVersion, + Hidden = false + }.ForwardAsSingle(o => $"-Version={o}"); + + public static readonly Option PropertiesOption = new ForwardedOption("--properties") + { + Description = CliCommandStrings.PackCmdPropertiesDescription, + HelpName = CliCommandStrings.PackCmdProperties, + Hidden = false + }; + private static readonly Command Command = ConstructCommand(); public static Command GetCommand() @@ -86,6 +104,8 @@ private static Command ConstructCommand() command.Options.Add(ConfigurationOption); command.Options.Add(CommonOptions.DisableBuildServersOption); command.Options.Add(TargetOption); + command.Options.Add(PropertiesOption); + command.Options.Add(VersionOption); // Don't include runtime option because we want to include it specifically and allow the short version ("-r") to be used RestoreCommandParser.AddImplicitRestoreOptions(command, includeRuntimeOption: false, includeNoDependenciesOption: true); diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.cs.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.cs.xlf index fcab6e61ce88..ef1ebea29d62 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.cs.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.cs.xlf @@ -1827,6 +1827,26 @@ Nástroj {1} (verze {2}) se úspěšně nainstaloval. Do souboru manifestu {3} s Výstupní adresář, kam se mají umístit sestavené balíčky + + PROPERTY + PROPERTY + + + + Sets properties for the pack operation + Sets properties for the pack operation + + + + VERSION + VERSION + + + + The version of the package to create + The version of the package to create + + The configuration to use for building the package. The default is 'Release'. Konfigurace, která se má použít k sestavení balíčku. Výchozí hodnota je Release. diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.de.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.de.xlf index f70cb9600a52..ceb57e0826c7 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.de.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.de.xlf @@ -1827,6 +1827,26 @@ Das Tool "{1}" (Version {2}) wurde erfolgreich installiert. Der Eintrag wird der Das Ausgabeverzeichnis, in dem erstellte Pakete abgelegt werden. + + PROPERTY + PROPERTY + + + + Sets properties for the pack operation + Sets properties for the pack operation + + + + VERSION + VERSION + + + + The version of the package to create + The version of the package to create + + The configuration to use for building the package. The default is 'Release'. Die für die Paketerstellung zu verwendende Konfiguration. Der Standardwert lautet "Release". diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.es.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.es.xlf index e349ccd9aae5..5ee39417ddef 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.es.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.es.xlf @@ -1827,6 +1827,26 @@ La herramienta "{1}" (versión "{2}") se instaló correctamente. Se ha agregado Directorio de salida en el que se ubicarán los paquetes compilados. + + PROPERTY + PROPERTY + + + + Sets properties for the pack operation + Sets properties for the pack operation + + + + VERSION + VERSION + + + + The version of the package to create + The version of the package to create + + The configuration to use for building the package. The default is 'Release'. Configuración que se va a usar para compilar el paquete. El valor predeterminado es "Release". diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.fr.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.fr.xlf index 9243b52795f5..5f1ca97a59bf 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.fr.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.fr.xlf @@ -1827,6 +1827,26 @@ L'outil '{1}' (version '{2}') a été correctement installé. L'entrée est ajou Répertoire de sortie dans lequel placer les packages générés. + + PROPERTY + PROPERTY + + + + Sets properties for the pack operation + Sets properties for the pack operation + + + + VERSION + VERSION + + + + The version of the package to create + The version of the package to create + + The configuration to use for building the package. The default is 'Release'. Configuration à utiliser pour la génération du package. La valeur par défaut est « Release ». diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.it.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.it.xlf index a383e84c2284..25ebe265e8ef 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.it.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.it.xlf @@ -1827,6 +1827,26 @@ Lo strumento '{1}' versione '{2}' è stato installato. La voce è stata aggiunta Directory di output in cui inserire i pacchetti compilati. + + PROPERTY + PROPERTY + + + + Sets properties for the pack operation + Sets properties for the pack operation + + + + VERSION + VERSION + + + + The version of the package to create + The version of the package to create + + The configuration to use for building the package. The default is 'Release'. Configurazione da usare per la compilazione del pacchetto. Il valore predefinito è 'Release'. diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ja.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ja.xlf index 12b1a2d0d6e0..e73d675a75ff 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ja.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ja.xlf @@ -1827,6 +1827,26 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man ビルドしたパッケージを配置する出力ディレクトリ。 + + PROPERTY + PROPERTY + + + + Sets properties for the pack operation + Sets properties for the pack operation + + + + VERSION + VERSION + + + + The version of the package to create + The version of the package to create + + The configuration to use for building the package. The default is 'Release'. パッケージのビルドに使用する構成。既定値は 'Release' です。 diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ko.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ko.xlf index 6f1e0be285b6..24c8da1a99f1 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ko.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ko.xlf @@ -1827,6 +1827,26 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man 빌드된 패키지를 배치할 출력 디렉터리입니다. + + PROPERTY + PROPERTY + + + + Sets properties for the pack operation + Sets properties for the pack operation + + + + VERSION + VERSION + + + + The version of the package to create + The version of the package to create + + The configuration to use for building the package. The default is 'Release'. 패키지를 빌드하는 데 사용할 구성입니다. 기본값은 'Release'입니다. diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pl.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pl.xlf index 950656ce22f2..93fa78eb79d9 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pl.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pl.xlf @@ -1827,6 +1827,26 @@ Narzędzie „{1}” (wersja „{2}”) zostało pomyślnie zainstalowane. Wpis Katalog wyjściowy, w którym mają zostać umieszczone skompilowane pakiety. + + PROPERTY + PROPERTY + + + + Sets properties for the pack operation + Sets properties for the pack operation + + + + VERSION + VERSION + + + + The version of the package to create + The version of the package to create + + The configuration to use for building the package. The default is 'Release'. Konfiguracja używana do kompilowania pakietu. Wartość domyślna to „Wersja”. diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pt-BR.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pt-BR.xlf index d8bb4763fa06..cc7691180edc 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pt-BR.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pt-BR.xlf @@ -1827,6 +1827,26 @@ A ferramenta '{1}' (versão '{2}') foi instalada com êxito. A entrada foi adici O diretório de saída no qual os pacotes do build serão colocados. + + PROPERTY + PROPERTY + + + + Sets properties for the pack operation + Sets properties for the pack operation + + + + VERSION + VERSION + + + + The version of the package to create + The version of the package to create + + The configuration to use for building the package. The default is 'Release'. A configuração a ser usada para compilar o pacote. O padrão é 'Liberar'. diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ru.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ru.xlf index b605c45c2d9e..a7371cf4e3f6 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ru.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ru.xlf @@ -1827,6 +1827,26 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man Выходной каталог для размещения собранных пакетов. + + PROPERTY + PROPERTY + + + + Sets properties for the pack operation + Sets properties for the pack operation + + + + VERSION + VERSION + + + + The version of the package to create + The version of the package to create + + The configuration to use for building the package. The default is 'Release'. Конфигурация, используемая для сборки пакета. Значение по умолчанию — "Release". diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.tr.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.tr.xlf index 7eb51cb17ed3..9e1cb333604b 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.tr.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.tr.xlf @@ -1827,6 +1827,26 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man Derlenen paketlerin yerleştirileceği çıkış dizini. + + PROPERTY + PROPERTY + + + + Sets properties for the pack operation + Sets properties for the pack operation + + + + VERSION + VERSION + + + + The version of the package to create + The version of the package to create + + The configuration to use for building the package. The default is 'Release'. Paketi derlemek için kullanılacak yapılandırma. Varsayılan değer 'Release' olur. diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hans.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hans.xlf index 3d1c446d846d..b97a5bb78696 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hans.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hans.xlf @@ -1827,6 +1827,26 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man 要放置生成包的输出目录。 + + PROPERTY + PROPERTY + + + + Sets properties for the pack operation + Sets properties for the pack operation + + + + VERSION + VERSION + + + + The version of the package to create + The version of the package to create + + The configuration to use for building the package. The default is 'Release'. 用于生成包的配置。默认值为 "Release"。 diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hant.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hant.xlf index af3ea934d94f..03379a0ccc76 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hant.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hant.xlf @@ -1827,6 +1827,26 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man 放置組建套件所在的輸出目錄。 + + PROPERTY + PROPERTY + + + + Sets properties for the pack operation + Sets properties for the pack operation + + + + VERSION + VERSION + + + + The version of the package to create + The version of the package to create + + The configuration to use for building the package. The default is 'Release'. 用於建置套件的設定。預設值為 'Release'。 diff --git a/test/TestAssets/TestProjects/TestNuspecProject/PackNoCsproj.nuspec b/test/TestAssets/TestProjects/TestNuspecProject/PackNoCsproj.nuspec new file mode 100644 index 000000000000..a5c5e21cd453 --- /dev/null +++ b/test/TestAssets/TestProjects/TestNuspecProject/PackNoCsproj.nuspec @@ -0,0 +1 @@ + PackNoCsproj 1.0.0 kalebfikadu false Test pack with no csproj \ No newline at end of file diff --git a/test/TestAssets/TestProjects/TestNuspecProject/content/one.txt b/test/TestAssets/TestProjects/TestNuspecProject/content/one.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test/dotnet.Tests/CommandTests/Pack/PackTests.cs b/test/dotnet.Tests/CommandTests/Pack/PackTests.cs index ac84cf33e022..d8be23785ae0 100644 --- a/test/dotnet.Tests/CommandTests/Pack/PackTests.cs +++ b/test/dotnet.Tests/CommandTests/Pack/PackTests.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.IO.Compression; +using Microsoft.Build.Logging.StructuredLogger; namespace Microsoft.DotNet.Pack.Tests { @@ -289,5 +290,103 @@ public void DotnetPackAcceptsRuntimeOption() result.Should().Fail() .And.HaveStdOutContaining("NETSDK1083"); } + [Fact] + public void DotnetPack_AcceptsPropertiesOption() + { + var testInstance = _testAssetsManager.CopyTestAsset("TestNuspecProject") + .WithSource(); + string nuspecPath = Path.Combine(testInstance.Path, "PackNoCsproj.nuspec"); + var result = new DotnetPackCommand(Log) + .WithWorkingDirectory(testInstance.Path) + .Execute(nuspecPath, "--properties", "id=CustomID"); + + result.Should().Pass(); + + var outputDir = new DirectoryInfo(testInstance.Path); + outputDir.Should().Exist() + .And.HaveFile("PackNoCsproj.1.0.0.nupkg"); + } + + [Fact] + public void DotnetPack_AcceptsVersionOption() + { + var testInstance = _testAssetsManager.CopyTestAsset("TestNuspecProject") + .WithSource(); + string nuspecPath = Path.Combine(testInstance.Path, "PackNoCsproj.nuspec"); + var result = new DotnetPackCommand(Log) + .WithWorkingDirectory(testInstance.Path) + .Execute(nuspecPath, "--version", "1.2.3"); + + result.Should().Pass(); + + var outputDir = new DirectoryInfo(testInstance.Path); + outputDir.Should().Exist() + .And.HaveFile("PackNoCsproj.1.2.3.nupkg"); + } + + [Fact] + public void DotnetPack_AcceptsCustomProperties() + { + var testInstance = _testAssetsManager.CopyTestAsset("TestNuspecProject") + .WithSource(); + + string nuspecPath = Path.Combine(testInstance.Path, "PackNoCsproj.nuspec"); + + var result = new DotnetPackCommand(Log) + .WithWorkingDirectory(testInstance.Path) + .Execute( + nuspecPath, "--properties", "id=CustomValue", + "--properties", "authors=CustomAuthor" + ); + + result.Should().Pass(); + } + [Fact] + public void DotnetPack_AcceptsConfigurationOption() + { + var testInstance = _testAssetsManager.CopyTestAsset("TestNuspecProject") + .WithSource(); + string nuspecPath = Path.Combine(testInstance.Path, "PackNoCsproj.nuspec"); + var result = new DotnetPackCommand(Log) + .WithWorkingDirectory(testInstance.Path) + .Execute(nuspecPath, "--configuration", "Release"); + + result.Should().Pass(); + var outputDir = new DirectoryInfo(testInstance.Path); + outputDir.Should().Exist() + .And.HaveFile("PackNoCsproj.1.0.0.nupkg"); + } + + [Fact] + public void DotnetPack_AcceptsOutputOption() + { + var testInstance = _testAssetsManager.CopyTestAsset("TestNuspecProject") + .WithSource(); + string nuspecPath = Path.Combine(testInstance.Path, "PackNoCsproj.nuspec"); + string outputDirPath = Path.Combine(testInstance.Path, "output"); + + var result = new DotnetPackCommand(Log) + .WithWorkingDirectory(testInstance.Path) + .Execute(nuspecPath, "--output", outputDirPath); + result.Should().Pass(); + var outputDir = new DirectoryInfo(testInstance.Path); + outputDir.Should().Exist() + .And.HaveFile("PackNoCsproj.1.0.0.nupkg"); + } + + [Fact] + public void DotnetPack_FailsForNonExistentNuspec() + { + var testInstance = _testAssetsManager.CopyTestAsset("TestNuspecProject") + .WithSource(); + string nuspecPath = Path.Combine(testInstance.Path, "NonExistent.nuspec"); + + var result = new DotnetPackCommand(Log) + .WithWorkingDirectory(testInstance.Path) + .Execute(nuspecPath); + + result.Should().Fail(); + + } } }