Skip to content

Commit

Permalink
Enable users to install unlisted version of tool if specify the exact…
Browse files Browse the repository at this point in the history
… match of the version of the tool (#36021)
  • Loading branch information
JL03-Yue authored Oct 19, 2023
2 parents e550065 + 7204716 commit 1ce5efa
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Task<string> DownloadPackageAsync(PackageId packageId,
NuGetVersion packageVersion = null,
PackageSourceLocation packageSourceLocation = null,
bool includePreview = false,
bool includeUnlisted = false,
DirectoryPath? downloadFolder = null,
PackageSourceMapping packageSourceMapping = null);

Expand Down
27 changes: 17 additions & 10 deletions src/Cli/dotnet/NugetPackageDownloader/NuGetPackageDownloader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,14 @@ public async Task<string> DownloadPackageAsync(PackageId packageId,
NuGetVersion packageVersion = null,
PackageSourceLocation packageSourceLocation = null,
bool includePreview = false,
bool includeUnlisted = false,
DirectoryPath? downloadFolder = null,
PackageSourceMapping packageSourceMapping = null)
{
CancellationToken cancellationToken = CancellationToken.None;

(var source, var resolvedPackageVersion) = await GetPackageSourceAndVersion(packageId, packageVersion,
packageSourceLocation, includePreview, packageSourceMapping).ConfigureAwait(false);
packageSourceLocation, includePreview, includeUnlisted, packageSourceMapping).ConfigureAwait(false);

FindPackageByIdResource resource = null;
SourceRepository repository = GetSourceRepository(source);
Expand Down Expand Up @@ -220,6 +221,7 @@ public async Task<IEnumerable<string>> ExtractPackageAsync(string packagePath, D
NuGetVersion packageVersion = null,
PackageSourceLocation packageSourceLocation = null,
bool includePreview = false,
bool includeUnlisted = false,
PackageSourceMapping packageSourceMapping = null)
{
CancellationToken cancellationToken = CancellationToken.None;
Expand All @@ -239,7 +241,7 @@ public async Task<IEnumerable<string>> ExtractPackageAsync(string packagePath, D
packageVersion = new NuGetVersion(packageVersion);
(source, packageMetadata) =
await GetPackageMetadataAsync(packageId.ToString(), packageVersion, packagesSources,
cancellationToken).ConfigureAwait(false);
cancellationToken, includeUnlisted).ConfigureAwait(false);
}

packageVersion = packageMetadata.Identity.Version;
Expand Down Expand Up @@ -421,14 +423,14 @@ private IEnumerable<PackageSource> LoadNuGetSources(PackageId packageId, Package
{
foundPackagesBySource = packageSources.Select(source => GetPackageMetadataAsync(source,
packageIdentifier,
true, cancellationToken).ConfigureAwait(false).GetAwaiter().GetResult()).ToArray();
true, false, cancellationToken).ConfigureAwait(false).GetAwaiter().GetResult()).ToArray();
}
else
{
foundPackagesBySource =
await Task.WhenAll(
packageSources.Select(source => GetPackageMetadataAsync(source, packageIdentifier,
true, cancellationToken)))
true, false, cancellationToken)))
.ConfigureAwait(false);
}

Expand Down Expand Up @@ -475,14 +477,14 @@ await Task.WhenAll(
{
foundPackagesBySource = packageSources.Select(source => GetPackageMetadataAsync(source,
packageIdentifier,
true, cancellationToken).ConfigureAwait(false).GetAwaiter().GetResult()).ToArray();
true, false, cancellationToken).ConfigureAwait(false).GetAwaiter().GetResult()).ToArray();
}
else
{
foundPackagesBySource =
await Task.WhenAll(
packageSources.Select(source => GetPackageMetadataAsync(source, packageIdentifier,
true, cancellationToken)))
true, false, cancellationToken)))
.ConfigureAwait(false);
}

