2017-12-04 14:13:24 -08:00
|
|
|
// 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;
|
2018-01-17 19:26:52 -08:00
|
|
|
using System.Collections.Generic;
|
2017-12-04 14:13:24 -08:00
|
|
|
using System.IO;
|
|
|
|
using System.Linq;
|
2018-02-06 13:38:06 -08:00
|
|
|
using System.Transactions;
|
2017-12-04 14:13:24 -08:00
|
|
|
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;
|
2018-02-22 19:13:36 -08:00
|
|
|
using NuGet.Versioning;
|
2017-12-04 14:13:24 -08:00
|
|
|
|
|
|
|
namespace Microsoft.DotNet.Tools.Install.Tool
|
|
|
|
{
|
2018-03-06 15:58:05 -08:00
|
|
|
internal delegate IShellShimRepository CreateShellShimRepository(DirectoryPath? nonGlobalLocation = null);
|
|
|
|
internal delegate (IToolPackageStore, IToolPackageInstaller) CreateToolPackageStoreAndInstaller(DirectoryPath? nonGlobalLocation = null);
|
|
|
|
|
2018-01-24 10:16:27 -08:00
|
|
|
internal class InstallToolCommand : CommandBase
|
2017-12-04 14:13:24 -08:00
|
|
|
{
|
2018-01-24 10:16:27 -08:00
|
|
|
private readonly IEnvironmentPathInstruction _environmentPathInstruction;
|
|
|
|
private readonly IReporter _reporter;
|
2018-02-06 13:38:06 -08:00
|
|
|
private readonly IReporter _errorReporter;
|
2018-03-06 15:58:05 -08:00
|
|
|
private CreateShellShimRepository _createShellShimRepository;
|
|
|
|
private CreateToolPackageStoreAndInstaller _createToolPackageStoreAndInstaller;
|
2018-01-24 10:16:27 -08:00
|
|
|
|
2018-02-22 19:13:36 -08:00
|
|
|
private readonly PackageId _packageId;
|
2018-01-24 10:16:27 -08:00
|
|
|
private readonly string _packageVersion;
|
|
|
|
private readonly string _configFilePath;
|
|
|
|
private readonly string _framework;
|
|
|
|
private readonly string _source;
|
|
|
|
private readonly bool _global;
|
2018-01-17 19:26:52 -08:00
|
|
|
private readonly string _verbosity;
|
2018-03-06 15:58:05 -08:00
|
|
|
private readonly string _toolPath;
|
2017-12-04 14:13:24 -08:00
|
|
|
|
|
|
|
public InstallToolCommand(
|
|
|
|
AppliedOption appliedCommand,
|
2018-01-24 10:16:27 -08:00
|
|
|
ParseResult parseResult,
|
2018-03-06 15:58:05 -08:00
|
|
|
CreateToolPackageStoreAndInstaller createToolPackageStoreAndInstaller = null,
|
|
|
|
CreateShellShimRepository createShellShimRepository = null,
|
2018-01-24 10:16:27 -08:00
|
|
|
IEnvironmentPathInstruction environmentPathInstruction = null,
|
|
|
|
IReporter reporter = null)
|
2017-12-04 14:13:24 -08:00
|
|
|
: base(parseResult)
|
|
|
|
{
|
|
|
|
if (appliedCommand == null)
|
|
|
|
{
|
|
|
|
throw new ArgumentNullException(nameof(appliedCommand));
|
|
|
|
}
|
|
|
|
|
2018-02-22 19:13:36 -08:00
|
|
|
_packageId = new PackageId(appliedCommand.Arguments.Single());
|
2017-12-04 14:13:24 -08:00
|
|
|
_packageVersion = appliedCommand.ValueOrDefault<string>("version");
|
|
|
|
_configFilePath = appliedCommand.ValueOrDefault<string>("configfile");
|
|
|
|
_framework = appliedCommand.ValueOrDefault<string>("framework");
|
2018-01-11 13:54:02 -08:00
|
|
|
_source = appliedCommand.ValueOrDefault<string>("source");
|
2018-01-19 17:15:34 -08:00
|
|
|
_global = appliedCommand.ValueOrDefault<bool>("global");
|
2018-01-17 19:26:52 -08:00
|
|
|
_verbosity = appliedCommand.SingleArgumentOrDefault("verbosity");
|
2018-03-06 15:58:05 -08:00
|
|
|
_toolPath = appliedCommand.SingleArgumentOrDefault("tool-path");
|
2018-01-24 10:16:27 -08:00
|
|
|
|
|
|
|
var cliFolderPathCalculator = new CliFolderPathCalculator();
|
2018-01-28 13:35:04 -08:00
|
|
|
|
2018-03-06 15:58:05 -08:00
|
|
|
_createToolPackageStoreAndInstaller = createToolPackageStoreAndInstaller ?? ToolPackageFactory.CreateToolPackageStoreAndInstaller;
|
2018-01-24 10:16:27 -08:00
|
|
|
|
|
|
|
_environmentPathInstruction = environmentPathInstruction
|
2018-01-28 13:35:04 -08:00
|
|
|
?? EnvironmentPathFactory.CreateEnvironmentPathInstruction();
|
2018-03-06 15:58:05 -08:00
|
|
|
_createShellShimRepository = createShellShimRepository ?? ShellShimRepositoryFactory.CreateShellShimRepository;
|
2018-01-24 10:16:27 -08:00
|
|
|
|
2018-02-06 13:38:06 -08:00
|
|
|
_reporter = (reporter ?? Reporter.Output);
|
|
|
|
_errorReporter = (reporter ?? Reporter.Error);
|
2017-12-04 14:13:24 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
public override int Execute()
|
|
|
|
{
|
2018-03-06 15:58:05 -08:00
|
|
|
if (string.IsNullOrWhiteSpace(_toolPath) && !_global)
|
2018-01-19 17:15:34 -08:00
|
|
|
{
|
2018-03-06 15:58:05 -08:00
|
|
|
throw new GracefulException(LocalizableStrings.InstallToolCommandNeedGlobalOrToolPath);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(_toolPath) && _global)
|
|
|
|
{
|
|
|
|
throw new GracefulException(LocalizableStrings.InstallToolCommandInvalidGlobalAndToolPath);
|
2018-01-19 17:15:34 -08:00
|
|
|
}
|
2017-12-04 14:13:24 -08:00
|
|
|
|
2018-01-28 13:35:04 -08:00
|
|
|
if (_configFilePath != null && !File.Exists(_configFilePath))
|
2018-01-17 19:26:52 -08:00
|
|
|
{
|
2018-01-28 13:35:04 -08:00
|
|
|
throw new GracefulException(
|
|
|
|
string.Format(
|
|
|
|
LocalizableStrings.NuGetConfigurationFileDoesNotExist,
|
|
|
|
Path.GetFullPath(_configFilePath)));
|
|
|
|
}
|
2018-02-06 13:38:06 -08:00
|
|
|
|
2018-03-06 15:58:05 -08:00
|
|
|
|
2018-02-22 19:13:36 -08:00
|
|
|
VersionRange versionRange = null;
|
|
|
|
if (!string.IsNullOrEmpty(_packageVersion) && !VersionRange.TryParse(_packageVersion, out versionRange))
|
|
|
|
{
|
|
|
|
throw new GracefulException(
|
|
|
|
string.Format(
|
|
|
|
LocalizableStrings.InvalidNuGetVersionRange,
|
|
|
|
_packageVersion));
|
|
|
|
}
|
|
|
|
|
2018-03-06 15:58:05 -08:00
|
|
|
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)
|
2018-01-28 13:35:04 -08:00
|
|
|
{
|
|
|
|
_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))
|
2018-02-06 13:38:06 -08:00
|
|
|
{
|
2018-03-06 15:58:05 -08:00
|
|
|
package = toolPackageInstaller.InstallPackage(
|
2018-02-06 13:38:06 -08:00
|
|
|
packageId: _packageId,
|
2018-02-22 19:13:36 -08:00
|
|
|
versionRange: versionRange,
|
2018-01-28 13:35:04 -08:00
|
|
|
targetFramework: _framework,
|
|
|
|
nugetConfig: configFile,
|
2018-02-06 13:38:06 -08:00
|
|
|
source: _source,
|
|
|
|
verbosity: _verbosity);
|
|
|
|
|
2018-01-28 13:35:04 -08:00
|
|
|
foreach (var command in package.Commands)
|
|
|
|
{
|
2018-03-06 15:58:05 -08:00
|
|
|
shellShimRepository.CreateShim(command.Executable, command.Name);
|
2018-01-28 13:35:04 -08:00
|
|
|
}
|
2018-02-06 13:38:06 -08:00
|
|
|
|
2018-01-28 13:35:04 -08:00
|
|
|
scope.Complete();
|
|
|
|
}
|
2018-02-06 13:38:06 -08:00
|
|
|
|
2018-03-06 15:58:05 -08:00
|
|
|
if (_global)
|
|
|
|
{
|
|
|
|
_environmentPathInstruction.PrintAddPathInstructionIfPathDoesNotExist();
|
|
|
|
}
|
2018-02-06 13:38:06 -08:00
|
|
|
|
2018-01-28 13:35:04 -08:00
|
|
|
_reporter.WriteLine(
|
|
|
|
string.Format(
|
|
|
|
LocalizableStrings.InstallationSucceeded,
|
|
|
|
string.Join(", ", package.Commands.Select(c => c.Name)),
|
2018-02-22 19:13:36 -08:00
|
|
|
package.Id,
|
|
|
|
package.Version.ToNormalizedString()).Green());
|
2018-01-28 13:35:04 -08:00
|
|
|
return 0;
|
2017-12-04 14:13:24 -08:00
|
|
|
}
|
2018-01-28 13:35:04 -08:00
|
|
|
catch (ToolPackageException ex)
|
2017-12-04 14:13:24 -08:00
|
|
|
{
|
2018-03-08 15:49:16 -08:00
|
|
|
throw new GracefulException(
|
|
|
|
messages: new[]
|
|
|
|
{
|
|
|
|
ex.Message,
|
|
|
|
string.Format(LocalizableStrings.ToolInstallationFailed, _packageId),
|
|
|
|
},
|
|
|
|
verboseMessages: new[] {ex.ToString()},
|
|
|
|
isUserError: false);
|
2017-12-04 14:13:24 -08:00
|
|
|
}
|
|
|
|
catch (ToolConfigurationException ex)
|
|
|
|
{
|
2018-03-08 15:49:16 -08:00
|
|
|
throw new GracefulException(
|
|
|
|
messages: new[]
|
|
|
|
{
|
|
|
|
string.Format(
|
|
|
|
LocalizableStrings.InvalidToolConfiguration,
|
|
|
|
ex.Message),
|
|
|
|
string.Format(LocalizableStrings.ToolInstallationFailedContactAuthor, _packageId)
|
|
|
|
},
|
|
|
|
verboseMessages: new[] {ex.ToString()},
|
|
|
|
isUserError: false);
|
2017-12-04 14:13:24 -08:00
|
|
|
}
|
2018-01-28 13:35:04 -08:00
|
|
|
catch (ShellShimException ex)
|
|
|
|
{
|
2018-03-08 15:49:16 -08:00
|
|
|
throw new GracefulException(
|
|
|
|
messages: new[]
|
|
|
|
{
|
|
|
|
string.Format(
|
|
|
|
LocalizableStrings.FailedToCreateToolShim,
|
|
|
|
_packageId,
|
|
|
|
ex.Message),
|
|
|
|
string.Format(LocalizableStrings.ToolInstallationFailed, _packageId)
|
|
|
|
},
|
|
|
|
verboseMessages: new[] {ex.ToString()},
|
|
|
|
isUserError: false);
|
2018-01-28 13:35:04 -08:00
|
|
|
}
|
2017-12-04 14:13:24 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|