Fix case sensitivity of tool package identifiers.

This commit fixes the case sensitivity of tool package identifiers.

Previously the install and uninstall commands unintentionally required the tool
package ids to specified in all lowercase for the install / uninstall to work.

Fixes #8682.
This commit is contained in:
Peter Huene 2018-02-22 19:13:36 -08:00
parent 4490fd5aa8
commit 5ebbd618ec
No known key found for this signature in database
GPG key ID: E1D265D820213D6A
44 changed files with 629 additions and 179 deletions

View file

@ -619,6 +619,9 @@ setx PATH "%PATH%;{0}"
<data name="ToolPackageConflictPackageId" xml:space="preserve"> <data name="ToolPackageConflictPackageId" xml:space="preserve">
<value>Tool '{0}' (version '{1}') is already installed.</value> <value>Tool '{0}' (version '{1}') is already installed.</value>
</data> </data>
<data name="FailedToFindStagedToolPackage" xml:space="preserve">
<value>Failed to find staged tool package '{0}'.</value>
</data>
<data name="ColumnMaxWidthMustBeGreaterThanZero" xml:space="preserve"> <data name="ColumnMaxWidthMustBeGreaterThanZero" xml:space="preserve">
<value>Column maximum width must be greater than zero.</value> <value>Column maximum width must be greater than zero.</value>
</data> </data>

View file

