Skip to content

Commit

Permalink
Support for install tool with prerelease flag
Browse files Browse the repository at this point in the history
  • Loading branch information
William Li committed Aug 11, 2021
1 parent f27cb45 commit 8cedad2
Show file tree
Hide file tree
Showing 11 changed files with 291 additions and 26 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.CommandLine.Parsing;
using Microsoft.DotNet.Cli;
using Microsoft.DotNet.Cli.Utils;
using NuGet.Versioning;

namespace Microsoft.DotNet.Tools.Tool.Install
{
internal static class ParseResultExtension
{
public static VersionRange GetVersionRange(this ParseResult parseResult)
{
string packageVersion = parseResult.ValueForOption<string>(ToolInstallCommandParser.VersionOption);
bool prerelease = parseResult.ValueForOption<bool>(ToolInstallCommandParser.PrereleaseOption);
if (prerelease)
{
packageVersion = (packageVersion ?? "") + "*-*";
}

VersionRange versionRange = null;
if (!string.IsNullOrEmpty(packageVersion) && !VersionRange.TryParse(packageVersion, out versionRange))
{
throw new GracefulException(
string.Format(
LocalizableStrings.InvalidNuGetVersionRange,
packageVersion));
}

return versionRange;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ internal static class ToolInstallCommandParser
ArgumentHelpName = LocalizableStrings.FrameworkOptionName
};

public static readonly Option<bool> PrereleaseOption = ToolSearchCommandParser.PrereleaseOption;

public static readonly Option<VerbosityOptions> VerbosityOption = CommonOptions.VerbosityOption();

// Don't use the common options version as we don't want this to be a forwarded option
Expand All @@ -54,6 +56,7 @@ public static Command GetCommand()
command.AddOption(ToolAppliedOption.ToolManifestOption(LocalizableStrings.ManifestPathOptionDescription, LocalizableStrings.ManifestPathOptionName));
command.AddOption(AddSourceOption);
command.AddOption(FrameworkOption);
command.AddOption(PrereleaseOption);
command.AddOption(ToolCommandRestorePassThroughOptions.DisableParallelOption);
command.AddOption(ToolCommandRestorePassThroughOptions.IgnoreFailedSourcesOption);
command.AddOption(ToolCommandRestorePassThroughOptions.NoCacheOption);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,14 +97,7 @@ public override int Execute()
Path.GetFullPath(_configFilePath)));
}

VersionRange versionRange = null;
if (!string.IsNullOrEmpty(_packageVersion) && !VersionRange.TryParse(_packageVersion, out versionRange))
{
throw new GracefulException(
string.Format(
LocalizableStrings.InvalidNuGetVersionRange,
_packageVersion));
}
VersionRange versionRange = _parseResult.GetVersionRange();

DirectoryPath? toolPath = null;
if (!string.IsNullOrEmpty(_toolPath))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ namespace Microsoft.DotNet.Tools.Tool.Install
{
internal class ToolInstallLocalInstaller
{
private readonly ParseResult _parseResult;
public string TargetFrameworkToInstall { get; private set; }

private readonly IToolPackageInstaller _toolPackageInstaller;
Expand All @@ -27,6 +28,7 @@ public ToolInstallLocalInstaller(
ParseResult parseResult,
IToolPackageInstaller toolPackageInstaller = null)
{
_parseResult = parseResult;
_packageId = new PackageId(parseResult.ValueForArgument<string>(ToolInstallCommandParser.PackageIdArgument));
_packageVersion = parseResult.ValueForOption<string>(ToolInstallCommandParser.VersionOption);
_configFilePath = parseResult.ValueForOption<string>(ToolInstallCommandParser.ConfigOption);
Expand Down Expand Up @@ -60,14 +62,7 @@ public IToolPackage Install(FilePath manifestFile)
Path.GetFullPath(_configFilePath)));
}

VersionRange versionRange = null;
if (!string.IsNullOrEmpty(_packageVersion) && !VersionRange.TryParse(_packageVersion, out versionRange))
{
throw new GracefulException(
string.Format(
LocalizableStrings.InvalidNuGetVersionRange,
_packageVersion));
}
VersionRange versionRange = _parseResult.GetVersionRange();

FilePath? configFile = null;
if (!string.IsNullOrEmpty(_configFilePath))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ internal static class ToolUpdateCommandParser

public static readonly Option<string> ToolManifestOption = ToolAppliedOption.ToolManifestOption(LocalizableStrings.ManifestPathOptionDescription, LocalizableStrings.ManifestPathOptionName);

public static readonly Option<bool> PrereleaseOption = ToolSearchCommandParser.PrereleaseOption;

public static readonly Option<VerbosityOptions> VerbosityOption = ToolInstallCommandParser.VerbosityOption;

public static Command GetCommand()
Expand All @@ -42,6 +44,7 @@ public static Command GetCommand()
command.AddOption(FrameworkOption);
command.AddOption(VersionOption);
command.AddOption(ToolManifestOption);
command.AddOption(PrereleaseOption);
command.AddOption(ToolCommandRestorePassThroughOptions.DisableParallelOption);
command.AddOption(ToolCommandRestorePassThroughOptions.IgnoreFailedSourcesOption);
command.AddOption(ToolCommandRestorePassThroughOptions.NoCacheOption);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,7 @@ public override int Execute()
toolPath = new DirectoryPath(_toolPath);
}

