dotnet-installer/src/dotnet/commands/dotnet-install/dotnet-install-tool/InstallToolCommand.cs
2018-03-08 15:49:16 -08:00

204 lines
8.3 KiB
C#

// 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;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Transactions;
using Microsoft.DotNet.Cli;
using Microsoft.DotNet.Cli.CommandLine;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Configurer;
using Microsoft.DotNet.ShellShim;
using Microsoft.DotNet.ToolPackage;
using Microsoft.Extensions.EnvironmentAbstractions;
using NuGet.Versioning;
namespace Microsoft.DotNet.Tools.Install.Tool
{
internal delegate IShellShimRepository CreateShellShimRepository(DirectoryPath? nonGlobalLocation = null);
internal delegate (IToolPackageStore, IToolPackageInstaller) CreateToolPackageStoreAndInstaller(DirectoryPath? nonGlobalLocation = null);
internal class InstallToolCommand : CommandBase
{
private readonly IEnvironmentPathInstruction _environmentPathInstruction;
private readonly IReporter _reporter;
private readonly IReporter _errorReporter;
private CreateShellShimRepository _createShellShimRepository;
private CreateToolPackageStoreAndInstaller _createToolPackageStoreAndInstaller;
private readonly PackageId _packageId;
private readonly string _packageVersion;
private readonly string _configFilePath;
private readonly string _framework;
private readonly string _source;
private readonly bool _global;
private readonly string _verbosity;
private readonly string _toolPath;
public InstallToolCommand(
AppliedOption appliedCommand,
ParseResult parseResult,
CreateToolPackageStoreAndInstaller createToolPackageStoreAndInstaller = null,
CreateShellShimRepository createShellShimRepository = null,
IEnvironmentPathInstruction environmentPathInstruction = null,
IReporter reporter = null)
: base(parseResult)
{
if (appliedCommand == null)
{
throw new ArgumentNullException(nameof(appliedCommand));
}
_packageId = new PackageId(appliedCommand.Arguments.Single());
_packageVersion = appliedCommand.ValueOrDefault<string>("version");
_configFilePath = appliedCommand.ValueOrDefault<string>("configfile");
_framework = appliedCommand.ValueOrDefault<string>("framework");
_source = appliedCommand.ValueOrDefault<string>("source");
_global = appliedCommand.ValueOrDefault<bool>("global");
_verbosity = appliedCommand.SingleArgumentOrDefault("verbosity");
_toolPath = appliedCommand.SingleArgumentOrDefault("tool-path");
var cliFolderPathCalculator = new CliFolderPathCalculator();
_createToolPackageStoreAndInstaller = createToolPackageStoreAndInstaller ?? ToolPackageFactory.CreateToolPackageStoreAndInstaller;
_environmentPathInstruction = environmentPathInstruction
?? EnvironmentPathFactory.CreateEnvironmentPathInstruction();
_createShellShimRepository = createShellShimRepository ?? ShellShimRepositoryFactory.CreateShellShimRepository;
_reporter = (reporter ?? Reporter.Output);
_errorReporter = (reporter ?? Reporter.Error);
}
public override int Execute()
{
if (string.IsNullOrWhiteSpace(_toolPath) && !_global)
{
throw new GracefulException(LocalizableStrings.InstallToolCommandNeedGlobalOrToolPath);
}
if (!string.IsNullOrWhiteSpace(_toolPath) && _global)
{
throw new GracefulException(LocalizableStrings.InstallToolCommandInvalidGlobalAndToolPath);
}
if (_configFilePath != null && !File.Exists(_configFilePath))
{
throw new GracefulException(
string.Format(
LocalizableStrings.NuGetConfigurationFileDoesNotExist,
Path.GetFullPath(_configFilePath)));
}
VersionRange versionRange = null;
if (!string.IsNullOrEmpty(_packageVersion) && !VersionRange.TryParse(_packageVersion, out versionRange))
{
throw new GracefulException(
string.Format(
LocalizableStrings.InvalidNuGetVersionRange,
_packageVersion));
}
DirectoryPath? toolPath = null;
if (_toolPath != null)
{
toolPath = new DirectoryPath(_toolPath);
}
(IToolPackageStore toolPackageStore, IToolPackageInstaller toolPackageInstaller) =
_createToolPackageStoreAndInstaller(toolPath);
IShellShimRepository shellShimRepository = _createShellShimRepository(toolPath);
// Prevent installation if any version of the package is installed
if (toolPackageStore.EnumeratePackageVersions(_packageId).FirstOrDefault() != null)
{
_errorReporter.WriteLine(string.Format(LocalizableStrings.ToolAlreadyInstalled, _packageId).Red());
return 1;
}
FilePath? configFile = null;
if (_configFilePath != null)
{
configFile = new FilePath(_configFilePath);
}
try
{
IToolPackage package = null;
using (var scope = new TransactionScope(
TransactionScopeOption.Required,
TimeSpan.Zero))
{
package = toolPackageInstaller.InstallPackage(
packageId: _packageId,
versionRange: versionRange,
targetFramework: _framework,
nugetConfig: configFile,
source: _source,
verbosity: _verbosity);
foreach (var command in package.Commands)
{
shellShimRepository.CreateShim(command.Executable, command.Name);
}
scope.Complete();
}
if (_global)
{
_environmentPathInstruction.PrintAddPathInstructionIfPathDoesNotExist();
}
_reporter.WriteLine(
string.Format(
LocalizableStrings.InstallationSucceeded,
string.Join(", ", package.Commands.Select(c => c.Name)),
package.Id,
package.Version.ToNormalizedString()).Green());
return 0;
}
catch (ToolPackageException ex)
{
throw new GracefulException(
messages: new[]
{
ex.Message,
string.Format(LocalizableStrings.ToolInstallationFailed, _packageId),
},
verboseMessages: new[] {ex.ToString()},
isUserError: false);
}
catch (ToolConfigurationException ex)
{
throw new GracefulException(
messages: new[]
{
string.Format(
LocalizableStrings.InvalidToolConfiguration,
ex.Message),
string.Format(LocalizableStrings.ToolInstallationFailedContactAuthor, _packageId)
},
verboseMessages: new[] {ex.ToString()},
isUserError: false);
}
catch (ShellShimException ex)
{
throw new GracefulException(
messages: new[]
{
string.Format(
LocalizableStrings.FailedToCreateToolShim,
_packageId,
ex.Message),
string.Format(LocalizableStrings.ToolInstallationFailed, _packageId)
},
verboseMessages: new[] {ex.ToString()},
isUserError: false);
}
}
}
}