@ -4,14 +4,15 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.Extensions.EnvironmentAbstractions; using Microsoft.Extensions.EnvironmentAbstractions;
using NuGet.Versioning;
namespace Microsoft.DotNet.ToolPackage namespace Microsoft.DotNet.ToolPackage
{ {
internal interface IToolPackage internal interface IToolPackage
{ {
string PackageId { get; } PackageId Id { get; }
string PackageVersion { get; } NuGetVersion Version { get; }
DirectoryPath PackageDirectory { get; } DirectoryPath PackageDirectory { get; }

View file

@ -4,14 +4,15 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.Extensions.EnvironmentAbstractions; using Microsoft.Extensions.EnvironmentAbstractions;
using NuGet.Versioning;
namespace Microsoft.DotNet.ToolPackage namespace Microsoft.DotNet.ToolPackage
{ {
internal interface IToolPackageInstaller internal interface IToolPackageInstaller
{ {
IToolPackage InstallPackage( IToolPackage InstallPackage(
string packageId, PackageId packageId,
string packageVersion = null, VersionRange versionRange = null,
string targetFramework = null, string targetFramework = null,
FilePath? nugetConfig = null, FilePath? nugetConfig = null,
string source = null, string source = null,

View file

@ -4,6 +4,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.Extensions.EnvironmentAbstractions; using Microsoft.Extensions.EnvironmentAbstractions;
using NuGet.Versioning;
namespace Microsoft.DotNet.ToolPackage namespace Microsoft.DotNet.ToolPackage
{ {
@ -11,6 +12,18 @@ namespace Microsoft.DotNet.ToolPackage
{ {
DirectoryPath Root { get; } DirectoryPath Root { get; }
IEnumerable<IToolPackage> GetInstalledPackages(string packageId = null); DirectoryPath GetRandomStagingDirectory();
NuGetVersion GetStagedPackageVersion(DirectoryPath stagingDirectory, PackageId packageId);
DirectoryPath GetRootPackageDirectory(PackageId packageId);
DirectoryPath GetPackageDirectory(PackageId packageId, NuGetVersion version);
IEnumerable<IToolPackage> EnumeratePackages();
IEnumerable<IToolPackage> EnumeratePackageVersions(PackageId packageId);
IToolPackage GetPackage(PackageId packageId, NuGetVersion version);
} }
} }

View file

@ -0,0 +1,43 @@
// 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 Microsoft.DotNet.InternalAbstractions;
namespace Microsoft.DotNet.ToolPackage
{
internal struct PackageId : IEquatable<PackageId>, IComparable<PackageId>
{
private string _id;
public PackageId(string id)
{
_id = id?.ToLowerInvariant() ?? throw new ArgumentNullException(nameof(id));
}
public bool Equals(PackageId other)
{
return ToString() == other.ToString();
}
public int CompareTo(PackageId other)
{
return string.Compare(ToString(), other.ToString(), StringComparison.Ordinal);
}
public override bool Equals(object obj)
{
return obj is PackageId id && Equals(id);
}
public override int GetHashCode()
{
return ToString().GetHashCode();
}
public override string ToString()
{
return _id ?? "";
}
}
}

View file

@ -7,13 +7,12 @@ using Microsoft.DotNet.Cli;
using Microsoft.DotNet.Configurer; using Microsoft.DotNet.Configurer;
using Microsoft.DotNet.Tools; using Microsoft.DotNet.Tools;
using Microsoft.Extensions.EnvironmentAbstractions; using Microsoft.Extensions.EnvironmentAbstractions;
using NuGet.Versioning;
namespace Microsoft.DotNet.ToolPackage namespace Microsoft.DotNet.ToolPackage
{ {
internal class ToolPackageInstaller : IToolPackageInstaller internal class ToolPackageInstaller : IToolPackageInstaller
{ {
public const string StagingDirectory = ".stage";
private readonly IToolPackageStore _store; private readonly IToolPackageStore _store;
private readonly IProjectRestorer _projectRestorer; private readonly IProjectRestorer _projectRestorer;
private readonly FilePath? _tempProject; private readonly FilePath? _tempProject;
@ -32,33 +31,27 @@ namespace Microsoft.DotNet.ToolPackage
} }
public IToolPackage InstallPackage( public IToolPackage InstallPackage(
string packageId, PackageId packageId,
string packageVersion = null, VersionRange versionRange = null,
string targetFramework = null, string targetFramework = null,
FilePath? nugetConfig = null, FilePath? nugetConfig = null,
string source = null, string source = null,
string verbosity = null) string verbosity = null)
{ {
if (packageId == null) var packageRootDirectory = _store.GetRootPackageDirectory(packageId);
{
throw new ArgumentNullException(nameof(packageId));
}
var packageRootDirectory = _store.Root.WithSubDirectories(packageId);
string rollbackDirectory = null; string rollbackDirectory = null;
return TransactionalAction.Run<IToolPackage>( return TransactionalAction.Run<IToolPackage>(
action: () => { action: () => {
try try
{ {
var stageDirectory = _store.GetRandomStagingDirectory();
var stageDirectory = _store.Root.WithSubDirectories(StagingDirectory, Path.GetRandomFileName());
Directory.CreateDirectory(stageDirectory.Value); Directory.CreateDirectory(stageDirectory.Value);
rollbackDirectory = stageDirectory.Value; rollbackDirectory = stageDirectory.Value;
var tempProject = CreateTempProject( var tempProject = CreateTempProject(
packageId: packageId, packageId: packageId,
packageVersion: packageVersion, versionRange: versionRange,
targetFramework: targetFramework ?? BundledTargetFramework.GetTargetFrameworkMoniker(), targetFramework: targetFramework ?? BundledTargetFramework.GetTargetFrameworkMoniker(),
restoreDirectory: stageDirectory); restoreDirectory: stageDirectory);
@ -76,29 +69,22 @@ namespace Microsoft.DotNet.ToolPackage
File.Delete(tempProject.Value); File.Delete(tempProject.Value);
} }
packageVersion = Path.GetFileName( var version = _store.GetStagedPackageVersion(stageDirectory, packageId);
Directory.EnumerateDirectories( var packageDirectory = _store.GetPackageDirectory(packageId, version);
stageDirectory.WithSubDirectories(packageId).Value).Single());
var packageDirectory = packageRootDirectory.WithSubDirectories(packageVersion);
if (Directory.Exists(packageDirectory.Value)) if (Directory.Exists(packageDirectory.Value))
{ {
throw new ToolPackageException( throw new ToolPackageException(
string.Format( string.Format(
CommonLocalizableStrings.ToolPackageConflictPackageId, CommonLocalizableStrings.ToolPackageConflictPackageId,
packageId, packageId,
packageVersion)); version.ToNormalizedString()));
} }
Directory.CreateDirectory(packageRootDirectory.Value); Directory.CreateDirectory(packageRootDirectory.Value);
Directory.Move(stageDirectory.Value, packageDirectory.Value); Directory.Move(stageDirectory.Value, packageDirectory.Value);
rollbackDirectory = packageDirectory.Value; rollbackDirectory = packageDirectory.Value;
return new ToolPackageInstance( return new ToolPackageInstance(_store, packageId, version, packageDirectory);
_store,
packageId,
packageVersion,
packageDirectory);
} }
catch (Exception ex) when (ex is UnauthorizedAccessException || ex is IOException) catch (Exception ex) when (ex is UnauthorizedAccessException || ex is IOException)
{ {
@ -126,8 +112,8 @@ namespace Microsoft.DotNet.ToolPackage
} }
private FilePath CreateTempProject( private FilePath CreateTempProject(
string packageId, PackageId packageId,
string packageVersion, VersionRange versionRange,
string targetFramework, string targetFramework,
DirectoryPath restoreDirectory) DirectoryPath restoreDirectory)
{ {
@ -159,8 +145,9 @@ namespace Microsoft.DotNet.ToolPackage
new XElement("DisableImplicitNuGetFallbackFolder", "true")), // disable SDK side implicit NuGetFallbackFolder new XElement("DisableImplicitNuGetFallbackFolder", "true")), // disable SDK side implicit NuGetFallbackFolder
new XElement("ItemGroup", new XElement("ItemGroup",
new XElement("PackageReference", new XElement("PackageReference",
new XAttribute("Include", packageId), new XAttribute("Include", packageId.ToString()),
new XAttribute("Version", packageVersion ?? "*") // nuget will restore * for latest new XAttribute("Version",
versionRange?.ToString("S", new VersionRangeFormatter()) ?? "*") // nuget will restore latest stable for *
)) ))
)); ));

View file

@ -6,6 +6,7 @@ using Microsoft.DotNet.Cli;
using Microsoft.DotNet.Tools; using Microsoft.DotNet.Tools;
using Microsoft.Extensions.EnvironmentAbstractions; using Microsoft.Extensions.EnvironmentAbstractions;
using NuGet.ProjectModel; using NuGet.ProjectModel;
using NuGet.Versioning;
namespace Microsoft.DotNet.ToolPackage namespace Microsoft.DotNet.ToolPackage
{ {
@ -17,20 +18,21 @@ namespace Microsoft.DotNet.ToolPackage
public ToolPackageInstance( public ToolPackageInstance(
IToolPackageStore store, IToolPackageStore store,
string packageId, PackageId id,
string packageVersion, NuGetVersion version,
DirectoryPath packageDirectory) DirectoryPath packageDirectory)
{ {
_store = store ?? throw new ArgumentNullException(nameof(store)); _store = store ?? throw new ArgumentNullException(nameof(store));
PackageId = packageId ?? throw new ArgumentNullException(nameof(packageId));
PackageVersion = packageVersion ?? throw new ArgumentNullException(nameof(packageVersion));
PackageDirectory = packageDirectory;
_commands = new Lazy<IReadOnlyList<CommandSettings>>(GetCommands); _commands = new Lazy<IReadOnlyList<CommandSettings>>(GetCommands);
Id = id;
Version = version ?? throw new ArgumentNullException(nameof(version));
PackageDirectory = packageDirectory;
} }
public string PackageId { get; private set; } public PackageId Id { get; private set; }
public string PackageVersion { get; private set; } public NuGetVersion Version { get; private set; }
public DirectoryPath PackageDirectory { get; private set; } public DirectoryPath PackageDirectory { get; private set; }
@ -53,13 +55,9 @@ namespace Microsoft.DotNet.ToolPackage
{ {
if (Directory.Exists(PackageDirectory.Value)) if (Directory.Exists(PackageDirectory.Value))
{ {
// Use the same staging directory for uninstall instead of temp // Use the staging directory for uninstall
// This prevents cross-device moves when temp is mounted to a different device // This prevents cross-device moves when temp is mounted to a different device
var tempPath = _store var tempPath = _store.GetRandomStagingDirectory().Value;
.Root
.WithSubDirectories(ToolPackageInstaller.StagingDirectory)
.WithFile(Path.GetRandomFileName())
.Value;
Directory.Move(PackageDirectory.Value, tempPath); Directory.Move(PackageDirectory.Value, tempPath);
tempPackageDirectory = tempPath; tempPackageDirectory = tempPath;
} }
@ -75,7 +73,7 @@ namespace Microsoft.DotNet.ToolPackage
throw new ToolPackageException( throw new ToolPackageException(
string.Format( string.Format(
CommonLocalizableStrings.FailedToUninstallToolPackage, CommonLocalizableStrings.FailedToUninstallToolPackage,
PackageId, Id,
ex.Message), ex.Message),
ex); ex);
} }
@ -116,7 +114,7 @@ namespace Microsoft.DotNet.ToolPackage
var toolConfigurationPath = var toolConfigurationPath =
PackageDirectory PackageDirectory
.WithSubDirectories( .WithSubDirectories(
PackageId, Id.ToString(),
library.Version.ToNormalizedString()) library.Version.ToNormalizedString())
.WithFile(dotnetToolSettings.Path); .WithFile(dotnetToolSettings.Path);
@ -138,7 +136,7 @@ namespace Microsoft.DotNet.ToolPackage
"dotnet", "dotnet",
PackageDirectory PackageDirectory
.WithSubDirectories( .WithSubDirectories(
PackageId, Id.ToString(),
library.Version.ToNormalizedString()) library.Version.ToNormalizedString())
.WithFile(entryPointFromLockFile.Path))); .WithFile(entryPointFromLockFile.Path)));
@ -158,7 +156,8 @@ namespace Microsoft.DotNet.ToolPackage
{ {
return lockFile return lockFile
?.Targets?.SingleOrDefault(t => t.RuntimeIdentifier != null) ?.Targets?.SingleOrDefault(t => t.RuntimeIdentifier != null)
?.Libraries?.SingleOrDefault(l => l.Name == PackageId); ?.Libraries?.SingleOrDefault(l =>
string.Compare(l.Name, Id.ToString(), StringComparison.CurrentCultureIgnoreCase) == 0);
} }
private static LockFileItem FindItemInTargetLibrary(LockFileTargetLibrary library, string targetRelativeFilePath) private static LockFileItem FindItemInTargetLibrary(LockFileTargetLibrary library, string targetRelativeFilePath)

View file

@ -2,12 +2,16 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using Microsoft.DotNet.Tools;
using Microsoft.Extensions.EnvironmentAbstractions; using Microsoft.Extensions.EnvironmentAbstractions;
using NuGet.Versioning;
namespace Microsoft.DotNet.ToolPackage namespace Microsoft.DotNet.ToolPackage
{ {
internal class ToolPackageStore : IToolPackageStore internal class ToolPackageStore : IToolPackageStore
{ {
public const string StagingDirectory = ".stage";
public ToolPackageStore(DirectoryPath root) public ToolPackageStore(DirectoryPath root)
{ {
Root = root; Root = root;
@ -15,17 +19,45 @@ namespace Microsoft.DotNet.ToolPackage
public DirectoryPath Root { get; private set; } public DirectoryPath Root { get; private set; }
public IEnumerable<IToolPackage> GetInstalledPackages(string packageId = null) public DirectoryPath GetRandomStagingDirectory()
{ {
if (packageId != null) return Root.WithSubDirectories(StagingDirectory, Path.GetRandomFileName());
{
return EnumerateVersions(packageId);
}
return EnumerateAllPackages().SelectMany(p => p);
} }
private IEnumerable<IEnumerable<IToolPackage>> EnumerateAllPackages() public NuGetVersion GetStagedPackageVersion(DirectoryPath stagingDirectory, PackageId packageId)
{
if (NuGetVersion.TryParse(
Path.GetFileName(
Directory.EnumerateDirectories(
stagingDirectory.WithSubDirectories(packageId.ToString()).Value).FirstOrDefault()),
out var version))
{
return version;
}
throw new ToolPackageException(
string.Format(
CommonLocalizableStrings.FailedToFindStagedToolPackage,
packageId));
}
public DirectoryPath GetRootPackageDirectory(PackageId packageId)
{
return Root.WithSubDirectories(packageId.ToString());
}
public DirectoryPath GetPackageDirectory(PackageId packageId, NuGetVersion version)
{
if (version == null)
{
throw new ArgumentNullException(nameof(version));
}
return GetRootPackageDirectory(packageId)
.WithSubDirectories(version.ToNormalizedString().ToLowerInvariant());
}
public IEnumerable<IToolPackage> EnumeratePackages()
{ {
if (!Directory.Exists(Root.Value)) if (!Directory.Exists(Root.Value))
{ {
@ -34,19 +66,25 @@ namespace Microsoft.DotNet.ToolPackage
foreach (var subdirectory in Directory.EnumerateDirectories(Root.Value)) foreach (var subdirectory in Directory.EnumerateDirectories(Root.Value))
{ {
var packageId = Path.GetFileName(subdirectory); var name = Path.GetFileName(subdirectory);
if (packageId == ToolPackageInstaller.StagingDirectory) var packageId = new PackageId(name);
// Ignore the staging directory and any directory that isn't the same as the package id
if (name == StagingDirectory || name != packageId.ToString())
{ {
continue; continue;
} }
yield return EnumerateVersions(packageId); foreach (var package in EnumeratePackageVersions(packageId))
{
yield return package;
}
} }
} }
private IEnumerable<IToolPackage> EnumerateVersions(string packageId) public IEnumerable<IToolPackage> EnumeratePackageVersions(PackageId packageId)
{ {
var packageRootDirectory = Root.WithSubDirectories(packageId); var packageRootDirectory = Root.WithSubDirectories(packageId.ToString());
if (!Directory.Exists(packageRootDirectory.Value)) if (!Directory.Exists(packageRootDirectory.Value))
{ {
yield break; yield break;
@ -54,13 +92,27 @@ namespace Microsoft.DotNet.ToolPackage
foreach (var subdirectory in Directory.EnumerateDirectories(packageRootDirectory.Value)) foreach (var subdirectory in Directory.EnumerateDirectories(packageRootDirectory.Value))
{ {
var version = Path.GetFileName(subdirectory);
yield return new ToolPackageInstance( yield return new ToolPackageInstance(
this, this,
packageId, packageId,
version, NuGetVersion.Parse(Path.GetFileName(subdirectory)),
packageRootDirectory.WithSubDirectories(version)); new DirectoryPath(subdirectory));
} }
} }
public IToolPackage GetPackage(PackageId packageId, NuGetVersion version)
{
if (version == null)
{
throw new ArgumentNullException(nameof(version));
}
var directory = GetPackageDirectory(packageId, version);
if (!Directory.Exists(directory.Value))
{
return null;
}
return new ToolPackageInstance(this, packageId, version, directory);
}
} }
} }

View file

@ -13,6 +13,7 @@ using Microsoft.DotNet.Configurer;
using Microsoft.DotNet.ShellShim; using Microsoft.DotNet.ShellShim;
using Microsoft.DotNet.ToolPackage; using Microsoft.DotNet.ToolPackage;
using Microsoft.Extensions.EnvironmentAbstractions; using Microsoft.Extensions.EnvironmentAbstractions;
using NuGet.Versioning;
namespace Microsoft.DotNet.Tools.Install.Tool namespace Microsoft.DotNet.Tools.Install.Tool
{ {
@ -25,7 +26,7 @@ namespace Microsoft.DotNet.Tools.Install.Tool
private readonly IReporter _reporter; private readonly IReporter _reporter;
private readonly IReporter _errorReporter; private readonly IReporter _errorReporter;
private readonly string _packageId; private readonly PackageId _packageId;
private readonly string _packageVersion; private readonly string _packageVersion;
private readonly string _configFilePath; private readonly string _configFilePath;
private readonly string _framework; private readonly string _framework;
@ -48,7 +49,7 @@ namespace Microsoft.DotNet.Tools.Install.Tool
throw new ArgumentNullException(nameof(appliedCommand)); throw new ArgumentNullException(nameof(appliedCommand));
} }
_packageId = appliedCommand.Arguments.Single(); _packageId = new PackageId(appliedCommand.Arguments.Single());
_packageVersion = appliedCommand.ValueOrDefault<string>("version"); _packageVersion = appliedCommand.ValueOrDefault<string>("version");
_configFilePath = appliedCommand.ValueOrDefault<string>("configfile"); _configFilePath = appliedCommand.ValueOrDefault<string>("configfile");
_framework = appliedCommand.ValueOrDefault<string>("framework"); _framework = appliedCommand.ValueOrDefault<string>("framework");
@ -91,8 +92,16 @@ namespace Microsoft.DotNet.Tools.Install.Tool
Path.GetFullPath(_configFilePath))); Path.GetFullPath(_configFilePath)));
} }
// Prevent installation if any version of the package is installed VersionRange versionRange = null;
if (_toolPackageStore.GetInstalledPackages(_packageId).FirstOrDefault() != null) if (!string.IsNullOrEmpty(_packageVersion) && !VersionRange.TryParse(_packageVersion, out versionRange))
{
throw new GracefulException(
string.Format(
LocalizableStrings.InvalidNuGetVersionRange,
_packageVersion));
}
if (_toolPackageStore.EnumeratePackageVersions(_packageId).FirstOrDefault() != null)
{ {
_errorReporter.WriteLine(string.Format(LocalizableStrings.ToolAlreadyInstalled, _packageId).Red()); _errorReporter.WriteLine(string.Format(LocalizableStrings.ToolAlreadyInstalled, _packageId).Red());
return 1; return 1;
@ -113,7 +122,7 @@ namespace Microsoft.DotNet.Tools.Install.Tool
{ {
package = _toolPackageInstaller.InstallPackage( package = _toolPackageInstaller.InstallPackage(
packageId: _packageId, packageId: _packageId,
packageVersion: _packageVersion, versionRange: versionRange,
targetFramework: _framework, targetFramework: _framework,
nugetConfig: configFile, nugetConfig: configFile,
source: _source, source: _source,
@ -133,8 +142,8 @@ namespace Microsoft.DotNet.Tools.Install.Tool
string.Format( string.Format(
LocalizableStrings.InstallationSucceeded, LocalizableStrings.InstallationSucceeded,
string.Join(", ", package.Commands.Select(c => c.Name)), string.Join(", ", package.Commands.Select(c => c.Name)),
package.PackageId, package.Id,
package.PackageVersion).Green()); package.Version.ToNormalizedString()).Green());
return 0; return 0;
} }
catch (ToolPackageException ex) catch (ToolPackageException ex)

View file

@ -178,4 +178,7 @@ Tool '{1}' (version '{2}') was successfully installed.</value>
<data name="FailedToCreateToolShim" xml:space="preserve"> <data name="FailedToCreateToolShim" xml:space="preserve">
<value>Failed to create shell shim for tool '{0}': {1}</value> <value>Failed to create shell shim for tool '{0}': {1}</value>
</data> </data>
<data name="InvalidNuGetVersionRange" xml:space="preserve">
<value>Specified version '{0}' is not a valid NuGet version range.</value>
</data>
</root> </root>

View file

@ -104,6 +104,11 @@ Instalace byla úspěšná. Pokud nejsou další pokyny, můžete přímo do já
<target state="translated">Balíček nástroje nebylo možné obnovit.</target> <target state="translated">Balíček nástroje nebylo možné obnovit.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="InvalidNuGetVersionRange">
<source>Specified version '{0}' is not a valid NuGet version range.</source>
<target state="new">Specified version '{0}' is not a valid NuGet version range.</target>
<note />
</trans-unit>
</body> </body>
</file> </file>
</xliff> </xliff>

View file

@ -104,6 +104,11 @@ Die Installation war erfolgreich. Sofern keine weiteren Anweisungen vorliegen, k
<target state="translated">Das Toolpaket konnte nicht wiederhergestellt werden.</target> <target state="translated">Das Toolpaket konnte nicht wiederhergestellt werden.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="InvalidNuGetVersionRange">
<source>Specified version '{0}' is not a valid NuGet version range.</source>
<target state="new">Specified version '{0}' is not a valid NuGet version range.</target>
<note />
</trans-unit>
</body> </body>
</file> </file>
</xliff> </xliff>

View file

@ -104,6 +104,11 @@ La instalación se completó correctamente. Si no hay más instrucciones, puede
<target state="translated">No se puede restaurar el paquete de la herramienta.</target> <target state="translated">No se puede restaurar el paquete de la herramienta.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="InvalidNuGetVersionRange">
<source>Specified version '{0}' is not a valid NuGet version range.</source>
<target state="new">Specified version '{0}' is not a valid NuGet version range.</target>
<note />
</trans-unit>
</body> </body>
</file> </file>
</xliff> </xliff>

View file

@ -104,6 +104,11 @@ L'installation a réussi. En l'absence d'instructions supplémentaires, vous pou
<target state="translated">Impossible de restaurer le package de l'outil.</target> <target state="translated">Impossible de restaurer le package de l'outil.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="InvalidNuGetVersionRange">
<source>Specified version '{0}' is not a valid NuGet version range.</source>
<target state="new">Specified version '{0}' is not a valid NuGet version range.</target>
<note />
</trans-unit>
</body> </body>
</file> </file>
</xliff> </xliff>

View file

@ -104,6 +104,11 @@ L'installazione è riuscita. Se non ci sono altre istruzioni, è possibile digit
<target state="translated">Non è stato possibile ripristinare il pacchetto dello strumento.</target> <target state="translated">Non è stato possibile ripristinare il pacchetto dello strumento.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="InvalidNuGetVersionRange">
<source>Specified version '{0}' is not a valid NuGet version range.</source>
<target state="new">Specified version '{0}' is not a valid NuGet version range.</target>
<note />
</trans-unit>
</body> </body>
</file> </file>
</xliff> </xliff>

View file

@ -104,6 +104,11 @@ Tool '{1}' (version '{2}') was successfully installed.</source>
<target state="translated">ツール パッケージを復元できませんでした。</target> <target state="translated">ツール パッケージを復元できませんでした。</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="InvalidNuGetVersionRange">
<source>Specified version '{0}' is not a valid NuGet version range.</source>
<target state="new">Specified version '{0}' is not a valid NuGet version range.</target>
<note />
</trans-unit>
</body> </body>
</file> </file>
</xliff> </xliff>

View file

@ -104,6 +104,11 @@ Tool '{1}' (version '{2}') was successfully installed.</source>
<target state="translated">도구 패키지를 복원할 수 없습니다.</target> <target state="translated">도구 패키지를 복원할 수 없습니다.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="InvalidNuGetVersionRange">
<source>Specified version '{0}' is not a valid NuGet version range.</source>
<target state="new">Specified version '{0}' is not a valid NuGet version range.</target>
<note />
</trans-unit>
</body> </body>
</file> </file>
</xliff> </xliff>

View file

@ -104,6 +104,11 @@ Instalacja powiodła się. Jeśli nie ma dodatkowych instrukcji, możesz wpisać
<target state="translated">Nie można przywrócić pakietu narzędzia.</target> <target state="translated">Nie można przywrócić pakietu narzędzia.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="InvalidNuGetVersionRange">
<source>Specified version '{0}' is not a valid NuGet version range.</source>
<target state="new">Specified version '{0}' is not a valid NuGet version range.</target>
<note />
</trans-unit>
</body> </body>
</file> </file>
</xliff> </xliff>

View file

@ -104,6 +104,11 @@ A instalação foi bem-sucedida. Se não houver outras instruções, digite o se
<target state="translated">O pacote da ferramenta não pôde ser restaurado.</target> <target state="translated">O pacote da ferramenta não pôde ser restaurado.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="InvalidNuGetVersionRange">
<source>Specified version '{0}' is not a valid NuGet version range.</source>
<target state="new">Specified version '{0}' is not a valid NuGet version range.</target>
<note />
</trans-unit>
</body> </body>
</file> </file>
</xliff> </xliff>

View file

@ -104,6 +104,11 @@ Tool '{1}' (version '{2}') was successfully installed.</source>
<target state="translated">Не удалось восстановить пакет инструмента.</target> <target state="translated">Не удалось восстановить пакет инструмента.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="InvalidNuGetVersionRange">
<source>Specified version '{0}' is not a valid NuGet version range.</source>
<target state="new">Specified version '{0}' is not a valid NuGet version range.</target>
<note />
</trans-unit>
</body> </body>
</file> </file>
</xliff> </xliff>

View file

@ -104,6 +104,11 @@ Yükleme başarılı oldu. Daha fazla yönerge yoksa, çağırmak için şu komu
<target state="translated">Araç paketi geri yüklenemedi.</target> <target state="translated">Araç paketi geri yüklenemedi.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="InvalidNuGetVersionRange">
<source>Specified version '{0}' is not a valid NuGet version range.</source>
<target state="new">Specified version '{0}' is not a valid NuGet version range.</target>
<note />
</trans-unit>
</body> </body>
</file> </file>
</xliff> </xliff>

View file

@ -104,6 +104,11 @@ Tool '{1}' (version '{2}') was successfully installed.</source>
<target state="translated">无法还原工具包。</target> <target state="translated">无法还原工具包。</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="InvalidNuGetVersionRange">
<source>Specified version '{0}' is not a valid NuGet version range.</source>
<target state="new">Specified version '{0}' is not a valid NuGet version range.</target>
<note />
</trans-unit>
</body> </body>
</file> </file>
</xliff> </xliff>

View file

@ -104,6 +104,11 @@ Tool '{1}' (version '{2}') was successfully installed.</source>
<target state="translated">此工具套件無法還原。</target> <target state="translated">此工具套件無法還原。</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="InvalidNuGetVersionRange">
<source>Specified version '{0}' is not a valid NuGet version range.</source>
<target state="new">Specified version '{0}' is not a valid NuGet version range.</target>
<note />
</trans-unit>
</body> </body>
</file> </file>
</xliff> </xliff>

View file

@ -46,10 +46,10 @@ namespace Microsoft.DotNet.Tools.List.Tool
table.AddColumn( table.AddColumn(
LocalizableStrings.PackageIdColumn, LocalizableStrings.PackageIdColumn,
p => p.PackageId); p => p.Id.ToString());
table.AddColumn( table.AddColumn(
LocalizableStrings.VersionColumn, LocalizableStrings.VersionColumn,
p => p.PackageVersion); p => p.Version.ToNormalizedString());
table.AddColumn( table.AddColumn(
LocalizableStrings.CommandsColumn, LocalizableStrings.CommandsColumn,
p => string.Join(CommandDelimiter, p.Commands.Select(c => c.Name))); p => string.Join(CommandDelimiter, p.Commands.Select(c => c.Name)));
@ -60,9 +60,9 @@ namespace Microsoft.DotNet.Tools.List.Tool
private IEnumerable<IToolPackage> GetPackages() private IEnumerable<IToolPackage> GetPackages()
{ {
return _toolPackageStore.GetInstalledPackages() return _toolPackageStore.EnumeratePackages()
.Where(PackageHasCommands) .Where(PackageHasCommands)
.OrderBy(p => p.PackageId) .OrderBy(p => p.Id)
.ToArray(); .ToArray();
} }
@ -79,7 +79,7 @@ namespace Microsoft.DotNet.Tools.List.Tool
_errorReporter.WriteLine( _errorReporter.WriteLine(
string.Format( string.Format(
LocalizableStrings.InvalidPackageWarning, LocalizableStrings.InvalidPackageWarning,
p.PackageId, p.Id,
ex.Message).Yellow()); ex.Message).Yellow());
return false; return false;
} }

View file

@ -49,12 +49,11 @@ namespace Microsoft.DotNet.Tools.Uninstall.Tool
throw new GracefulException(LocalizableStrings.UninstallToolCommandOnlySupportsGlobal); throw new GracefulException(LocalizableStrings.UninstallToolCommandOnlySupportsGlobal);
} }
var packageId = _options.Arguments.Single(); var packageId = new PackageId(_options.Arguments.Single());
IToolPackage package = null; IToolPackage package = null;
try try
{ {
package = _toolPackageStore.GetInstalledPackages(packageId).SingleOrDefault(); package = _toolPackageStore.EnumeratePackageVersions(packageId).SingleOrDefault();
if (package == null) if (package == null)
{ {
_errorReporter.WriteLine( _errorReporter.WriteLine(
@ -92,8 +91,8 @@ namespace Microsoft.DotNet.Tools.Uninstall.Tool
_reporter.WriteLine( _reporter.WriteLine(
string.Format( string.Format(
LocalizableStrings.UninstallSucceeded, LocalizableStrings.UninstallSucceeded,
package.PackageId, package.Id,
package.PackageVersion).Green()); package.Version.ToNormalizedString()).Green());
return 0; return 0;
} }
catch (ToolPackageException ex) catch (ToolPackageException ex)

View file

@ -853,6 +853,11 @@ setx PATH "%PATH%;{0}"
<target state="new">Settings file 'DotnetToolSettings.xml' was not found in the package.</target> <target state="new">Settings file 'DotnetToolSettings.xml' was not found in the package.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="FailedToFindStagedToolPackage">
<source>Failed to find staged tool package '{0}'.</source>
<target state="new">Failed to find staged tool package '{0}'.</target>
<note />
</trans-unit>
</body> </body>
</file> </file>
</xliff> </xliff>

View file

@ -853,6 +853,11 @@ setx PATH "%PATH%;{0}"
<target state="new">Settings file 'DotnetToolSettings.xml' was not found in the package.</target> <target state="new">Settings file 'DotnetToolSettings.xml' was not found in the package.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="FailedToFindStagedToolPackage">
<source>Failed to find staged tool package '{0}'.</source>
<target state="new">Failed to find staged tool package '{0}'.</target>
<note />
</trans-unit>
</body> </body>
</file> </file>
</xliff> </xliff>

View file

@ -853,6 +853,11 @@ setx PATH "%PATH%;{0}"
<target state="new">Settings file 'DotnetToolSettings.xml' was not found in the package.</target> <target state="new">Settings file 'DotnetToolSettings.xml' was not found in the package.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="FailedToFindStagedToolPackage">
<source>Failed to find staged tool package '{0}'.</source>
<target state="new">Failed to find staged tool package '{0}'.</target>
<note />
</trans-unit>
</body> </body>
</file> </file>
</xliff> </xliff>

View file

@ -853,6 +853,11 @@ setx PATH "%PATH%;{0}"
<target state="new">Settings file 'DotnetToolSettings.xml' was not found in the package.</target> <target state="new">Settings file 'DotnetToolSettings.xml' was not found in the package.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="FailedToFindStagedToolPackage">
<source>Failed to find staged tool package '{0}'.</source>
<target state="new">Failed to find staged tool package '{0}'.</target>
<note />
</trans-unit>
</body> </body>
</file> </file>
</xliff> </xliff>

View file

@ -853,6 +853,11 @@ setx PATH "%PATH%;{0}"
<target state="new">Settings file 'DotnetToolSettings.xml' was not found in the package.</target> <target state="new">Settings file 'DotnetToolSettings.xml' was not found in the package.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="FailedToFindStagedToolPackage">
<source>Failed to find staged tool package '{0}'.</source>
<target state="new">Failed to find staged tool package '{0}'.</target>
<note />
</trans-unit>
</body> </body>
</file> </file>
</xliff> </xliff>

View file

@ -853,6 +853,11 @@ setx PATH "%PATH%;{0}"
<target state="new">Settings file 'DotnetToolSettings.xml' was not found in the package.</target> <target state="new">Settings file 'DotnetToolSettings.xml' was not found in the package.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="FailedToFindStagedToolPackage">
<source>Failed to find staged tool package '{0}'.</source>
<target state="new">Failed to find staged tool package '{0}'.</target>
<note />
</trans-unit>
</body> </body>
</file> </file>
</xliff> </xliff>

View file

@ -853,6 +853,11 @@ setx PATH "%PATH%;{0}"
<target state="new">Settings file 'DotnetToolSettings.xml' was not found in the package.</target> <target state="new">Settings file 'DotnetToolSettings.xml' was not found in the package.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="FailedToFindStagedToolPackage">
<source>Failed to find staged tool package '{0}'.</source>
<target state="new">Failed to find staged tool package '{0}'.</target>
<note />
</trans-unit>
</body> </body>
</file> </file>
</xliff> </xliff>

View file

@ -853,6 +853,11 @@ setx PATH "%PATH%;{0}"
<target state="new">Settings file 'DotnetToolSettings.xml' was not found in the package.</target> <target state="new">Settings file 'DotnetToolSettings.xml' was not found in the package.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="FailedToFindStagedToolPackage">
<source>Failed to find staged tool package '{0}'.</source>
<target state="new">Failed to find staged tool package '{0}'.</target>
<note />
</trans-unit>
</body> </body>
</file> </file>
</xliff> </xliff>

View file

@ -853,6 +853,11 @@ setx PATH "%PATH%;{0}"
<target state="new">Settings file 'DotnetToolSettings.xml' was not found in the package.</target> <target state="new">Settings file 'DotnetToolSettings.xml' was not found in the package.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="FailedToFindStagedToolPackage">
<source>Failed to find staged tool package '{0}'.</source>
<target state="new">Failed to find staged tool package '{0}'.</target>
<note />
</trans-unit>
</body> </body>
</file> </file>
</xliff> </xliff>

View file

@ -853,6 +853,11 @@ setx PATH "%PATH%;{0}"
<target state="new">Settings file 'DotnetToolSettings.xml' was not found in the package.</target> <target state="new">Settings file 'DotnetToolSettings.xml' was not found in the package.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="FailedToFindStagedToolPackage">
<source>Failed to find staged tool package '{0}'.</source>
<target state="new">Failed to find staged tool package '{0}'.</target>
<note />
</trans-unit>
</body> </body>
</file> </file>
</xliff> </xliff>

View file

@ -853,6 +853,11 @@ setx PATH "%PATH%;{0}"
<target state="new">Settings file 'DotnetToolSettings.xml' was not found in the package.</target> <target state="new">Settings file 'DotnetToolSettings.xml' was not found in the package.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="FailedToFindStagedToolPackage">
<source>Failed to find staged tool package '{0}'.</source>
<target state="new">Failed to find staged tool package '{0}'.</target>
<note />
</trans-unit>
</body> </body>
</file> </file>
</xliff> </xliff>

View file

@ -853,6 +853,11 @@ setx PATH "%PATH%;{0}"
<target state="new">Settings file 'DotnetToolSettings.xml' was not found in the package.</target> <target state="new">Settings file 'DotnetToolSettings.xml' was not found in the package.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="FailedToFindStagedToolPackage">
<source>Failed to find staged tool package '{0}'.</source>
<target state="new">Failed to find staged tool package '{0}'.</target>
<note />
</trans-unit>
</body> </body>
</file> </file>
</xliff> </xliff>

View file

@ -853,6 +853,11 @@ setx PATH "%PATH%;{0}"
<target state="new">Settings file 'DotnetToolSettings.xml' was not found in the package.</target> <target state="new">Settings file 'DotnetToolSettings.xml' was not found in the package.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="FailedToFindStagedToolPackage">
<source>Failed to find staged tool package '{0}'.</source>
<target state="new">Failed to find staged tool package '{0}'.</target>
<note />
</trans-unit>
</body> </body>
</file> </file>
</xliff> </xliff>

View file

@ -16,6 +16,7 @@ using Microsoft.DotNet.Tools.Install.Tool;
using Microsoft.DotNet.Tools.Tests.ComponentMocks; using Microsoft.DotNet.Tools.Tests.ComponentMocks;
using Microsoft.Extensions.DependencyModel.Tests; using Microsoft.Extensions.DependencyModel.Tests;
using Microsoft.Extensions.EnvironmentAbstractions; using Microsoft.Extensions.EnvironmentAbstractions;
using NuGet.Versioning;
using Xunit; using Xunit;
namespace Microsoft.DotNet.ToolPackage.Tests namespace Microsoft.DotNet.ToolPackage.Tests
@ -33,13 +34,13 @@ namespace Microsoft.DotNet.ToolPackage.Tests
Action a = () => installer.InstallPackage( Action a = () => installer.InstallPackage(
packageId: TestPackageId, packageId: TestPackageId,
packageVersion: TestPackageVersion, versionRange: VersionRange.Parse(TestPackageVersion),
targetFramework: _testTargetframework); targetFramework: _testTargetframework);
a.ShouldThrow<ToolPackageException>().WithMessage(LocalizableStrings.ToolInstallationRestoreFailed); a.ShouldThrow<ToolPackageException>().WithMessage(LocalizableStrings.ToolInstallationRestoreFailed);
reporter.Lines.Count.Should().Be(1); reporter.Lines.Count.Should().Be(1);
reporter.Lines[0].Should().Contain(TestPackageId); reporter.Lines[0].Should().Contain(TestPackageId.ToString());
} }
[Theory] [Theory]
@ -54,7 +55,7 @@ namespace Microsoft.DotNet.ToolPackage.Tests
var package = installer.InstallPackage( var package = installer.InstallPackage(
packageId: TestPackageId, packageId: TestPackageId,
packageVersion: TestPackageVersion, versionRange: VersionRange.Parse(TestPackageVersion),
targetFramework: _testTargetframework); targetFramework: _testTargetframework);
AssertPackageInstall(reporter, fileSystem, package, store); AssertPackageInstall(reporter, fileSystem, package, store);
@ -75,7 +76,7 @@ namespace Microsoft.DotNet.ToolPackage.Tests
var package = installer.InstallPackage( var package = installer.InstallPackage(
packageId: TestPackageId, packageId: TestPackageId,
packageVersion: TestPackageVersion, versionRange: VersionRange.Parse(TestPackageVersion),
targetFramework: _testTargetframework, targetFramework: _testTargetframework,
nugetConfig: nugetConfigPath); nugetConfig: nugetConfigPath);
@ -102,7 +103,7 @@ namespace Microsoft.DotNet.ToolPackage.Tests
{ {
package = installer.InstallPackage( package = installer.InstallPackage(
packageId: TestPackageId, packageId: TestPackageId,
packageVersion: TestPackageVersion, versionRange: VersionRange.Parse(TestPackageVersion),
targetFramework: _testTargetframework, targetFramework: _testTargetframework,
nugetConfig: nugetConfigPath); nugetConfig: nugetConfigPath);
@ -127,7 +128,7 @@ namespace Microsoft.DotNet.ToolPackage.Tests
var package = installer.InstallPackage( var package = installer.InstallPackage(
packageId: TestPackageId, packageId: TestPackageId,
packageVersion: TestPackageVersion, versionRange: VersionRange.Parse(TestPackageVersion),
targetFramework: _testTargetframework, targetFramework: _testTargetframework,
nugetConfig: nugetConfigPath); nugetConfig: nugetConfigPath);
@ -166,7 +167,7 @@ namespace Microsoft.DotNet.ToolPackage.Tests
var package = installer.InstallPackage( var package = installer.InstallPackage(
packageId: TestPackageId, packageId: TestPackageId,
packageVersion: TestPackageVersion, versionRange: VersionRange.Parse(TestPackageVersion),
targetFramework: _testTargetframework); targetFramework: _testTargetframework);
AssertPackageInstall(reporter, fileSystem, package, store); AssertPackageInstall(reporter, fileSystem, package, store);
@ -208,7 +209,7 @@ namespace Microsoft.DotNet.ToolPackage.Tests
var package = installer.InstallPackage( var package = installer.InstallPackage(
packageId: TestPackageId, packageId: TestPackageId,
packageVersion: TestPackageVersion, versionRange: VersionRange.Parse(TestPackageVersion),
nugetConfig: nugetConfigPath); nugetConfig: nugetConfigPath);
AssertPackageInstall(reporter, fileSystem, package, store); AssertPackageInstall(reporter, fileSystem, package, store);
@ -229,7 +230,7 @@ namespace Microsoft.DotNet.ToolPackage.Tests
var package = installer.InstallPackage( var package = installer.InstallPackage(
packageId: TestPackageId, packageId: TestPackageId,
packageVersion: TestPackageVersion, versionRange: VersionRange.Parse(TestPackageVersion),
targetFramework: _testTargetframework, targetFramework: _testTargetframework,
source: source); source: source);
@ -251,7 +252,7 @@ namespace Microsoft.DotNet.ToolPackage.Tests
TransactionScopeOption.Required, TransactionScopeOption.Required,
TimeSpan.Zero)) TimeSpan.Zero))
{ {
installer.InstallPackage("non.existent.package.id"); installer.InstallPackage(new PackageId("non.existent.package.id"));
t.Complete(); t.Complete();
} }
@ -282,7 +283,7 @@ namespace Microsoft.DotNet.ToolPackage.Tests
{ {
installer.InstallPackage( installer.InstallPackage(
packageId: TestPackageId, packageId: TestPackageId,
packageVersion: TestPackageVersion, versionRange: VersionRange.Parse(TestPackageVersion),
targetFramework: _testTargetframework, targetFramework: _testTargetframework,
source: source); source: source);
@ -314,7 +315,7 @@ namespace Microsoft.DotNet.ToolPackage.Tests
{ {
Action first = () => installer.InstallPackage( Action first = () => installer.InstallPackage(
packageId: TestPackageId, packageId: TestPackageId,
packageVersion: TestPackageVersion, versionRange: VersionRange.Parse(TestPackageVersion),
targetFramework: _testTargetframework, targetFramework: _testTargetframework,
source: source); source: source);
@ -322,7 +323,7 @@ namespace Microsoft.DotNet.ToolPackage.Tests
installer.InstallPackage( installer.InstallPackage(
packageId: TestPackageId, packageId: TestPackageId,
packageVersion: TestPackageVersion, versionRange: VersionRange.Parse(TestPackageVersion),
targetFramework: _testTargetframework, targetFramework: _testTargetframework,
source: source); source: source);
@ -353,7 +354,7 @@ namespace Microsoft.DotNet.ToolPackage.Tests
var package = installer.InstallPackage( var package = installer.InstallPackage(
packageId: TestPackageId, packageId: TestPackageId,
packageVersion: TestPackageVersion, versionRange: VersionRange.Parse(TestPackageVersion),
targetFramework: _testTargetframework, targetFramework: _testTargetframework,
source: source); source: source);
@ -361,7 +362,7 @@ namespace Microsoft.DotNet.ToolPackage.Tests
Action secondCall = () => installer.InstallPackage( Action secondCall = () => installer.InstallPackage(
packageId: TestPackageId, packageId: TestPackageId,
packageVersion: TestPackageVersion, versionRange: VersionRange.Parse(TestPackageVersion),
targetFramework: _testTargetframework, targetFramework: _testTargetframework,
source: source); source: source);
@ -376,7 +377,7 @@ namespace Microsoft.DotNet.ToolPackage.Tests
fileSystem fileSystem
.Directory .Directory
.Exists(store.Root.WithSubDirectories(TestPackageId).Value) .Exists(store.Root.WithSubDirectories(TestPackageId.ToString()).Value)
.Should() .Should()
.BeTrue(); .BeTrue();
@ -384,7 +385,7 @@ namespace Microsoft.DotNet.ToolPackage.Tests
fileSystem fileSystem
.Directory .Directory
.EnumerateFileSystemEntries(store.Root.WithSubDirectories(".stage").Value) .EnumerateFileSystemEntries(store.Root.WithSubDirectories(ToolPackageStore.StagingDirectory).Value)
.Should() .Should()
.BeEmpty(); .BeEmpty();
} }
@ -402,7 +403,7 @@ namespace Microsoft.DotNet.ToolPackage.Tests
var package = installer.InstallPackage( var package = installer.InstallPackage(
packageId: TestPackageId, packageId: TestPackageId,
packageVersion: TestPackageVersion, versionRange: VersionRange.Parse(TestPackageVersion),
targetFramework: _testTargetframework, targetFramework: _testTargetframework,
source: source); source: source);
@ -410,7 +411,7 @@ namespace Microsoft.DotNet.ToolPackage.Tests
package.Uninstall(); package.Uninstall();
store.GetInstalledPackages(TestPackageId).Should().BeEmpty(); store.EnumeratePackages().Should().BeEmpty();
} }
[Theory] [Theory]
@ -426,7 +427,7 @@ namespace Microsoft.DotNet.ToolPackage.Tests
var package = installer.InstallPackage( var package = installer.InstallPackage(
packageId: TestPackageId, packageId: TestPackageId,
packageVersion: TestPackageVersion, versionRange: VersionRange.Parse(TestPackageVersion),
targetFramework: _testTargetframework, targetFramework: _testTargetframework,
source: source); source: source);
@ -438,10 +439,10 @@ namespace Microsoft.DotNet.ToolPackage.Tests
{ {
package.Uninstall(); package.Uninstall();
store.GetInstalledPackages(TestPackageId).Should().BeEmpty(); store.EnumeratePackages().Should().BeEmpty();
} }
package = store.GetInstalledPackages(TestPackageId).First(); package = store.EnumeratePackageVersions(TestPackageId).First();
AssertPackageInstall(reporter, fileSystem, package, store); AssertPackageInstall(reporter, fileSystem, package, store);
} }
@ -459,7 +460,7 @@ namespace Microsoft.DotNet.ToolPackage.Tests
var package = installer.InstallPackage( var package = installer.InstallPackage(
packageId: TestPackageId, packageId: TestPackageId,
packageVersion: TestPackageVersion, versionRange: VersionRange.Parse(TestPackageVersion),
targetFramework: _testTargetframework, targetFramework: _testTargetframework,
source: source); source: source);
@ -473,7 +474,28 @@ namespace Microsoft.DotNet.ToolPackage.Tests
scope.Complete(); scope.Complete();
} }
store.GetInstalledPackages(TestPackageId).Should().BeEmpty(); store.EnumeratePackages().Should().BeEmpty();
}
[Theory]
[InlineData(false)]
[InlineData(true)]
public void GivenAPackageNameWithDifferentCaseItCanInstallThePackage(bool testMockBehaviorIsInSync)
{
var nugetConfigPath = WriteNugetConfigFileToPointToTheFeed();
var (store, installer, reporter, fileSystem) = Setup(
useMock: testMockBehaviorIsInSync,
feeds: GetMockFeedsForConfigFile(nugetConfigPath));
var package = installer.InstallPackage(
packageId: new PackageId("GlObAl.TooL.coNsoLe.DemO"),
targetFramework: _testTargetframework,
nugetConfig: nugetConfigPath);
AssertPackageInstall(reporter, fileSystem, package, store);
package.Uninstall();
} }
private static void AssertPackageInstall( private static void AssertPackageInstall(
@ -484,11 +506,14 @@ namespace Microsoft.DotNet.ToolPackage.Tests
{ {
reporter.Lines.Should().BeEmpty(); reporter.Lines.Should().BeEmpty();
package.PackageId.Should().Be(TestPackageId); package.Id.Should().Be(TestPackageId);
package.PackageVersion.Should().Be(TestPackageVersion); package.Version.ToNormalizedString().Should().Be(TestPackageVersion);
package.PackageDirectory.Value.Should().Contain(store.Root.Value); package.PackageDirectory.Value.Should().Contain(store.Root.Value);
store.GetInstalledPackages(TestPackageId).Select(p => p.PackageVersion).Should().Equal(TestPackageVersion); store.EnumeratePackageVersions(TestPackageId)
.Select(p => p.Version.ToNormalizedString())
.Should()
.Equal(TestPackageVersion);
package.Commands.Count.Should().Be(1); package.Commands.Count.Should().Be(1);
fileSystem.File.Exists(package.Commands[0].Executable.Value).Should().BeTrue($"{package.Commands[0].Executable.Value} should exist"); fileSystem.File.Exists(package.Commands[0].Executable.Value).Should().BeTrue($"{package.Commands[0].Executable.Value} should exist");
@ -506,11 +531,11 @@ namespace Microsoft.DotNet.ToolPackage.Tests
.Directory .Directory
.EnumerateFileSystemEntries(store.Root.Value) .EnumerateFileSystemEntries(store.Root.Value)
.Should() .Should()
.NotContain(e => Path.GetFileName(e) != ".stage"); .NotContain(e => Path.GetFileName(e) != ToolPackageStore.StagingDirectory);
fileSystem fileSystem
.Directory .Directory
.EnumerateFileSystemEntries(store.Root.WithSubDirectories(".stage").Value) .EnumerateFileSystemEntries(store.Root.WithSubDirectories(ToolPackageStore.StagingDirectory).Value)
.Should() .Should()
.BeEmpty(); .BeEmpty();
} }
@ -536,7 +561,7 @@ namespace Microsoft.DotNet.ToolPackage.Tests
{ {
new MockFeedPackage new MockFeedPackage
{ {
PackageId = TestPackageId, PackageId = TestPackageId.ToString(),
Version = TestPackageVersion Version = TestPackageVersion
} }
} }
@ -556,7 +581,7 @@ namespace Microsoft.DotNet.ToolPackage.Tests
{ {
new MockFeedPackage new MockFeedPackage
{ {
PackageId = TestPackageId, PackageId = TestPackageId.ToString(),
Version = TestPackageVersion Version = TestPackageVersion
} }
} }
@ -576,7 +601,7 @@ namespace Microsoft.DotNet.ToolPackage.Tests
{ {
new MockFeedPackage new MockFeedPackage
{ {
PackageId = TestPackageId, PackageId = TestPackageId.ToString(),
Version = TestPackageVersion Version = TestPackageVersion
} }
} }
@ -642,6 +667,6 @@ namespace Microsoft.DotNet.ToolPackage.Tests
private static string GetTestLocalFeedPath() => Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "TestAssetLocalNugetFeed"); private static string GetTestLocalFeedPath() => Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "TestAssetLocalNugetFeed");
private readonly string _testTargetframework = BundledTargetFramework.GetTargetFrameworkMoniker(); private readonly string _testTargetframework = BundledTargetFramework.GetTargetFrameworkMoniker();
private const string TestPackageVersion = "1.0.4"; private const string TestPackageVersion = "1.0.4";
private const string TestPackageId = "global.tool.console.demo"; private static readonly PackageId TestPackageId = new PackageId("global.tool.console.demo");
} }
} }