VersionRange versionRange = null;
if (!string.IsNullOrEmpty(_packageVersion) && !VersionRange.TryParse(_packageVersion, out versionRange))
{
throw new GracefulException(
string.Format(
LocalizableStrings.InvalidNuGetVersionRange,
_packageVersion));
}
VersionRange versionRange = _parseResult.GetVersionRange();

(IToolPackageStore toolPackageStore,
IToolPackageStoreQuery toolPackageStoreQuery,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,90 @@ public void GivenAllButNoPackageVersionItCanInstallThePackage(bool testMockBehav
uninstaller.Uninstall(package.PackageDirectory);
}

[Theory]
[InlineData(false)]
[InlineData(true)]
public void GivenOfflineFeedInstallWhenCallWithprereleaseItSucceeds(bool testMockBehaviorIsInSync)
{
IToolPackageInstaller installer = null;
IToolPackageUninstaller uninstaller = null;
if (testMockBehaviorIsInSync == false)
{
var testFeedWithOnlyPreviewPackages =
Path.Combine(Path.GetTempPath(),
Path.GetRandomFileName());

Directory.CreateDirectory(testFeedWithOnlyPreviewPackages);
var tempFeed = GetTestLocalFeedPath();
File.Copy(Path.Combine(GetTestLocalFeedPath(), "global.tool.console.demo.1.0.4.nupkg"),
Path.Combine(testFeedWithOnlyPreviewPackages, "global.tool.console.demo.1.0.4.nupkg"));
File.Copy(Path.Combine(GetTestLocalFeedPath(), "global.tool.console.demo.2.0.1-preview1.nupkg"),
Path.Combine(testFeedWithOnlyPreviewPackages, "global.tool.console.demo.2.0.1-preview1.nupkg"));

var (store, storeQuery, realInstaller, realUninstaller, reporter, fileSystem) = Setup(
useMock: testMockBehaviorIsInSync,
offlineFeed: new DirectoryPath(testFeedWithOnlyPreviewPackages),
feeds: GetOfflineMockFeed());

installer = realInstaller;
uninstaller = realUninstaller;
}
else
{
var fileSystem = new FileSystemMockBuilder().Build();
var root = new DirectoryPath(_testAssetsManager
.CreateTestDirectory(nameof(GivenOfflineFeedInstallWhenCallWithprereleaseItSucceeds) +
testMockBehaviorIsInSync).Path);
var toolPackageStoreMock = new ToolPackageStoreMock(root, fileSystem);
var store = toolPackageStoreMock;
var storeQuery = toolPackageStoreMock;
installer = new ToolPackageInstallerMock(
fileSystem: fileSystem,
store: toolPackageStoreMock,
projectRestorer: new ProjectRestorerMock(
fileSystem: fileSystem,
reporter: new BufferedReporter(),
feeds: new List<MockFeed>
{
new MockFeed
{
Type = MockFeedType.ImplicitAdditionalFeed,
Packages = new List<MockFeedPackage>
{
new MockFeedPackage
{
PackageId = TestPackageId.ToString(),
Version = "1.0.4",
ToolCommandName = "SimulatorCommand"
},
new MockFeedPackage
{
PackageId = TestPackageId.ToString(),
Version = "2.0.1-preview1",
ToolCommandName = "SimulatorCommand"
}
}
}
}));
uninstaller = new ToolPackageUninstallerMock(fileSystem, toolPackageStoreMock);
}


var package = installer.InstallPackage(new PackageLocation(), packageId: TestPackageId,
versionRange: VersionRange.Parse("*-*"), targetFramework: _testTargetframework);

package.Version.ToNormalizedString().Should().Be("2.0.1-preview1");

uninstaller.Uninstall(package.PackageDirectory);

var package2 = installer.InstallPackage(new PackageLocation(), packageId: TestPackageId,
versionRange: VersionRange.Parse("2.0*-*"), targetFramework: _testTargetframework);

package2.Version.ToNormalizedString().Should().Be("2.0.1-preview1");

uninstaller.Uninstall(package.PackageDirectory);
}

[Theory]
[InlineData(false)]
[InlineData(true)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public IToolPackage InstallPackage(PackageLocation packageLocation, PackageId pa
// Write a fake project with the requested package id, version, and framework
_fileSystem.File.WriteAllText(
tempProject.Value,
$"{packageId};{versionRange?.ToString("S", new VersionRangeFormatter()) ?? "*"};{targetFramework};{stageDirectory.Value}");
$"{packageId};{versionRange?.OriginalString ?? "*"};{targetFramework};{stageDirectory.Value}");

// Perform a restore on the fake project
_projectRestorer.Restore(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,86 @@ public void WhenRunWithValidVersionRangeItShouldSucceed()
PackageVersion).Green());
}