Expand Down Expand Up @@ -525,6 +527,11 @@ public async Task<NuGetVersion> GetBestPackageVersionAsync(PackageId packageId,
VersionRange versionRange,
PackageSourceLocation packageSourceLocation = null)
{
if(versionRange.MinVersion != null && versionRange.MaxVersion != null && versionRange.MinVersion == versionRange.MaxVersion)
{
return versionRange.MinVersion;
}

CancellationToken cancellationToken = CancellationToken.None;
IPackageSearchMetadata packageMetadata;

Expand All @@ -539,7 +546,7 @@ public async Task<NuGetVersion> GetBestPackageVersionAsync(PackageId packageId,
}

private async Task<(PackageSource, IPackageSearchMetadata)> GetPackageMetadataAsync(string packageIdentifier,
NuGetVersion packageVersion, IEnumerable<PackageSource> sources, CancellationToken cancellationToken)
NuGetVersion packageVersion, IEnumerable<PackageSource> sources, CancellationToken cancellationToken, bool includeUnlisted = false)
{
if (string.IsNullOrWhiteSpace(packageIdentifier))
{
Expand All @@ -555,7 +562,7 @@ public async Task<NuGetVersion> GetBestPackageVersionAsync(PackageId packageId,
CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
List<Task<(PackageSource source, IEnumerable<IPackageSearchMetadata> foundPackages)>> tasks = sources
.Select(source =>
GetPackageMetadataAsync(source, packageIdentifier, true, linkedCts.Token)).ToList();
GetPackageMetadataAsync(source, packageIdentifier, true, includeUnlisted, linkedCts.Token)).ToList();

bool TryGetPackageMetadata(
(PackageSource source, IEnumerable<IPackageSearchMetadata> foundPackages) sourceAndFoundPackages,
Expand Down Expand Up @@ -621,7 +628,7 @@ bool TryGetPackageMetadata(
}

private async Task<(PackageSource source, IEnumerable<IPackageSearchMetadata> foundPackages)>
GetPackageMetadataAsync(PackageSource source, string packageIdentifier, bool includePrerelease = false,
GetPackageMetadataAsync(PackageSource source, string packageIdentifier, bool includePrerelease = false, bool includeUnlisted = false,
CancellationToken cancellationToken = default)
{
if (string.IsNullOrWhiteSpace(packageIdentifier))
Expand All @@ -643,7 +650,7 @@ bool TryGetPackageMetadata(
foundPackages = await resource.GetMetadataAsync(
packageIdentifier,
includePrerelease,
false,
includeUnlisted,
_cacheSettings,
_verboseLogger,
cancellationToken).ConfigureAwait(false);
Expand Down
13 changes: 10 additions & 3 deletions src/Cli/dotnet/ToolPackage/ToolPackageDownloader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,12 @@ public IToolPackage InstallPackage(PackageLocation packageLocation, PackageId pa
var nugetPackageDownloader = new NuGetPackageDownloader.NuGetPackageDownloader(toolDownloadDir, verboseLogger: nugetLogger, isNuGetTool: true);

var packageSourceLocation = new PackageSourceLocation(packageLocation.NugetConfig, packageLocation.RootConfigDirectory, null, packageLocation.AdditionalFeeds);

bool givenSpecificVersion = false;
if (versionRange.MinVersion != null && versionRange.MaxVersion != null && versionRange.MinVersion == versionRange.MaxVersion)
{
givenSpecificVersion = true;
}
NuGetVersion packageVersion = nugetPackageDownloader.GetBestPackageVersionAsync(packageId, versionRange, packageSourceLocation).GetAwaiter().GetResult();

rollbackDirectory = isGlobalTool ? toolDownloadDir.Value: Path.Combine(toolDownloadDir.Value, packageId.ToString(), packageVersion.ToString());
Expand All @@ -121,7 +127,7 @@ public IToolPackage InstallPackage(PackageLocation packageLocation, PackageId pa

if (package == null)
{
DownloadAndExtractPackage(packageLocation, packageId, nugetPackageDownloader, toolDownloadDir.Value, _toolPackageStore, packageVersion, packageSourceLocation).GetAwaiter().GetResult();
DownloadAndExtractPackage(packageLocation, packageId, nugetPackageDownloader, toolDownloadDir.Value, _toolPackageStore, packageVersion, packageSourceLocation, includeUnlisted: givenSpecificVersion).GetAwaiter().GetResult();
}
else if(isGlobalTool)
{
Expand Down Expand Up @@ -241,10 +247,11 @@ private static async Task<NuGetVersion> DownloadAndExtractPackage(
string packagesRootPath,
IToolPackageStore toolPackageStore,
NuGetVersion packageVersion,
PackageSourceLocation packageSourceLocation
PackageSourceLocation packageSourceLocation,
bool includeUnlisted = false
)
{
var packagePath = await nugetPackageDownloader.DownloadPackageAsync(packageId, packageVersion, packageSourceLocation).ConfigureAwait(false);
var packagePath = await nugetPackageDownloader.DownloadPackageAsync(packageId, packageVersion, packageSourceLocation, includeUnlisted: includeUnlisted).ConfigureAwait(false);

// look for package on disk and read the version
NuGetVersion version;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public FailingNuGetPackageDownloader(string testDir)
public Task<string> DownloadPackageAsync(PackageId packageId, NuGetVersion packageVersion,
PackageSourceLocation packageSourceLocation = null,
bool includePreview = false,
bool includeUnlisted = false,
DirectoryPath? downloadFolder = null,
PackageSourceMapping packageSourceMapping = null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public Task<string> DownloadPackageAsync(PackageId packageId,
NuGetVersion packageVersion = null,
PackageSourceLocation packageSourceLocation = null,
bool includePreview = false,
bool includeUnlisted = false,
DirectoryPath? downloadFolder = null,
PackageSourceMapping packageSourceMapping = null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

namespace Microsoft.DotNet.Tests.Commands.Tool
{
public class ToolInstallGlobalOrToolPathCommandTests
public class ToolInstallGlobalOrToolPathCommandTests: SdkTest
{
private readonly IFileSystem _fileSystem;
private readonly IToolPackageStore _toolPackageStore;
Expand All @@ -35,8 +35,9 @@ public class ToolInstallGlobalOrToolPathCommandTests
private const string PackageId = "global.tool.console.demo";
private const string PackageVersion = "1.0.4";
private const string ToolCommandName = "SimulatorCommand";
private readonly string UnlistedPackageId = "elemental.sysinfotool";

public ToolInstallGlobalOrToolPathCommandTests()
public ToolInstallGlobalOrToolPathCommandTests(ITestOutputHelper log): base(log)
{
_reporter = new BufferedReporter();
_fileSystem = new FileSystemMockBuilder().UseCurrentSystemTemporaryDirectory().Build();
Expand Down Expand Up @@ -351,6 +352,36 @@ public void WhenRunWithValidVersionRangeItShouldSucceed()
PackageVersion).Green());
}

[Fact]
public void WhenRunWithValidUnlistedVersionRangeItShouldSucceed()
{
const string nugetSourcePath = "https://api.nuget.org/v3/index.json";
var testDir = _testAssetsManager.CreateTestDirectory().Path;

var toolInstallGlobalOrToolPathCommand = new DotnetCommand(Log, "tool", "install", "-g", UnlistedPackageId, "--version", "[0.5.0]", "--add-source", nugetSourcePath)
.WithEnvironmentVariable("DOTNET_SKIP_WORKLOAD_INTEGRITY_CHECK", "true")
.WithWorkingDirectory(testDir);

toolInstallGlobalOrToolPathCommand.Execute().Should().Pass();

// Uninstall the unlisted package
var toolUninstallCommand = new DotnetCommand(Log, "tool", "uninstall", "-g", UnlistedPackageId);
toolUninstallCommand.Execute().Should().Pass();
}

[Fact]
public void WhenRunWithoutValidVersionUnlistedToolItShouldThrow()
{
const string nugetSourcePath = "https://api.nuget.org/v3/index.json";
var testDir = _testAssetsManager.CreateTestDirectory().Path;

var toolInstallGlobalOrToolPathCommand = new DotnetCommand(Log, "tool", "install", "-g", UnlistedPackageId, "--add-source", nugetSourcePath)
.WithEnvironmentVariable("DOTNET_SKIP_WORKLOAD_INTEGRITY_CHECK", "true")
.WithWorkingDirectory(testDir);

toolInstallGlobalOrToolPathCommand.Execute().Should().Fail();
}

[Fact]
public void WhenRunWithPrereleaseItShouldSucceed()
{
Expand Down

0 comments on commit 1ce5efa

Please sign in to comment.