Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid reinstall tool already installed #41746

Merged
merged 18 commits into from
Jun 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
c0e922c
Change test assert to check if tool already exists
caiogranero Jun 20, 2024
70bdc2f
Add method to get nuget version
caiogranero Jun 20, 2024
9b36be1
Implement method to get nuget version
caiogranero Jun 20, 2024
01b707a
Avoid reinstall a package based on nuget version
caiogranero Jun 20, 2024
92ffb3e
Handle reinstall tool already isntalled as success
caiogranero Jun 22, 2024
32abc8f
Add two tests cases to cover the correct nuget version is returned.
caiogranero Jun 22, 2024
c52a3b6
Remove unnecessary variables.
caiogranero Jun 22, 2024
7a286a5
Merge branch 'main' into avoid-reinstall-same-version
caiogranero Jun 22, 2024
94123aa
Only check nuget version if tool is installed
caiogranero Jun 22, 2024
2f6bf96
Merge branch 'avoid-reinstall-same-version' of https://github.com/cai…
caiogranero Jun 22, 2024
5166cc0
Update test/dotnet.Tests/CommandTests/ToolInstallGlobalOrToolPathComm…
caiogranero Jun 24, 2024
dd5ac7c
Include package version in output message
caiogranero Jun 24, 2024
4808282
Merge branch 'main' into avoid-reinstall-same-version
caiogranero Jun 24, 2024
c2ef39b
Merge branch 'main' into avoid-reinstall-same-version
nagilson Jun 26, 2024
eb0f9da
Wrap arguments
caiogranero Jun 26, 2024
1af62f3
Merge branch 'avoid-reinstall-same-version' of https://github.com/cai…
caiogranero Jun 26, 2024
f0b99f6
Merge branch 'main' into avoid-reinstall-same-version
caiogranero Jun 27, 2024
9588ec8
Merge branch 'main' into avoid-reinstall-same-version
caiogranero Jun 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion src/Cli/dotnet/ToolPackage/IToolPackageDownloader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,21 @@ namespace Microsoft.DotNet.Cli.ToolPackage
{
internal interface IToolPackageDownloader
{
IToolPackage InstallPackage(PackageLocation packageLocation, PackageId packageId,
IToolPackage InstallPackage(PackageLocation packageLocation,
PackageId packageId,
VerbosityOptions verbosity,
VersionRange versionRange = null,
string targetFramework = null,
bool isGlobalTool = false,
bool isGlobalToolRollForward = false
);

NuGetVersion GetNuGetVersion(
PackageLocation packageLocation,
PackageId packageId,
VerbosityOptions verbosity,
VersionRange versionRange = null,
bool isGlobalTool = false
);
}
}
34 changes: 34 additions & 0 deletions src/Cli/dotnet/ToolPackage/ToolPackageDownloader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -377,5 +377,39 @@ private static void CreateAssetFile(
lockFile.Targets.Add(lockFileTarget);
new LockFileFormat().Write(Path.Combine(assetFileDirectory.Value, "project.assets.json"), lockFile);
}

public NuGetVersion GetNuGetVersion(
PackageLocation packageLocation,
PackageId packageId,
VerbosityOptions verbosity,
VersionRange versionRange = null,
bool isGlobalTool = false)
{
ILogger nugetLogger = new NullLogger();

if (verbosity.IsDetailedOrDiagnostic())
{
nugetLogger = new NuGetConsoleLogger();
}

if (versionRange == null)
{
var versionString = "*";
versionRange = VersionRange.Parse(versionString);
}

var nugetPackageDownloader = new NuGetPackageDownloader.NuGetPackageDownloader(
packageInstallDir: isGlobalTool ? _globalToolStageDir : _localToolDownloadDir,
verboseLogger: nugetLogger,
isNuGetTool: true,
verbosityOptions: verbosity);

var packageSourceLocation = new PackageSourceLocation(
nugetConfig: packageLocation.NugetConfig,
rootConfigDirectory: packageLocation.RootConfigDirectory,
additionalSourceFeeds: packageLocation.AdditionalFeeds);

return nugetPackageDownloader.GetBestPackageVersionAsync(packageId, versionRange, packageSourceLocation).GetAwaiter().GetResult();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
using Microsoft.DotNet.Tools.Tool.List;
using static System.Formats.Asn1.AsnWriter;
using System.CommandLine.Parsing;
using static System.Threading.Lock;

namespace Microsoft.DotNet.Tools.Tool.Install
{
Expand Down Expand Up @@ -157,6 +158,17 @@ private int ExecuteInstallCommand(PackageId packageId)

IToolPackage oldPackageNullable = GetOldPackage(toolPackageStoreQuery, packageId);

if (oldPackageNullable != null)
{
NuGetVersion nugetVersion = GetBestMatchNugetVersion(packageId, versionRange, toolPackageDownloader);

if (ToolVersionAlreadyInstalled(oldPackageNullable, nugetVersion))
{
_reporter.WriteLine(string.Format(LocalizableStrings.ToolAlreadyInstalled, _packageId, oldPackageNullable.Version.ToNormalizedString()).Green());
return 0;
}
}

using (var scope = new TransactionScope(
TransactionScopeOption.Required,
TimeSpan.Zero))
Expand Down Expand Up @@ -226,6 +238,22 @@ private int ExecuteInstallCommand(PackageId packageId)
return 0;
}

private NuGetVersion GetBestMatchNugetVersion(PackageId packageId, VersionRange versionRange, IToolPackageDownloader toolPackageDownloader)
{
return toolPackageDownloader.GetNuGetVersion(
packageLocation: new PackageLocation(nugetConfig: GetConfigFile(), additionalFeeds: _source),
packageId: packageId,
versionRange: versionRange,
verbosity: _verbosity,
isGlobalTool: true
);
}

private static bool ToolVersionAlreadyInstalled(IToolPackage oldPackageNullable, NuGetVersion nuGetVersion)
{
return oldPackageNullable != null && (oldPackageNullable.Version.Version == nuGetVersion.Version);
Forgind marked this conversation as resolved.
Show resolved Hide resolved
}

private static void EnsureVersionIsHigher(IToolPackage oldPackageNullable, IToolPackage newInstalledPackage, bool allowDowngrade)
{
if (oldPackageNullable != null && (newInstalledPackage.Version < oldPackageNullable.Version && !allowDowngrade))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,53 @@ public void GivenAConfigFileRootDirectoryPackageInstallSucceedsViaFindingNugetCo
uninstaller.Uninstall(package.PackageDirectory);
}

[Theory]
[InlineData(false)]
[InlineData(true)]
public void GivenAllButNoPackageVersionItReturnLatestStableVersion(bool testMockBehaviorIsInSync)
{
var nugetConfigPath = GenerateRandomNugetConfigFilePath();

var (store, storeQuery, downloader, uninstaller, reporter, fileSystem) = Setup(
useMock: testMockBehaviorIsInSync,
writeLocalFeedToNugetConfig: nugetConfigPath);

var package = downloader.GetNuGetVersion(
new PackageLocation(nugetConfig: nugetConfigPath),
packageId: TestPackageId,
verbosity: TestVerbosity,
isGlobalTool: true);

package.OriginalVersion.Should().Be(TestPackageVersion);
}

[Theory]
[InlineData(false, "1.0.0-rc*", TestPackageVersion)]
[InlineData(true, "1.0.0-rc*", TestPackageVersion)]
[InlineData(false, "1.*", TestPackageVersion)]
[InlineData(true, "1.*", TestPackageVersion)]
[InlineData(false, TestPackageVersion, TestPackageVersion)]
[InlineData(true, TestPackageVersion, TestPackageVersion)]
public void GivenASpecificVersionGetCorrectVersion(bool testMockBehaviorIsInSync, string requestedVersion, string expectedVersion)
{
var nugetConfigPath = GenerateRandomNugetConfigFilePath();
var emptySource = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
Directory.CreateDirectory(emptySource);

var (store, storeQuery, downloader, uninstaller, reporter, fileSystem) = Setup(
useMock: testMockBehaviorIsInSync,
writeLocalFeedToNugetConfig: nugetConfigPath);

var package = downloader.GetNuGetVersion(new PackageLocation(nugetConfig: nugetConfigPath,
additionalFeeds: new[] { emptySource }),
packageId: TestPackageId,
verbosity: TestVerbosity,
versionRange: VersionRange.Parse(requestedVersion),
isGlobalTool: true);

package.OriginalVersion.Should().Be(expectedVersion);
}

[Theory]
[InlineData(false)]
[InlineData(true)]
Expand Down Expand Up @@ -689,6 +736,7 @@ public void GivenARootWithNonAsciiCharacterInstallSucceeds()
new ToolPackageUninstaller(store).Uninstall(package.PackageDirectory);
}


[Theory]
[InlineData(false)]
[InlineData(true)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public IToolPackage InstallPackage(PackageLocation packageLocation, PackageId pa
_toolDownloadDir = isGlobalTool ? _globalToolStageDir : _localToolDownloadDir;
var assetFileDirectory = isGlobalTool ? _globalToolStageDir : _localToolAssetDir;
rollbackDirectory = _toolDownloadDir.Value;

if (string.IsNullOrEmpty(packageId.ToString()))
{
throw new ToolPackageException(LocalizableStrings.ToolInstallationRestoreFailed);
Expand Down Expand Up @@ -180,10 +180,10 @@ public IToolPackage InstallPackage(PackageLocation packageLocation, PackageId pa
PackagedShims = Array.Empty<FilePath>()
};
}
else
else
{
var packageRootDirectory = _toolPackageStore.GetRootPackageDirectory(packageId);

_fileSystem.Directory.CreateDirectory(packageRootDirectory.Value);
_fileSystem.Directory.Move(_toolDownloadDir.Value, packageDirectory.Value);
rollbackDirectory = packageDirectory.Value;
Expand All @@ -201,7 +201,7 @@ public IToolPackage InstallPackage(PackageLocation packageLocation, PackageId pa
version: version,
packageDirectory: packageDirectory,
warnings: warnings, packagedShims: packedShims, frameworks: frameworks);
}
}
},
rollback: () =>
{
Expand All @@ -214,7 +214,7 @@ public IToolPackage InstallPackage(PackageLocation packageLocation, PackageId pa
{
_fileSystem.Directory.Delete(packageRootDirectory.Value, false);
}

});
}

