| File: Commands\Tool\Install\ToolInstallLocalCommand.cs | Web Access |
| Project: src\sdk\src\Cli\dotnet\dotnet.csproj (dotnet) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.CommandLine; using System.Diagnostics; using Microsoft.DotNet.Cli.Commands.Tool.Update; using Microsoft.DotNet.Cli.Extensions; using Microsoft.DotNet.Cli.NuGetPackageDownloader; using Microsoft.DotNet.Cli.ToolManifest; using Microsoft.DotNet.Cli.ToolPackage; using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Cli.Utils.Extensions; using Microsoft.Extensions.EnvironmentAbstractions; using NuGet.Versioning; namespace Microsoft.DotNet.Cli.Commands.Tool.Install; internal sealed class ToolInstallLocalCommand : CommandBase<ToolUpdateInstallCommandDefinition> { private readonly IToolManifestFinder _toolManifestFinder; private readonly IToolManifestEditor _toolManifestEditor; private readonly ILocalToolsResolverCache _localToolsResolverCache; private readonly ToolInstallLocalInstaller _toolLocalPackageInstaller; private readonly IReporter _reporter; private readonly PackageIdentityWithRange? _packageIdentityWithRange; private readonly bool _allowPackageDowngrade; private readonly string? _explicitManifestFile; private readonly bool _createManifestIfNeeded; private readonly bool _allowRollForward; private readonly bool _updateAll; internal RestoreActionConfig restoreActionConfig; public ToolInstallLocalCommand( ParseResult parseResult, IToolPackageDownloader? toolPackageDownloader = null, IToolManifestFinder? toolManifestFinder = null, IToolManifestEditor? toolManifestEditor = null, ILocalToolsResolverCache? localToolsResolverCache = null, IReporter? reporter = null, string? runtimeJsonPathForTests = null) : base(parseResult) { if (Definition is ToolUpdateCommandDefinition updateDef) { _updateAll = parseResult.GetValue(updateDef.UpdateAllOption); _packageIdentityWithRange = parseResult.GetValue(updateDef.PackageIdentityArgument); } else { var installDef = (ToolInstallCommandDefinition)Definition; _packageIdentityWithRange = parseResult.GetValue(installDef.PackageIdentityArgument); _createManifestIfNeeded = parseResult.GetValue(installDef.CreateManifestIfNeededOption); _allowRollForward = parseResult.GetValue(installDef.RollForwardOption); } _explicitManifestFile = parseResult.GetValue(Definition.ToolManifestOption); _reporter = reporter ?? Reporter.Output; _toolManifestFinder = toolManifestFinder ?? new ToolManifestFinder(new DirectoryPath(Directory.GetCurrentDirectory())); _toolManifestEditor = toolManifestEditor ?? new ToolManifestEditor(); _localToolsResolverCache = localToolsResolverCache ?? new LocalToolsResolverCache(); restoreActionConfig = Definition.RestoreOptions.ToRestoreActionConfig(parseResult); _toolLocalPackageInstaller = new ToolInstallLocalInstaller( configFilePath: parseResult.GetValue(Definition.ConfigOption), sources: parseResult.GetValue(Definition.AddSourceOption), sourceFeedOverrides: parseResult.GetValue(Definition.SourceOption), verbosity: parseResult.GetValue(Definition.VerbosityOption), toolPackageDownloader, runtimeJsonPathForTests, restoreActionConfig); _allowPackageDowngrade = parseResult.GetValue(Definition.AllowPackageDowngradeOption); } public override int Execute() { if (_updateAll) { foreach (var (manifestPackage, _) in ((IToolManifestInspector)_toolManifestFinder).Inspect()) { ExecuteInstallCommand(manifestPackage.PackageId, versionRange: null); } return 0; } // package id must be specified (UpdateToolCommandInvalidAllAndPackageId is reported otherwise): Debug.Assert(_packageIdentityWithRange != null); var packageId = new PackageId(_packageIdentityWithRange.Value.Id); var versionRange = VersionRangeUtilities.GetVersionRange( _packageIdentityWithRange.Value.VersionRange?.OriginalString, _parseResult.GetValue(Definition.VersionOption), _parseResult.GetValue(Definition.PrereleaseOption)); return ExecuteInstallCommand(packageId, versionRange); } private int ExecuteInstallCommand(PackageId packageId, VersionRange? versionRange) { FilePath manifestFile = GetManifestFilePath(); (FilePath? manifestFileOptional, string warningMessage) = _toolManifestFinder.ExplicitManifestOrFindManifestContainPackageId(_explicitManifestFile, packageId); if (warningMessage != null) { _reporter.WriteLine(warningMessage.Yellow()); } manifestFile = manifestFileOptional ?? GetManifestFilePath(); var existingPackageWithPackageId = _toolManifestFinder.Find(manifestFile).Where(p => p.PackageId.Equals(packageId)); if (!existingPackageWithPackageId.Any()) { return InstallNewTool(manifestFile, packageId, versionRange); } var existingPackage = existingPackageWithPackageId.Single(); var toolDownloadedPackage = _toolLocalPackageInstaller.Install(manifestFile, packageId, versionRange); InstallToolUpdate(existingPackage, toolDownloadedPackage, manifestFile, packageId); _localToolsResolverCache.SaveToolPackage( toolDownloadedPackage, _toolLocalPackageInstaller.TargetFrameworkToInstall); return 0; } public int InstallToolUpdate(ToolManifestPackage existingPackage, IToolPackage toolDownloadedPackage, FilePath manifestFile, PackageId packageId) { if (existingPackage.Version > toolDownloadedPackage.Version && !_allowPackageDowngrade) { throw new GracefulException( [ string.Format( CliCommandStrings.UpdateLocalToolToLowerVersion, toolDownloadedPackage.Version.ToNormalizedString(), existingPackage.Version.ToNormalizedString(), manifestFile.Value) ], isUserError: false); } else if (existingPackage.Version == toolDownloadedPackage.Version) { _reporter.WriteLine( string.Format( CliCommandStrings.UpdateLocaToolSucceededVersionNoChange, toolDownloadedPackage.Id, existingPackage.Version.ToNormalizedString(), manifestFile.Value)); } else { _toolManifestEditor.Edit( manifestFile, packageId, toolDownloadedPackage.Version, [toolDownloadedPackage.Command.Name]); _reporter.WriteLine( string.Format( CliCommandStrings.UpdateLocalToolSucceeded, toolDownloadedPackage.Id, existingPackage.Version.ToNormalizedString(), toolDownloadedPackage.Version.ToNormalizedString(), manifestFile.Value).Green()); } _localToolsResolverCache.SaveToolPackage( toolDownloadedPackage, _toolLocalPackageInstaller.TargetFrameworkToInstall); return 0; } public int InstallNewTool(FilePath manifestFile, PackageId packageId, VersionRange? versionRange) { IToolPackage toolDownloadedPackage = _toolLocalPackageInstaller.Install(manifestFile, packageId, versionRange); _toolManifestEditor.Add( manifestFile, toolDownloadedPackage.Id, toolDownloadedPackage.Version, [toolDownloadedPackage.Command.Name], _allowRollForward); _localToolsResolverCache.SaveToolPackage( toolDownloadedPackage, _toolLocalPackageInstaller.TargetFrameworkToInstall); _reporter.WriteLine( string.Format( CliCommandStrings.LocalToolInstallationSucceeded, toolDownloadedPackage.Command.Name, toolDownloadedPackage.Id, toolDownloadedPackage.Version.ToNormalizedString(), manifestFile.Value).Green()); return 0; } public FilePath GetManifestFilePath() { return string.IsNullOrWhiteSpace(_explicitManifestFile) ? _toolManifestFinder.FindFirst(_createManifestIfNeeded) : new FilePath(_explicitManifestFile); } }