View file

@ -11,6 +11,7 @@ using Microsoft.DotNet.ToolPackage;
using Microsoft.DotNet.Tools; using Microsoft.DotNet.Tools;
using Microsoft.DotNet.Tools.Install.Tool; using Microsoft.DotNet.Tools.Install.Tool;
using Microsoft.Extensions.EnvironmentAbstractions; using Microsoft.Extensions.EnvironmentAbstractions;
using NuGet.Versioning;
namespace Microsoft.DotNet.Tools.Tests.ComponentMocks namespace Microsoft.DotNet.Tools.Tests.ComponentMocks
{ {
@ -63,7 +64,7 @@ namespace Microsoft.DotNet.Tools.Tests.ComponentMocks
string verbosity = null) string verbosity = null)
{ {
string packageId; string packageId;
string packageVersion; VersionRange versionRange;
string targetFramework; string targetFramework;
try try
@ -77,7 +78,7 @@ namespace Microsoft.DotNet.Tools.Tests.ComponentMocks
} }
packageId = tokens[0]; packageId = tokens[0];
packageVersion = tokens[1]; versionRange = VersionRange.Parse(tokens[1]);
targetFramework = tokens[2]; targetFramework = tokens[2];
} }
catch (IOException) catch (IOException)
@ -92,16 +93,16 @@ namespace Microsoft.DotNet.Tools.Tests.ComponentMocks
var feedPackage = GetPackage( var feedPackage = GetPackage(
packageId, packageId,
packageVersion, versionRange,
nugetConfig, nugetConfig,
source); source);
packageVersion = feedPackage.Version; var packageVersion = feedPackage.Version;
targetFramework = string.IsNullOrEmpty(targetFramework) ? "targetFramework" : targetFramework; targetFramework = string.IsNullOrEmpty(targetFramework) ? "targetFramework" : targetFramework;
var fakeExecutableSubDirectory = Path.Combine( var fakeExecutableSubDirectory = Path.Combine(
packageId, packageId.ToLowerInvariant(),
packageVersion, packageVersion.ToLowerInvariant(),
"tools", "tools",
targetFramework, targetFramework,
"any"); "any");
@ -116,7 +117,7 @@ namespace Microsoft.DotNet.Tools.Tests.ComponentMocks
private MockFeedPackage GetPackage( private MockFeedPackage GetPackage(
string packageId, string packageId,
string packageVersion = null, VersionRange versionRange = null,
FilePath? nugetConfig = null, FilePath? nugetConfig = null,
string source = null) string source = null)
{ {
@ -133,7 +134,7 @@ namespace Microsoft.DotNet.Tools.Tests.ComponentMocks
return true; return true;
}) })
.SelectMany(f => f.Packages) .SelectMany(f => f.Packages)
.Where(p => MatchPackageVersion(p, packageId, packageVersion)).OrderByDescending(p => p.Version) .Where(p => MatchPackage(p, packageId, versionRange)).OrderByDescending(p => p.Version)
.FirstOrDefault(); .FirstOrDefault();
if (package == null) if (package == null)
@ -148,13 +149,15 @@ namespace Microsoft.DotNet.Tools.Tests.ComponentMocks
return package; return package;
} }
private static bool MatchPackageVersion(MockFeedPackage p, string packageId, string packageVersion) private static bool MatchPackage(MockFeedPackage p, string packageId, VersionRange versionRange)
{ {
if (string.IsNullOrEmpty(packageVersion)) if (string.Compare(p.PackageId, packageId, StringComparison.CurrentCultureIgnoreCase) != 0)
{ {
return p.PackageId == packageId; return false;
} }
return p.PackageId == packageId && p.Version == packageVersion;
return versionRange == null ||
versionRange.FindBestMatch(new[] { NuGetVersion.Parse(p.Version) }) != null;
} }
} }
} }