Expand Down Expand Up @@ -300,6 +300,29 @@ private static bool ExcludeOtherFeeds(FilePath nugetConfig, MockFeed f)
|| (f.Type == MockFeedType.ExplicitNugetConfig && f.Uri == nugetConfig.Value);
}

public NuGetVersion GetNuGetVersion(
PackageLocation packageLocation,
PackageId packageId,
VerbosityOptions verbosity,
VersionRange versionRange = null,
bool isGlobalTool = false)
{
versionRange = VersionRange.Parse(versionRange?.OriginalString ?? "*");

if (string.IsNullOrEmpty(packageId.ToString()))
{
throw new ToolPackageException(LocalizableStrings.ToolInstallationRestoreFailed);
}

var feedPackage = GetPackage(
packageId.ToString(),
versionRange,
packageLocation.NugetConfig,
packageLocation.RootConfigDirectory);

return NuGetVersion.Parse(feedPackage.Version);
}

private class TestToolPackage : IToolPackage
{
public PackageId Id { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ public void WhenRunWithExactVersionItShouldSucceed()
}

[Fact]
public void WhenInstallTheSameVersionTwiceItShouldSucceed()
public void WhenInstallTheSpecificSameVersionTwiceItShouldNoop()
{
ParseResult result = Parser.Instance.Parse($"dotnet tool install -g {PackageId} --version {PackageVersion}");

Expand All @@ -402,13 +402,7 @@ public void WhenInstallTheSameVersionTwiceItShouldSucceed()

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

_reporter
.Lines
.Should()
.Equal(string.Format(
Microsoft.DotNet.Tools.Tool.Update.LocalizableStrings.UpdateSucceededStableVersionNoChange,
PackageId,
PackageVersion).Green());
_reporter.Lines.Should().Equal(string.Format(LocalizableStrings.ToolAlreadyInstalled, PackageId, PackageVersion).Green());
}

[Fact]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ public void GivenAnExistedSameVersionInstallationWhenCallItCanPrintSuccessMessag
command.Execute();

_reporter.Lines.First().Should().Contain(string.Format(
LocalizableStrings.UpdateSucceededStableVersionNoChange,
Microsoft.DotNet.Tools.Tool.Install.LocalizableStrings.ToolAlreadyInstalled,
_packageId, HigherPackageVersion));
}

Expand All @@ -306,7 +306,7 @@ public void GivenAnExistedSameVersionInstallationWhenCallWithPrereleaseItUsesAPr
command.Execute();

_reporter.Lines.First().Should().Contain(string.Format(
LocalizableStrings.UpdateSucceededPreVersionNoChange,
Microsoft.DotNet.Tools.Tool.Install.LocalizableStrings.ToolAlreadyInstalled,
_packageId, HigherPreviewPackageVersion));
}

Expand Down
Loading