[Fact]
public void WhenRunWithPrereleaseItShouldSucceed()
{
IToolPackageInstaller toolToolPackageInstaller = GetToolToolPackageInstallerWithPreviewInFeed();

ParseResult result = Parser.Instance.Parse($"dotnet tool install -g {PackageId} --prerelease");

var toolInstallGlobalOrToolPathCommand = new ToolInstallGlobalOrToolPathCommand(
result,
(location, forwardArguments) => (_toolPackageStore, _toolPackageStoreQuery, toolToolPackageInstaller),
_createShellShimRepository,
_environmentPathInstructionMock,
_reporter);

toolInstallGlobalOrToolPathCommand.Execute().Should().Be(0);

_reporter
.Lines
.Should()
.Contain(l => l == string.Format(
LocalizableStrings.InstallationSucceeded,
ToolCommandName,
PackageId,
"2.0.1-preview1").Green());
}

[Fact]
public void WhenRunWithPrereleaseAndPackageVersionItShouldSucceed()
{
IToolPackageInstaller toolToolPackageInstaller = GetToolToolPackageInstallerWithPreviewInFeed();

ParseResult result = Parser.Instance.Parse($"dotnet tool install -g {PackageId} --version 2.0 --prerelease");

var toolInstallGlobalOrToolPathCommand = new ToolInstallGlobalOrToolPathCommand(
result,
(location, forwardArguments) => (_toolPackageStore, _toolPackageStoreQuery, toolToolPackageInstaller),
_createShellShimRepository,
_environmentPathInstructionMock,
_reporter);

toolInstallGlobalOrToolPathCommand.Execute().Should().Be(0);

_reporter
.Lines
.Should()
.Contain(l => l == string.Format(
LocalizableStrings.InstallationSucceeded,
ToolCommandName,
PackageId,
"2.0.1-preview1").Green());
}

private IToolPackageInstaller GetToolToolPackageInstallerWithPreviewInFeed()
{
var toolToolPackageInstaller = CreateToolPackageInstaller(
feeds: new List<MockFeed>
{
new MockFeed
{
Type = MockFeedType.ImplicitAdditionalFeed,
Packages = new List<MockFeedPackage>
{
new MockFeedPackage
{
PackageId = PackageId,
Version = "1.0.4",
ToolCommandName = "SimulatorCommand"
},
new MockFeedPackage
{
PackageId = PackageId,
Version = "2.0.1-preview1",
ToolCommandName = "SimulatorCommand"
}
}
}
});
return toolToolPackageInstaller;
}

[Fact]
public void WhenRunWithoutAMatchingRangeItShouldFail()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,71 @@ public void WhenRunWithValidVersionRangeItShouldSucceed()
AssertDefaultInstallSuccess();
}

[Fact]
public void WhenRunWithPrereleaseAndPackageVersionItShouldSucceed()
{
ParseResult result =
Parser.Instance.Parse($"dotnet tool install {_packageIdA.ToString()} --version 2.0 --prerelease");

var installLocalCommand = new ToolInstallLocalCommand(
result,
GetToolToolPackageInstallerWithPreviewInFeed(),
_toolManifestFinder,
_toolManifestEditor,
_localToolsResolverCache,
_reporter);

installLocalCommand.Execute().Should().Be(0);
var manifestPackages = _toolManifestFinder.Find();
manifestPackages.Should().HaveCount(1);
var addedPackage = manifestPackages.Single();
_localToolsResolverCache.TryLoad(new RestoredCommandIdentifier(
addedPackage.PackageId,
new NuGetVersion("2.0.1-preview1"),
NuGetFramework.Parse(BundledTargetFramework.GetTargetFrameworkMoniker()),
Constants.AnyRid,
addedPackage.CommandNames.Single()),
out RestoredCommand restoredCommand
).Should().BeTrue();

_fileSystem.File.Exists(restoredCommand.Executable.Value);
}

private IToolPackageInstaller GetToolToolPackageInstallerWithPreviewInFeed()
{
List<MockFeed> feeds = new List<MockFeed>
{
new MockFeed
{
Type = MockFeedType.ImplicitAdditionalFeed,
Packages = new List<MockFeedPackage>
{
new MockFeedPackage
{
PackageId = _packageIdA.ToString(),
Version = "1.0.4",
ToolCommandName = "SimulatorCommand"
},
new MockFeedPackage
{
PackageId = _packageIdA.ToString(),
Version = "2.0.1-preview1",
ToolCommandName = "SimulatorCommand"
}
}
}
};
var toolToolPackageInstaller = (IToolPackageInstaller)new ToolPackageInstallerMock(
fileSystem: _fileSystem,
store: _toolPackageStore,
projectRestorer: new ProjectRestorerMock(
fileSystem: _fileSystem,
reporter: _reporter,
feeds: feeds),
installCallback: null);
return toolToolPackageInstaller;
}

private void AssertDefaultInstallSuccess()
{
var manifestPackages = _toolManifestFinder.Find();
Expand Down
Loading

0 comments on commit 8cedad2

Please sign in to comment.