View file

@ -10,6 +10,7 @@ using Microsoft.DotNet.Cli;
using Microsoft.DotNet.ToolPackage; using Microsoft.DotNet.ToolPackage;
using Microsoft.DotNet.Tools; using Microsoft.DotNet.Tools;
using Microsoft.Extensions.EnvironmentAbstractions; using Microsoft.Extensions.EnvironmentAbstractions;
using NuGet.Versioning;
namespace Microsoft.DotNet.Tools.Tests.ComponentMocks namespace Microsoft.DotNet.Tools.Tests.ComponentMocks
{ {
@ -35,19 +36,19 @@ namespace Microsoft.DotNet.Tools.Tests.ComponentMocks
} }
public IToolPackage InstallPackage( public IToolPackage InstallPackage(
string packageId, PackageId packageId,
string packageVersion = null, VersionRange versionRange = null,
string targetFramework = null, string targetFramework = null,
FilePath? nugetConfig = null, FilePath? nugetConfig = null,
string source = null, string source = null,
string verbosity = null) string verbosity = null)
{ {
var packageRootDirectory = _store.Root.WithSubDirectories(packageId); var packageRootDirectory = _store.GetRootPackageDirectory(packageId);
string rollbackDirectory = null; string rollbackDirectory = null;
return TransactionalAction.Run<IToolPackage>( return TransactionalAction.Run<IToolPackage>(
action: () => { action: () => {
var stageDirectory = _store.Root.WithSubDirectories(".stage", Path.GetRandomFileName()); var stageDirectory = _store.GetRandomStagingDirectory();
_fileSystem.Directory.CreateDirectory(stageDirectory.Value); _fileSystem.Directory.CreateDirectory(stageDirectory.Value);
rollbackDirectory = stageDirectory.Value; rollbackDirectory = stageDirectory.Value;
@ -56,7 +57,7 @@ namespace Microsoft.DotNet.Tools.Tests.ComponentMocks
// Write a fake project with the requested package id, version, and framework // Write a fake project with the requested package id, version, and framework
_fileSystem.File.WriteAllText( _fileSystem.File.WriteAllText(
tempProject.Value, tempProject.Value,
$"{packageId}:{packageVersion}:{targetFramework}"); $"{packageId}:{versionRange?.ToString("S", new VersionRangeFormatter()) ?? "*"}:{targetFramework}");
// Perform a restore on the fake project // Perform a restore on the fake project
_projectRestorer.Restore( _projectRestorer.Restore(
@ -71,29 +72,22 @@ namespace Microsoft.DotNet.Tools.Tests.ComponentMocks
_installCallback(); _installCallback();
} }
packageVersion = Path.GetFileName( var version = _store.GetStagedPackageVersion(stageDirectory, packageId);
_fileSystem.Directory.EnumerateFileSystemEntries( var packageDirectory = _store.GetPackageDirectory(packageId, version);
stageDirectory.WithSubDirectories(packageId).Value).Single());
var packageDirectory = packageRootDirectory.WithSubDirectories(packageVersion);
if (_fileSystem.Directory.Exists(packageDirectory.Value)) if (_fileSystem.Directory.Exists(packageDirectory.Value))
{ {
throw new ToolPackageException( throw new ToolPackageException(
string.Format( string.Format(
CommonLocalizableStrings.ToolPackageConflictPackageId, CommonLocalizableStrings.ToolPackageConflictPackageId,
packageId, packageId,
packageVersion)); version.ToNormalizedString()));
} }
_fileSystem.Directory.CreateDirectory(packageRootDirectory.Value); _fileSystem.Directory.CreateDirectory(packageRootDirectory.Value);
_fileSystem.Directory.Move(stageDirectory.Value, packageDirectory.Value); _fileSystem.Directory.Move(stageDirectory.Value, packageDirectory.Value);
rollbackDirectory = packageDirectory.Value; rollbackDirectory = packageDirectory.Value;
return new ToolPackageMock( return new ToolPackageMock(_fileSystem, packageId, version, packageDirectory);
_fileSystem,
packageId,
packageVersion,
packageDirectory);
}, },
rollback: () => { rollback: () => {
if (rollbackDirectory != null && _fileSystem.Directory.Exists(rollbackDirectory)) if (rollbackDirectory != null && _fileSystem.Directory.Exists(rollbackDirectory))

View file

@ -8,6 +8,7 @@ using System.Linq;
using Microsoft.DotNet.Cli; using Microsoft.DotNet.Cli;
using Microsoft.DotNet.ToolPackage; using Microsoft.DotNet.ToolPackage;
using Microsoft.Extensions.EnvironmentAbstractions; using Microsoft.Extensions.EnvironmentAbstractions;
using NuGet.Versioning;
namespace Microsoft.DotNet.Tools.Tests.ComponentMocks namespace Microsoft.DotNet.Tools.Tests.ComponentMocks
{ {
@ -19,22 +20,22 @@ namespace Microsoft.DotNet.Tools.Tests.ComponentMocks
public ToolPackageMock( public ToolPackageMock(
IFileSystem fileSystem, IFileSystem fileSystem,
string packageId, PackageId id,
string packageVersion, NuGetVersion version,
DirectoryPath packageDirectory, DirectoryPath packageDirectory,
Action uninstallCallback = null) Action uninstallCallback = null)
{ {
_fileSystem = fileSystem ?? throw new ArgumentNullException(nameof(fileSystem)); _fileSystem = fileSystem ?? throw new ArgumentNullException(nameof(fileSystem));
PackageId = packageId ?? throw new ArgumentNullException(nameof(packageId)); Id = id;
PackageVersion = packageVersion ?? throw new ArgumentNullException(nameof(packageVersion)); Version = version ?? throw new ArgumentNullException(nameof(version));
PackageDirectory = packageDirectory; PackageDirectory = packageDirectory;
_commands = new Lazy<IReadOnlyList<CommandSettings>>(GetCommands); _commands = new Lazy<IReadOnlyList<CommandSettings>>(GetCommands);
_uninstallCallback = uninstallCallback; _uninstallCallback = uninstallCallback;
} }
public string PackageId { get; private set; } public PackageId Id { get; private set; }
public string PackageVersion { get; private set; } public NuGetVersion Version { get; private set; }
public DirectoryPath PackageDirectory { get; private set; } public DirectoryPath PackageDirectory { get; private set; }
@ -78,7 +79,7 @@ namespace Microsoft.DotNet.Tools.Tests.ComponentMocks
throw new ToolPackageException( throw new ToolPackageException(
string.Format( string.Format(
CommonLocalizableStrings.FailedToUninstallToolPackage, CommonLocalizableStrings.FailedToUninstallToolPackage,
PackageId, Id,
ex.Message), ex.Message),
ex); ex);
} }
@ -118,7 +119,7 @@ namespace Microsoft.DotNet.Tools.Tests.ComponentMocks
throw new ToolPackageException( throw new ToolPackageException(
string.Format( string.Format(
CommonLocalizableStrings.FailedToRetrieveToolConfiguration, CommonLocalizableStrings.FailedToRetrieveToolConfiguration,
PackageId, Id,
ex.Message), ex.Message),
ex); ex);
} }

View file

@ -8,6 +8,7 @@ using System.Linq;
using Microsoft.DotNet.Cli; using Microsoft.DotNet.Cli;
using Microsoft.DotNet.ToolPackage; using Microsoft.DotNet.ToolPackage;
using Microsoft.Extensions.EnvironmentAbstractions; using Microsoft.Extensions.EnvironmentAbstractions;
using NuGet.Versioning;
namespace Microsoft.DotNet.Tools.Tests.ComponentMocks namespace Microsoft.DotNet.Tools.Tests.ComponentMocks
{ {
@ -28,9 +29,66 @@ namespace Microsoft.DotNet.Tools.Tests.ComponentMocks
public DirectoryPath Root { get; private set; } public DirectoryPath Root { get; private set; }
public IEnumerable<IToolPackage> GetInstalledPackages(string packageId) public DirectoryPath GetRandomStagingDirectory()
{ {
var packageRootDirectory = Root.WithSubDirectories(packageId); return Root.WithSubDirectories(ToolPackageStore.StagingDirectory, Path.GetRandomFileName());
}
public NuGetVersion GetStagedPackageVersion(DirectoryPath stagingDirectory, PackageId packageId)
{
if (NuGetVersion.TryParse(
Path.GetFileName(
_fileSystem.Directory.EnumerateFileSystemEntries(
stagingDirectory.WithSubDirectories(packageId.ToString()).Value).FirstOrDefault()),
out var version))
{
return version;
}
throw new ToolPackageException(
string.Format(
CommonLocalizableStrings.FailedToFindStagedToolPackage,
packageId));
}
public DirectoryPath GetRootPackageDirectory(PackageId packageId)
{
return Root.WithSubDirectories(packageId.ToString());
}
public DirectoryPath GetPackageDirectory(PackageId packageId, NuGetVersion version)
{
return GetRootPackageDirectory(packageId)
.WithSubDirectories(version.ToNormalizedString().ToLowerInvariant());
}
public IEnumerable<IToolPackage> EnumeratePackages()
{
if (!_fileSystem.Directory.Exists(Root.Value))
{
yield break;
}
foreach (var subdirectory in _fileSystem.Directory.EnumerateFileSystemEntries(Root.Value))
{
var name = Path.GetFileName(subdirectory);
var packageId = new PackageId(name);
if (name == ToolPackageStore.StagingDirectory || name != packageId.ToString())
{
continue;
}
foreach (var package in EnumeratePackageVersions(packageId))
{
yield return package;
}
}
}
public IEnumerable<IToolPackage> EnumeratePackageVersions(PackageId packageId)
{
var packageRootDirectory = Root.WithSubDirectories(packageId.ToString());
if (!_fileSystem.Directory.Exists(packageRootDirectory.Value)) if (!_fileSystem.Directory.Exists(packageRootDirectory.Value))
{ {
yield break; yield break;
@ -38,14 +96,23 @@ namespace Microsoft.DotNet.Tools.Tests.ComponentMocks
foreach (var subdirectory in _fileSystem.Directory.EnumerateFileSystemEntries(packageRootDirectory.Value)) foreach (var subdirectory in _fileSystem.Directory.EnumerateFileSystemEntries(packageRootDirectory.Value))
{ {
var version = Path.GetFileName(subdirectory);
yield return new ToolPackageMock( yield return new ToolPackageMock(
_fileSystem, _fileSystem,
packageId, packageId,
version, NuGetVersion.Parse(Path.GetFileName(subdirectory)),
packageRootDirectory.WithSubDirectories(version), new DirectoryPath(subdirectory),
_uninstallCallback); _uninstallCallback);
} }
} }
public IToolPackage GetPackage(PackageId packageId, NuGetVersion version)
{
var directory = GetPackageDirectory(packageId, version);
if (!_fileSystem.Directory.Exists(directory.Value))
{
return null;
}
return new ToolPackageMock(_fileSystem, packageId, version, directory, _uninstallCallback);
}
} }
} }

View file

@ -148,17 +148,12 @@ namespace Microsoft.DotNet.Tests.Commands
installToolCommand.Execute().Should().Be(1); installToolCommand.Execute().Should().Be(1);
_reporter.Lines.Count.Should().Be(2);
_reporter _reporter
.Lines[0] .Lines
.Should() .Should()
.Contain("Simulated error"); .Equal(
"Simulated error".Red(),
_reporter string.Format(LocalizableStrings.ToolInstallationFailed, PackageId).Red());
.Lines[1]
.Should()
.Contain(string.Format(LocalizableStrings.ToolInstallationFailed, PackageId));
_fileSystem.Directory.Exists(Path.Combine(PathToPlacePackages, PackageId)).Should().BeFalse(); _fileSystem.Directory.Exists(Path.Combine(PathToPlacePackages, PackageId)).Should().BeFalse();
} }
@ -205,20 +200,14 @@ namespace Microsoft.DotNet.Tests.Commands
installToolCommand.Execute().Should().Be(1); installToolCommand.Execute().Should().Be(1);
_reporter.Lines.Count.Should().Be(2);
_reporter _reporter
.Lines[0] .Lines
.Should() .Should()
.Contain( .Equal(
string.Format( string.Format(
LocalizableStrings.InvalidToolConfiguration, LocalizableStrings.InvalidToolConfiguration,
"Simulated error")); "Simulated error").Red(),
string.Format(LocalizableStrings.ToolInstallationFailedContactAuthor, PackageId).Red());
_reporter
.Lines[1]
.Should()
.Contain(string.Format(LocalizableStrings.ToolInstallationFailedContactAuthor, PackageId));
} }
[Fact] [Fact]
@ -237,13 +226,144 @@ namespace Microsoft.DotNet.Tests.Commands
_reporter _reporter
.Lines .Lines
.Single()
.Should() .Should()
.Contain(string.Format( .Equal(string.Format(
LocalizableStrings.InstallationSucceeded, LocalizableStrings.InstallationSucceeded,
ProjectRestorerMock.FakeCommandName, ProjectRestorerMock.FakeCommandName,
PackageId, PackageId,
PackageVersion)); PackageVersion).Green());
}
[Fact]
public void WhenRunWithInvalidVersionItShouldThrow()
{
const string invalidVersion = "!NotValidVersion!";
ParseResult result = Parser.Instance.Parse($"dotnet install tool -g {PackageId} --version {invalidVersion}");
AppliedOption appliedCommand = result["dotnet"]["install"]["tool"];
var installToolCommand = new InstallToolCommand(
appliedCommand,
result,
_toolPackageStore,
CreateToolPackageInstaller(),
_shellShimRepositoryMock,
new EnvironmentPathInstructionMock(_reporter, PathToPlaceShim, true),
_reporter);
Action action = () => installToolCommand.Execute();
action
.ShouldThrow<GracefulException>()
.WithMessage(string.Format(
LocalizableStrings.InvalidNuGetVersionRange,
invalidVersion));
}
[Fact]
public void WhenRunWithExactVersionItShouldSucceed()
{
ParseResult result = Parser.Instance.Parse($"dotnet install tool -g {PackageId} --version {PackageVersion}");
AppliedOption appliedCommand = result["dotnet"]["install"]["tool"];
var installToolCommand = new InstallToolCommand(
appliedCommand,
result,
_toolPackageStore,
CreateToolPackageInstaller(),
_shellShimRepositoryMock,
new EnvironmentPathInstructionMock(_reporter, PathToPlaceShim, true),
_reporter);
installToolCommand.Execute().Should().Be(0);
_reporter
.Lines
.Should()
.Equal(string.Format(
LocalizableStrings.InstallationSucceeded,
ProjectRestorerMock.FakeCommandName,
PackageId,
PackageVersion).Green());
}
[Fact]
public void WhenRunWithValidVersionRangeItShouldSucceed()
{
ParseResult result = Parser.Instance.Parse($"dotnet install tool -g {PackageId} --version [1.0,2.0]");
AppliedOption appliedCommand = result["dotnet"]["install"]["tool"];
var installToolCommand = new InstallToolCommand(
appliedCommand,
result,
_toolPackageStore,
CreateToolPackageInstaller(),
_shellShimRepositoryMock,
new EnvironmentPathInstructionMock(_reporter, PathToPlaceShim, true),
_reporter);
installToolCommand.Execute().Should().Be(0);
_reporter
.Lines
.Should()
.Equal(string.Format(
LocalizableStrings.InstallationSucceeded,
ProjectRestorerMock.FakeCommandName,
PackageId,
PackageVersion).Green());
}
[Fact]
public void WhenRunWithoutAMatchingRangeItShouldFail()
{
ParseResult result = Parser.Instance.Parse($"dotnet install tool -g {PackageId} --version [5.0,10.0]");
AppliedOption appliedCommand = result["dotnet"]["install"]["tool"];
var installToolCommand = new InstallToolCommand(
appliedCommand,
result,
_toolPackageStore,
CreateToolPackageInstaller(),
_shellShimRepositoryMock,
new EnvironmentPathInstructionMock(_reporter, PathToPlaceShim, true),
_reporter);
installToolCommand.Execute().Should().Be(1);
_reporter
.Lines
.Should()
.Equal(
$"Error: failed to restore package {PackageId}.", // From mock implementation, not localized
LocalizableStrings.ToolInstallationRestoreFailed.Red(),
string.Format(LocalizableStrings.ToolInstallationFailed, PackageId).Red());
}
[Fact]
public void WhenRunWithValidVersionWildcardItShouldSucceed()
{
ParseResult result = Parser.Instance.Parse($"dotnet install tool -g {PackageId} --version 1.0.*");
AppliedOption appliedCommand = result["dotnet"]["install"]["tool"];
var installToolCommand = new InstallToolCommand(
appliedCommand,
result,
_toolPackageStore,
CreateToolPackageInstaller(),
_shellShimRepositoryMock,
new EnvironmentPathInstructionMock(_reporter, PathToPlaceShim, true),
_reporter);
installToolCommand.Execute().Should().Be(0);
_reporter
.Lines
.Should()
.Equal(string.Format(
LocalizableStrings.InstallationSucceeded,
ProjectRestorerMock.FakeCommandName,
PackageId,
PackageVersion).Green());
} }
private IToolPackageInstaller CreateToolPackageInstaller( private IToolPackageInstaller CreateToolPackageInstaller(