diff --git a/src/NuGet.Core/NuGet.CommandLine.XPlat/Commands/PushCommand.cs b/src/NuGet.Core/NuGet.CommandLine.XPlat/Commands/PushCommand.cs index 1facb2b2f0a..b53cae72ca4 100644 --- a/src/NuGet.Core/NuGet.CommandLine.XPlat/Commands/PushCommand.cs +++ b/src/NuGet.Core/NuGet.CommandLine.XPlat/Commands/PushCommand.cs @@ -36,6 +36,11 @@ public static void Register(CommandLineApplication app, Func getLogger) Strings.SymbolSource_Description, CommandOptionType.SingleValue); + var configurationFile = push.Option( + "--config-file ", + Strings.Option_ConfigFile, + CommandOptionType.SingleValue); + var timeout = push.Option( "-t|--timeout ", Strings.Push_Timeout_Description, @@ -105,7 +110,9 @@ public static void Register(CommandLineApplication app, Func getLogger) } #pragma warning disable CS0618 // Type or member is obsolete - var sourceProvider = new PackageSourceProvider(XPlatUtility.GetSettingsForCurrentWorkingDirectory(), enablePackageSourcesChangedEvent: false); + var sourceProvider = new PackageSourceProvider( + XPlatUtility.ProcessConfigFile(configurationFile.Value()), + enablePackageSourcesChangedEvent: false); #pragma warning restore CS0618 // Type or member is obsolete try diff --git a/src/NuGet.Core/NuGet.Commands/CommandRunners/PushRunner.cs b/src/NuGet.Core/NuGet.Commands/CommandRunners/PushRunner.cs index 5cb8898431f..7513a2b367d 100644 --- a/src/NuGet.Core/NuGet.Commands/CommandRunners/PushRunner.cs +++ b/src/NuGet.Core/NuGet.Commands/CommandRunners/PushRunner.cs @@ -95,7 +95,8 @@ public static Task Run( bool skipDuplicate, ILogger logger) { - return Run(settings: settings, + return Run( + settings: settings, sourceProvider: sourceProvider, packagePaths: new[] { packagePath }, source: source, diff --git a/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/NuGetPushCommandTest.cs b/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/NuGetPushCommandTest.cs index 7e843e4a6d0..1273ee409bc 100644 --- a/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/NuGetPushCommandTest.cs +++ b/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/NuGetPushCommandTest.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Net; using System.Security.Principal; @@ -11,6 +12,7 @@ using NuGet.Common; using NuGet.Configuration; using NuGet.Test.Utility; +using FileSystemUtils = NuGet.Test.Utility.TestFileSystemUtility; using Test.Utility; using Xunit; @@ -19,7 +21,11 @@ namespace NuGet.CommandLine.Test public class NuGetPushCommandTest { private const string ApiKeyHeader = "X-NuGet-ApiKey"; + private const string Param_ConfigFile = "-ConfigFile"; + private const string Param_Source = "-Source"; + private const string Command_Push = "push"; private static readonly string NuGetExePath = Util.GetNuGetExePath(); + private static readonly string CurrentDirectoryPath = Directory.GetCurrentDirectory(); // Tests pushing to a source that is a v2 file system directory. [Fact] @@ -34,7 +40,7 @@ public void PushCommand_PushToV2FileSystemSource() var packageFileName = Util.CreateTestPackage("testPackage1", "1.1.0", packageDirectory); // Act - string[] args = new string[] { "push", packageFileName, "-Source", source }; + string[] args = new string[] { Command_Push, packageFileName, Param_Source, source }; var result = CommandRunner.Run( nugetexe, Directory.GetCurrentDirectory(), @@ -70,7 +76,7 @@ public void PushCommand_PushToV3FileSystemSource() var packageFileName = Util.CreateTestPackage(packageId, version, packageDirectory); // Act - string[] args = new string[] { "push", packageFileName, "-Source", source }; + string[] args = new string[] { Command_Push, packageFileName, Param_Source, source }; var result = CommandRunner.Run( nugetexe, Directory.GetCurrentDirectory(), @@ -109,7 +115,7 @@ public void PushCommand_PushToV2AbsoluteFileSystemDefaultPushSource() File.WriteAllText(configFileName, config); // Act - string[] args = new string[] { "push", packageFileName }; + string[] args = new string[] { Command_Push, packageFileName }; var result = CommandRunner.Run( nugetexe, packageDirectory, @@ -149,7 +155,7 @@ public void PushCommand_PushToV2RelativeFileSystemDefaultPushSource() File.WriteAllText(configFileName, config); // Act - string[] args = new string[] { "push", packageFileName }; + string[] args = new string[] { Command_Push, packageFileName }; var result = CommandRunner.Run( nugetexe, packageDirectory, @@ -186,7 +192,7 @@ public void PushCommand_PushToV2NamedDefaultPushSource() File.WriteAllText(configFileName, config); // Act - string[] args = new string[] { "push", packageFileName }; + string[] args = new string[] { Command_Push, packageFileName }; var result = CommandRunner.Run( nugetexe, packageDirectory, @@ -215,7 +221,7 @@ public void PushCommand_PushToFileSystemSourceUnixStyle() var source = ((string)windowsSource).Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); // Act - string[] args = new string[] { "push", packageFileName, "-Source", source }; + string[] args = new string[] { Command_Push, packageFileName, Param_Source, source }; var result = CommandRunner.Run( nugetexe, Directory.GetCurrentDirectory(), @@ -243,7 +249,7 @@ public void PushCommand_PushToFileSystemSourceUncStyle() var uncSource = @"\\localhost\" + ((string)source).Replace(':', '$'); // Act - string[] args = new string[] { "push", packageFileName, "-Source", uncSource }; + string[] args = new string[] { Command_Push, packageFileName, Param_Source, uncSource }; var result = CommandRunner.Run( nugetexe, Directory.GetCurrentDirectory(), @@ -322,7 +328,7 @@ public void PushCommand_LogsServerWarningsWhenPresent(string firstServerWarning, // Act var args = new string[] - {"push", packageFileName, "-Source", server.Uri + "push", "-Apikey", "token"}; + {Command_Push, packageFileName, Param_Source, server.Uri + Command_Push, "-Apikey", "token"}; var result = CommandRunner.Run( nugetexe, Directory.GetCurrentDirectory(), @@ -559,7 +565,7 @@ public void PushCommand_PushToServerFollowRedirection() server.Start(); // Act - string[] args = new string[] { "push", packageFileName, "-Source", server.Uri + "redirect" }; + string[] args = new string[] { Command_Push, packageFileName, Param_Source, server.Uri + "redirect" }; var result = CommandRunner.Run( nugetexe, Directory.GetCurrentDirectory(), @@ -600,7 +606,7 @@ public void PushCommand_PushToServerWithInfiniteRedirectionLoop() server.Start(); // Act - string[] args = new string[] { "push", packageFileName, "-Source", server.Uri + "redirect" }; + string[] args = new string[] { Command_Push, packageFileName, Param_Source, server.Uri + "redirect" }; var result = CommandRunner.Run( nugetexe, Directory.GetCurrentDirectory(), @@ -633,7 +639,7 @@ public void PushCommand_PushToServerWithInvalidRedirectionLocation() server.Start(); // Act - string[] args = new string[] { "push", packageFileName, "-Source", server.Uri + "redirect" }; + string[] args = new string[] { Command_Push, packageFileName, Param_Source, server.Uri + "redirect" }; var result = CommandRunner.Run( nugetexe, Directory.GetCurrentDirectory(), @@ -1343,9 +1349,9 @@ public void PushCommand_PushToServerV3() // Act string[] args = new string[] { - "push", + Command_Push, packageFileName, - "-Source", + Param_Source, serverV3.Uri + "index.json" }; @@ -1465,9 +1471,9 @@ public void PushCommand_PushToServerV3_Unavailable() // Act string[] args = new string[] { - "push", + Command_Push, packageFileName, - "-Source", + Param_Source, serverV3.Uri + "index.json" }; @@ -1585,10 +1591,10 @@ public void PushCommand_PushToServer_ApiKeyAsNamedArgument() // Act var args = new[] { - "push", + Command_Push, packageFileName, "should-be-ignored", // The named argument is preferred over the positional argument. - "-Source", + Param_Source, serverV3.Uri + "index.json", "-ApiKey", testApiKey, @@ -1674,9 +1680,9 @@ public void PushCommand_PushToServerV3_ApiKeyFromConfig(string configKeyFormatSt // Act var args = new[] { - "push", + Command_Push, packageFileName, - "-Source", + Param_Source, "nuget.org", "-ConfigFile", settings.ConfigPath, @@ -2078,6 +2084,339 @@ public void PushCommand_PushToServerV3_WithSymbols_ApiKey_SymbolApiKey_BothFromC } } + [Theory] + [InlineData(">")] + public void PushCommand_ConfigFile_BadName(string configFileName) + { + var args = new string[] + { + Command_Push, + "testPackage1", + Param_ConfigFile, + configFileName + }; + + var result = CommandRunner.Run( + NuGetExePath, + CurrentDirectoryPath, + string.Join(" ", args), + true); + + Assert.True( + result.ExitCode != 0, + "The run did not fail as desired. Simply got this output:" + result.Output); + + Assert.True( + result.Errors.Contains("Illegal characters in path."), + "Expected error message not found in " + result.Errors); + } + + [Fact] + public void PushCommand_ConfigFile_MissingName() + { + var args = new string[] + { + Command_Push, + "testPackage1", + Param_ConfigFile + }; + + var result = CommandRunner.Run( + NuGetExePath, + CurrentDirectoryPath, + string.Join(" ", args), + true); + + Assert.True( + result.ExitCode != 0, + "The run did not fail as desired. Simply got this output:" + result.Output); + + Assert.True( + result.Errors.Contains( + string.Format( + CultureInfo.InvariantCulture, + "Missing option value for: '{0}'", + Param_ConfigFile)), + "Expected error message not found in " + result.Errors); + } + + [Fact] + public void PushCommand_ConfigFile_NotFound() + { + var configFileName = "My.Config"; + + // Act + var args = new string[] + { + Command_Push, + "testPackage1", + Param_ConfigFile, + configFileName + }; + + var result = CommandRunner.Run( + NuGetExePath, + CurrentDirectoryPath, + string.Join(" ", args), + true); + + // Assert + Assert.True( + result.ExitCode != 0, + "The run did not fail as desired. Simply got this output:" + result.Output); + + var expectedError = string.Format( + CultureInfo.InvariantCulture, + "File '{0}' does not exist.", + Path.Combine(CurrentDirectoryPath, configFileName).ToString()); + + Assert.True( + result.Errors.Contains(expectedError), + string.Format( + CultureInfo.InvariantCulture, + "Expected error: {0} \r\nActual error: {1}", + expectedError, result.Errors)); + } + + [Fact] + public void PushCommand_ConfigFile_BadFormat() + { + var configFileName = "My.Config"; + var repositoryKey = "MySource"; + + using (var testDirectory = TestDirectory.Create()) + { + var repositoryPath = Path.Combine(testDirectory, "repository"); + var configFilePath = Path.Combine(testDirectory, "config"); + Directory.CreateDirectory(repositoryPath); + Directory.CreateDirectory(configFilePath); + + var packageFileName = Util.CreateTestPackage("testPackage1", "1.1.0", testDirectory); + + FileSystemUtils.CreateFile( + configFilePath, + configFileName, + string.Format( + CultureInfo.InvariantCulture, + @"Not XML!")); + + var args = new string[] + { + Command_Push, + packageFileName, + Param_Source, + repositoryKey, + Param_ConfigFile, + Path.Combine(configFilePath, configFileName) + }; + + var result = CommandRunner.Run( + NuGetExePath, + testDirectory, + string.Join(" ", args), + true); + + // TODO: The bad config file is ignored, so I need to confirm this is expected behavior. + // This test needs to be updated before merging since it is failing 100%. + Assert.True( + result.ExitCode != 0, + "The run did not fail as desired. Simply got this output:" + result.Output); + + var expectedError = string.Format( + CultureInfo.InvariantCulture, + "Invalid file '{0}'", + Path.Combine(CurrentDirectoryPath, configFileName).ToString()); + + Assert.True( + result.Errors.Contains("NuGet.Config is not valid XML."), + string.Format( + CultureInfo.InvariantCulture, + "Error was expected to contain: {0} \r\nActual error: {1}", + expectedError, result.Errors)); + + Assert.False( + File.Exists(Path.Combine(repositoryPath, packageFileName)), + string.Format( + CultureInfo.InvariantCulture, + @"The package {0} was found in {1}", + packageFileName, repositoryPath)); + } + } + + [Fact] + public void PushCommand_ConfigFile_ExpectedFormat() + { + var configFileName = "My.Config"; + var repositoryKey = "MySource"; + + using (var testDirectory = TestDirectory.Create()) + { + var repositoryPath = Path.Combine(testDirectory, "repository"); + var configFilePath = Path.Combine(testDirectory, "config"); + Directory.CreateDirectory(repositoryPath); + Directory.CreateDirectory(configFilePath); + + var packageFileName = Util.CreateTestPackage("testPackage1", "1.1.0", testDirectory); + + FileSystemUtils.CreateFile( + configFilePath, + configFileName, + string.Format( + CultureInfo.InvariantCulture, + @" + + + + + ", + repositoryKey, repositoryPath)); + + var args = new string[] + { + Command_Push, + packageFileName, + Param_Source, + repositoryKey, + Param_ConfigFile, + Path.Combine(configFilePath, configFileName) + }; + + var result = CommandRunner.Run( + NuGetExePath, + testDirectory, + string.Join(" ", args), + true); + + // Assert + Assert.True( + result.ExitCode == 0, + "Execution failed with:" + result.Output); + + Assert.True( + File.Exists(Path.Combine(repositoryPath, packageFileName)), + string.Format( + CultureInfo.InvariantCulture, + @"The package {0} was not found in {1}", + packageFileName, repositoryPath)); + } + } + + [Fact] + public void PushCommand_ConfigFile_ParamsOverrideConfigFile() + { + var configFileName = "My.Config"; + var testRepository1 = "repository1"; + var testRepository2 = "repository2"; + + using (var testDirectory = TestDirectory.Create()) + { + var repository1Path = Path.Combine(testDirectory, testRepository1); + var repository2Path = Path.Combine(testDirectory, testRepository2); + var configFilePath = Path.Combine(testDirectory, "config"); + Directory.CreateDirectory(repository1Path); + Directory.CreateDirectory(repository2Path); + Directory.CreateDirectory(configFilePath); + + var packageFileName = Util.CreateTestPackage("testPackage1", "1.1.0", testDirectory); + + FileSystemUtils.CreateFile( + configFilePath, + configFileName, + string.Format( + CultureInfo.InvariantCulture, + @" + + + + + ", + repository1Path)); + + var args = new string[] + { + Command_Push, + packageFileName, + Param_Source, + repository2Path, + Param_ConfigFile, + Path.Combine(configFilePath, configFileName) + }; + + var result = CommandRunner.Run( + NuGetExePath, + testDirectory, + string.Join(" ", args), + true); + + // Assert + Assert.True( + result.ExitCode == 0, + "Execution failed with:" + result.Output); + + Assert.True( + File.Exists(Path.Combine(repository2Path, packageFileName)), + string.Format( + CultureInfo.InvariantCulture, + @"The package {0} was not found in {1}", + packageFileName, repository2Path)); + } + } + + [Fact] + public void PushCommand_ConfigFile_NoSourceParam() + { + var configFileName = "My.Config"; + var testRepository = "repository"; + + using (var testDirectory = TestDirectory.Create()) + { + var repositoryPath = Path.Combine(testDirectory, testRepository); + var configFilePath = Path.Combine(testDirectory, "config"); + Directory.CreateDirectory(repositoryPath); + Directory.CreateDirectory(configFilePath); + + var packageFileName = Util.CreateTestPackage("testPackage1", "1.1.0", testDirectory); + + FileSystemUtils.CreateFile( + configFilePath, + configFileName, + string.Format( + CultureInfo.InvariantCulture, + @" + + + + + ", + repositoryPath)); + + var args = new string[] + { + Command_Push, + packageFileName, + Param_ConfigFile, + Path.Combine(configFilePath, configFileName) + }; + + var result = CommandRunner.Run( + NuGetExePath, + testDirectory, + string.Join(" ", args), + true); + + Assert.True( + result.ExitCode == 0, + "Execution failed with:" + result.Output); + + Assert.True( + File.Exists(Path.Combine(repositoryPath, packageFileName)), + string.Format( + CultureInfo.InvariantCulture, + @"The package {0} was not found in {1}", + packageFileName, repositoryPath)); + } + } + [Fact] public void PushCommand_FailWhenNoSourceSpecified() { @@ -2093,7 +2432,7 @@ public void PushCommand_FailWhenNoSourceSpecified() // Act string[] args = new string[] { - "push", + Command_Push, packageFileName, "-ApiKey", "blah-blah" @@ -2171,9 +2510,9 @@ public void PushCommand_APIV2Package_Endpoint() // Act string[] args = new string[] { - "push", + Command_Push, packageFileName, - "-Source", + Param_Source, server.Uri + "api/v2/Package" }; @@ -2207,9 +2546,9 @@ public void PushCommand_InvalidInput_NonSource(string invalidInput) // Act var args = new string[] { - "push", + Command_Push, packageFileName, - "-Source", + Param_Source, invalidInput }; @@ -2251,9 +2590,9 @@ public void PushCommand_InvalidInput_V2HttpSource(string invalidInput) // Act var args = new string[] { - "push", + Command_Push, packageFileName, - "-Source", + Param_Source, invalidInput }; @@ -2301,9 +2640,9 @@ public void PushCommand_InvalidInput_V2_NonExistent(string invalidInput) // Act var args = new string[] { - "push", + Command_Push, packageFileName, - "-Source", + Param_Source, invalidInput }; @@ -2339,9 +2678,9 @@ public void PushCommand_InvalidInput_V3_NonExistent(string invalidInput) // Act var args = new string[] { - "push", + Command_Push, packageFileName, - "-Source", + Param_Source, invalidInput }; @@ -2385,9 +2724,9 @@ public void PushCommand_InvalidInput_V3_NotFound(string invalidInput) // Act var args = new string[] { - "push", + Command_Push, packageFileName, - "-Source", + Param_Source, invalidInput }; @@ -2410,7 +2749,7 @@ public void PushCommand_InvalidInput_V3_NotFound(string invalidInput) } [Theory] - [InlineData("push")] + [InlineData(Command_Push)] [InlineData("push a b c")] [InlineData("push a b c -Timeout 2")] public void PushCommand_Failure_InvalidArguments(string cmd) @@ -2557,9 +2896,9 @@ public void PushCommand_WhenPushingToAnHttpServerV3_Warns() // Act string[] args = new string[] { - "push", + Command_Push, packageFileName, - "-Source", + Param_Source, serverV3.Uri + "index.json" }; diff --git a/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/Util.cs b/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/Util.cs index afcf17f065e..0569d2a94d3 100644 --- a/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/Util.cs +++ b/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/Util.cs @@ -310,6 +310,7 @@ public static string CreateUAPProject(string directory, string projectJsonConten return projectFile; } + // TODO: Remove CreateFile methods from this utility class. Will require changes to all classes in NuGet.CommandLine.Test. /// /// Creates a file with the specified content. /// diff --git a/test/NuGet.Core.FuncTests/NuGet.XPlat.FuncTest/XPlatPushTests.cs b/test/NuGet.Core.FuncTests/NuGet.XPlat.FuncTest/XPlatPushTests.cs index 6c71c1d18cc..b26dbcce5b8 100644 --- a/test/NuGet.Core.FuncTests/NuGet.XPlat.FuncTest/XPlatPushTests.cs +++ b/test/NuGet.Core.FuncTests/NuGet.XPlat.FuncTest/XPlatPushTests.cs @@ -1,20 +1,24 @@ // 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; using System.Collections.Generic; -using System.Diagnostics; +using System.Globalization; using System.IO; -using System.Linq; using System.Threading.Tasks; using NuGet.Configuration; using NuGet.Test.Utility; +using FileSystemUtils = NuGet.Test.Utility.TestFileSystemUtility; using Xunit; namespace NuGet.XPlat.FuncTest { public class XPlatPushTests { + private const string Command_Push = "push"; + private const string Param_ApiKey = "--api-key"; + private const string Param_ConfigFile = "--config-file"; + private const string Param_Source = "--source"; + [PackageSourceTheory] [PackageSourceData(TestSources.MyGet)] [PackageSourceData(TestSources.ProGet, Skip = "No such host is known")] @@ -22,7 +26,7 @@ public class XPlatPushTests [PackageSourceData(TestSources.NuGetServer, Skip = "No such host is known")] public async Task PushToServerSucceeds(PackageSource packageSource) { - // Arrange + // Setup using (var packageDir = TestDirectory.Create()) using (TestFileSystemUtility.SetCurrentDirectory(packageDir)) { @@ -35,23 +39,23 @@ public async Task PushToServerSucceeds(PackageSource packageSource) var apiKey = XPlatTestUtils.ReadApiKey(packageSource.Name); Assert.False(string.IsNullOrEmpty(apiKey)); - var pushArgs = new List + var pushArgs = new string[] { - "push", + Command_Push, packageFile.FullName, - "--source", + Param_Source, packageSource.Source, - "--api-key", + Param_ApiKey, apiKey, "--interactive" }; // Act - var exitCode = NuGet.CommandLine.XPlat.Program.MainInternal(pushArgs.ToArray(), log); + var exitCode = NuGet.CommandLine.XPlat.Program.MainInternal(pushArgs, log); + + // Validate + ValidateSuccessfulRun(log); - // Assert - Assert.Equal(string.Empty, log.ShowErrors()); - Assert.Equal(0, exitCode); Assert.Contains($"PUT {packageSource.Source}", log.ShowMessages()); Assert.Contains("Your package was pushed.", log.ShowMessages()); } @@ -64,7 +68,7 @@ public async Task PushToServerSucceeds(PackageSource packageSource) [PackageSourceData(TestSources.NuGetServer, Skip = "No such host is known")] public async Task PushToServerWhichRejectsDuplicates_SkipDuplicate_Succeeds(PackageSource packageSource) { - // Arrange + // Setup using (var packageDir = TestDirectory.Create()) using (TestFileSystemUtility.SetCurrentDirectory(packageDir)) { @@ -77,31 +81,29 @@ public async Task PushToServerWhichRejectsDuplicates_SkipDuplicate_Succeeds(Pack var apiKey = XPlatTestUtils.ReadApiKey(packageSource.Name); Assert.False(string.IsNullOrEmpty(apiKey)); - var pushArgs = new List + + var pushArgs = new string[] { - "push", + Command_Push, packageFile.FullName, - "--source", + Param_Source, packageSource.Source, - "--api-key", + Param_ApiKey, apiKey, "--skip-duplicate" }; // Act - var exitCodeFirstPush = NuGet.CommandLine.XPlat.Program.MainInternal(pushArgs.ToArray(), logFirstPush); - var exitCodeSecondPush = NuGet.CommandLine.XPlat.Program.MainInternal(pushArgs.ToArray(), logSecondPush); + var exitCodeFirstPush = NuGet.CommandLine.XPlat.Program.MainInternal(pushArgs, logFirstPush); + NuGet.CommandLine.XPlat.Program.MainInternal(pushArgs, logSecondPush); - // Assert First Push - it should happen without error. - var outputMessagesFirstPush = logFirstPush.ShowMessages(); - Assert.Equal(string.Empty, logFirstPush.ShowErrors()); - Assert.Equal(0, exitCodeFirstPush); + // Validate First Push - it should happen without error. + ValidateSuccessfulRun(logFirstPush); - // Assert Second Push - it should happen without error, even though a duplicate is present. + // Validate Second Push - it should happen without error, even though a duplicate is present. var outputMessagesSecondPush = logSecondPush.ShowMessages(); - Assert.Equal(string.Empty, logSecondPush.ShowErrors()); - Assert.Equal(0, exitCodeSecondPush); + ValidateSuccessfulRun(logSecondPush); Assert.Contains($"PUT {packageSource.Source}", outputMessagesSecondPush); Assert.DoesNotContain("already exists at feed", outputMessagesSecondPush); Assert.Contains("Your package was pushed.", outputMessagesSecondPush); @@ -113,7 +115,7 @@ public async Task PushToServerWhichRejectsDuplicates_SkipDuplicate_Succeeds(Pack [PackageSourceData(TestSources.Nexus, Skip = "No such host is known")] public async Task PushToServerSucceeds_DeleteFirst(PackageSource packageSource) { - // Arrange + // Setup using (var packageDir = TestDirectory.Create()) using (TestFileSystemUtility.SetCurrentDirectory(packageDir)) { @@ -128,22 +130,22 @@ public async Task PushToServerSucceeds_DeleteFirst(PackageSource packageSource) DeletePackageBeforePush(packageId, packageVersion, packageSource.Source, apiKey); - var pushArgs = new List + var pushArgs = new string[] { - "push", + Command_Push, packageFile.FullName, - "--source", + Param_Source, packageSource.Source, - "--api-key", + Param_ApiKey, apiKey }; // Act - var exitCode = NuGet.CommandLine.XPlat.Program.MainInternal(pushArgs.ToArray(), log); + NuGet.CommandLine.XPlat.Program.MainInternal(pushArgs, log); + + // Validate + ValidateSuccessfulRun(log); - // Assert - Assert.Equal(string.Empty, log.ShowErrors()); - Assert.Equal(0, exitCode); Assert.Contains($"PUT {packageSource.Source}", log.ShowMessages()); Assert.Contains("Your package was pushed.", log.ShowMessages()); } @@ -156,7 +158,7 @@ public async Task PushMultiplePathsToFileSystemSource() using (var packageDirectory = TestDirectory.Create()) using (var source = TestDirectory.Create()) { - // Arrange + // Setup var log = new TestCommandOutputLogger(); var packageInfoCollection = new[] { @@ -164,21 +166,20 @@ await TestPackagesCore.GetRuntimePackageAsync(packageDirectory, "testPackageA", await TestPackagesCore.GetRuntimePackageAsync(packageDirectory, "testPackageB", "1.1.0"), }; - var pushArgs = new List + var pushArgs = new string[] { - "push", + Command_Push, packageInfoCollection[0].FullName, packageInfoCollection[1].FullName, - "--source", + Param_Source, source, }; // Act - var exitCode = CommandLine.XPlat.Program.MainInternal(pushArgs.ToArray(), log); + CommandLine.XPlat.Program.MainInternal(pushArgs, log); - // Assert - Assert.Equal(string.Empty, log.ShowErrors()); - Assert.Equal(0, exitCode); + // Validate + ValidateSuccessfulRun(log); foreach (var packageInfo in packageInfoCollection) { @@ -188,6 +189,90 @@ await TestPackagesCore.GetRuntimePackageAsync(packageDirectory, "testPackageB", } } + [Fact] + public async Task PushCommand_ConfigFile_ExpectedFormat() + { + var log = new TestCommandOutputLogger(); + var configFileName = "My.Config"; + var repositoryKey = "MySource"; + + using (var testDirectory = TestDirectory.Create()) + { + FileInfo testPackageInfo = await TestPackagesCore.GetRuntimePackageAsync(testDirectory, "testPackageA", "1.1.0"); + var repositoryPath = Path.Combine(testDirectory, "repository"); + var configFilePath = Path.Combine(testDirectory, "config"); + Directory.CreateDirectory(repositoryPath); + Directory.CreateDirectory(configFilePath); + + FileSystemUtils.CreateFile( + configFilePath, + configFileName, + string.Format( + CultureInfo.InvariantCulture, + @" + + + + + ", + repositoryKey, repositoryPath)); + + var pushArgs = new List + { + Command_Push, + testPackageInfo.FullName, + Param_Source, + repositoryKey, + Param_ConfigFile, + Path.Combine(configFilePath, configFileName) + }; + + CommandLine.XPlat.Program.MainInternal(pushArgs.ToArray(), log); + + ValidateSuccessfulRun(log); + + Assert.True( + File.Exists(Path.Combine(repositoryPath, testPackageInfo.FullName)), + string.Format( + CultureInfo.InvariantCulture, + @"The package {0} was not found in {1}", + testPackageInfo.FullName, repositoryPath)); + } + } + + [Fact] + public void PushCommand_ConfigFile_MissingName() + { + var log = new TestCommandOutputLogger(); + + var pushArgs = new string[] + { + Command_Push, + "testPackage1", + Param_ConfigFile + }; + + var exitCode = CommandLine.XPlat.Program.MainInternal(pushArgs, log); + + Assert.True( + exitCode != 0, + "The run did not fail as desired. Simply got this output:" + log.ShowMessages()); + + string actualErrors = log.ShowErrors(); + Assert.True( + actualErrors.Contains(@"Missing value for option 'config-file'"), + "Expected error message not found in " + actualErrors); + } + + private void ValidateSuccessfulRun(TestCommandOutputLogger log) + { + Assert.True( + log.Errors == 0, + "Run was not successful. Errors:" + log.ShowErrors()); + + Assert.Equal(string.Empty, log.ShowErrors()); + } + /// /// This is called when the package must be deleted before being pushed. It's ok if this /// fails, maybe the package was never pushed. @@ -201,9 +286,9 @@ private static void DeletePackageBeforePush(string packageId, string packageVers "delete", packageId, packageVersion, - "--source", + Param_Source, sourceUri, - "--api-key", + Param_ApiKey, apiKey, "--non-interactive" }; diff --git a/test/TestUtilities/Test.Utility/TestFileSystemUtility.cs b/test/TestUtilities/Test.Utility/TestFileSystemUtility.cs index 5af2ee6938a..72beab16586 100644 --- a/test/TestUtilities/Test.Utility/TestFileSystemUtility.cs +++ b/test/TestUtilities/Test.Utility/TestFileSystemUtility.cs @@ -129,6 +129,31 @@ public static string GetNuGetExeDirectoryInRepo() return Path.Combine(ArtifactDir, "VS15"); } + /// + /// Creates a file with the specified content. + /// + /// The directory of the created file. + /// The name of the created file. + /// The content of the created file. + public static void CreateFile(string directory, string fileName, string fileContent) + { + if (!Directory.Exists(directory)) + { + Directory.CreateDirectory(directory); + } + + var fileFullName = Path.Combine(directory, fileName); + CreateFile(fileFullName, fileContent); + } + + public static void CreateFile(string fileFullName, string fileContent) + { + using (var writer = new StreamWriter(fileFullName)) + { + writer.Write(fileContent); + } + } + public static bool DeleteRandomTestFolder(string randomTestPath) { // Avoid cleaning up test folders if