diff --git a/eng/dogfood.ps1 b/eng/dogfood.ps1
index 8cde5ba7b0c2..23eae6bdda00 100644
--- a/eng/dogfood.ps1
+++ b/eng/dogfood.ps1
@@ -47,6 +47,7 @@ try {
$env:PATH = "$TestDotnetRoot;$env:Path"
$env:DOTNET_ROOT = $TestDotnetRoot
+ $env:DOTNET_ADD_GLOBAL_TOOLS_TO_PATH="0"
# Avoid downloading Microsoft.Net.Sdk.Compilers.Toolset from feed
# Locally built SDK package version is Major.Minor.0-dev, which won't be available.
diff --git a/eng/dogfood.sh b/eng/dogfood.sh
index 9394bd4ecbd0..921f68393a10 100755
--- a/eng/dogfood.sh
+++ b/eng/dogfood.sh
@@ -25,4 +25,5 @@ export MicrosoftNETBuildExtensionsTargets="$artifacts_dir/bin/$configuration/Sdk
export PATH=$testDotnetRoot:$PATH
export DOTNET_ROOT=$testDotnetRoot
+export DOTNET_ADD_GLOBAL_TOOLS_TO_PATH=0
export PS1="(dogfood) $PS1"
\ No newline at end of file
diff --git a/eng/restore-toolset.ps1 b/eng/restore-toolset.ps1
index bab26d21c1a3..c4624758adfe 100644
--- a/eng/restore-toolset.ps1
+++ b/eng/restore-toolset.ps1
@@ -51,6 +51,7 @@ set DOTNET_MSBUILD_SDK_RESOLVER_CLI_DIR=$env:DOTNET_INSTALL_DIR
set PATH=$env:DOTNET_INSTALL_DIR;%PATH%
set NUGET_PACKAGES=$env:NUGET_PACKAGES
+set DOTNET_ADD_GLOBAL_TOOLS_TO_PATH=0
DOSKEY killdotnet=taskkill /F /IM dotnet.exe /T ^& taskkill /F /IM VSTest.Console.exe /T ^& taskkill /F /IM msbuild.exe /T
"@
@@ -70,6 +71,7 @@ DOSKEY killdotnet=taskkill /F /IM dotnet.exe /T ^& taskkill /F /IM VSTest.Consol
`$env:PATH="$env:DOTNET_INSTALL_DIR;" + `$env:PATH
`$env:NUGET_PACKAGES="$env:NUGET_PACKAGES"
+`$env:DOTNET_ADD_GLOBAL_TOOLS_TO_PATH="0"
function killdotnet {
taskkill /F /IM dotnet.exe /T
diff --git a/eng/restore-toolset.sh b/eng/restore-toolset.sh
index 579fb11bf6c3..42f0c88d9cf3 100755
--- a/eng/restore-toolset.sh
+++ b/eng/restore-toolset.sh
@@ -61,6 +61,7 @@ export DOTNET_MSBUILD_SDK_RESOLVER_CLI_DIR=$DOTNET_INSTALL_DIR
export PATH=$DOTNET_INSTALL_DIR:\$PATH
export NUGET_PACKAGES=$NUGET_PACKAGES
+export DOTNET_ADD_GLOBAL_TOOLS_TO_PATH=0
"
echo "$scriptContents" > ${scriptPath}
diff --git a/src/Cli/dotnet/CliStrings.resx b/src/Cli/dotnet/CliStrings.resx
index cf4b6b130d54..1acd6a165830 100644
--- a/src/Cli/dotnet/CliStrings.resx
+++ b/src/Cli/dotnet/CliStrings.resx
@@ -319,6 +319,9 @@
Command '{0}' uses unsupported runner '{1}'."
+
+ The tool does not support the current architecture or operating system ({0}). Supported runtimes: {1}
+
Command '{0}' conflicts with an existing command from another tool.
@@ -413,6 +416,9 @@ setx PATH "%PATH%;{0}"
Tool '{0}' (version '{1}') is already installed.
+
+ Package {0} is not a .NET tool.
+
Failed to find staged tool package '{0}'.
@@ -435,7 +441,10 @@ setx PATH "%PATH%;{0}"
More than one packaged shim is available: {0}.
- Failed to read NuGet LockFile for tool package '{0}': {1}
+ Failed to read NuGet assets file for tool package '{0}': {1}
+
+
+ Failed to find library in NuGet assets file for tool package '{0}': {1}LEVEL
diff --git a/src/Cli/dotnet/CommandFactory/CommandResolution/LocalToolsCommandResolver.cs b/src/Cli/dotnet/CommandFactory/CommandResolution/LocalToolsCommandResolver.cs
index 8ac809931781..d9845c0aea06 100644
--- a/src/Cli/dotnet/CommandFactory/CommandResolution/LocalToolsCommandResolver.cs
+++ b/src/Cli/dotnet/CommandFactory/CommandResolution/LocalToolsCommandResolver.cs
@@ -7,6 +7,7 @@
using Microsoft.DotNet.Cli.ToolPackage;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.Extensions.EnvironmentAbstractions;
+using NuGet.DependencyResolver;
using NuGet.Frameworks;
namespace Microsoft.DotNet.Cli.CommandFactory.CommandResolution;
@@ -82,22 +83,39 @@ private CommandSpec GetPackageCommandSpecUsingMuxer(CommandResolverArguments arg
NuGetFramework.Parse(BundledTargetFramework.GetTargetFrameworkMoniker()),
Constants.AnyRid,
toolCommandName),
- out var restoredCommand))
+ out var toolCommand))
{
- if (!_fileSystem.File.Exists(restoredCommand.Executable.Value))
+ if (!_fileSystem.File.Exists(toolCommand.Executable.Value))
{
throw new GracefulException(string.Format(CliStrings.NeedRunToolRestore,
toolCommandName.ToString()));
}
- if (toolManifestPackage.RollForward || allowRollForward)
+ if (toolCommand.Runner == "dotnet")
{
- arguments.CommandArguments = ["--allow-roll-forward", .. arguments.CommandArguments];
+ if (toolManifestPackage.RollForward || allowRollForward)
+ {
+ arguments.CommandArguments = ["--allow-roll-forward", .. arguments.CommandArguments];
+ }
+
+ return MuxerCommandSpecMaker.CreatePackageCommandSpecUsingMuxer(
+ toolCommand.Executable.Value,
+ arguments.CommandArguments);
}
+ else if (toolCommand.Runner == "executable")
+ {
+ var escapedArgs = ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(
+ arguments.CommandArguments);
- return MuxerCommandSpecMaker.CreatePackageCommandSpecUsingMuxer(
- restoredCommand.Executable.Value,
- arguments.CommandArguments);
+ return new CommandSpec(
+ toolCommand.Executable.Value,
+ escapedArgs);
+ }
+ else
+ {
+ throw new GracefulException(string.Format(CliStrings.ToolSettingsUnsupportedRunner,
+ toolCommand.Name, toolCommand.Runner));
+ }
}
else
{
diff --git a/src/Cli/dotnet/Commands/CliCommandStrings.resx b/src/Cli/dotnet/Commands/CliCommandStrings.resx
index 82b2f559d0f4..ede0617ae9d2 100644
--- a/src/Cli/dotnet/Commands/CliCommandStrings.resx
+++ b/src/Cli/dotnet/Commands/CliCommandStrings.resx
@@ -1938,16 +1938,6 @@ Your project targets multiple frameworks. Specify which framework to run using '
Tool '{0}' failed to install. Contact the tool author for assistance.
-
- Tool '{0}' failed to install. This failure may have been caused by:
-
-* You are attempting to install a preview release and did not use the --version option to specify the version.
-* A package by this name was found, but it was not a .NET tool.
-* The required NuGet feed cannot be accessed, perhaps because of an Internet connection problem.
-* You mistyped the name of the tool.
-
-For more reasons, including package naming enforcement, visit https://aka.ms/failure-installing-tool
-
The tool package could not be restored.
@@ -2486,4 +2476,4 @@ To display a value, specify the corresponding command-line option without provid
Recursively add projects' ReferencedProjects to solution
-
\ No newline at end of file
+
diff --git a/src/Cli/dotnet/Commands/Pack/PackCommandParser.cs b/src/Cli/dotnet/Commands/Pack/PackCommandParser.cs
index 59a44b53efd0..41c8c5530bfa 100644
--- a/src/Cli/dotnet/Commands/Pack/PackCommandParser.cs
+++ b/src/Cli/dotnet/Commands/Pack/PackCommandParser.cs
@@ -84,7 +84,10 @@ private static Command ConstructCommand()
command.Options.Add(CommonOptions.VersionSuffixOption);
command.Options.Add(ConfigurationOption);
command.Options.Add(CommonOptions.DisableBuildServersOption);
- RestoreCommandParser.AddImplicitRestoreOptions(command, includeRuntimeOption: true, includeNoDependenciesOption: true);
+
+ // Don't include runtime option because we want to include it specifically and allow the short version ("-r") to be used
+ RestoreCommandParser.AddImplicitRestoreOptions(command, includeRuntimeOption: false, includeNoDependenciesOption: true);
+ command.Options.Add(CommonOptions.RuntimeOption(CliCommandStrings.BuildRuntimeOptionDescription));
command.SetAction(PackCommand.Run);
diff --git a/src/Cli/dotnet/Commands/Tool/Install/LocalToolsResolverCacheExtensions.cs b/src/Cli/dotnet/Commands/Tool/Install/LocalToolsResolverCacheExtensions.cs
index 391c21b7fda3..a9a7eba26e0d 100644
--- a/src/Cli/dotnet/Commands/Tool/Install/LocalToolsResolverCacheExtensions.cs
+++ b/src/Cli/dotnet/Commands/Tool/Install/LocalToolsResolverCacheExtensions.cs
@@ -33,7 +33,7 @@ public static void SaveToolPackage(
}
localToolsResolverCache.Save(
- new Dictionary
+ new Dictionary
{
[new RestoredCommandIdentifier(
toolDownloadedPackage.Id,
diff --git a/src/Cli/dotnet/Commands/Tool/Install/ToolInstallCommandLowLevelErrorConverter.cs b/src/Cli/dotnet/Commands/Tool/Install/ToolInstallCommandLowLevelErrorConverter.cs
index e250514422c3..955e8cc71e92 100644
--- a/src/Cli/dotnet/Commands/Tool/Install/ToolInstallCommandLowLevelErrorConverter.cs
+++ b/src/Cli/dotnet/Commands/Tool/Install/ToolInstallCommandLowLevelErrorConverter.cs
@@ -12,12 +12,7 @@ internal static class InstallToolCommandLowLevelErrorConverter
{
public static IEnumerable GetUserFacingMessages(Exception ex, PackageId packageId)
{
- if (ex is ToolPackageException)
- {
- yield return ex.Message;
- yield return string.Format(CliCommandStrings.ToolInstallationFailedWithRestoreGuidance, packageId);
- }
- else if (ex is ToolConfigurationException)
+ if (ex is ToolConfigurationException)
{
yield return string.Format(CliCommandStrings.InvalidToolConfiguration, ex.Message);
yield return string.Format(CliCommandStrings.ToolInstallationFailedContactAuthor, packageId);
@@ -31,8 +26,7 @@ public static IEnumerable GetUserFacingMessages(Exception ex, PackageId
public static bool ShouldConvertToUserFacingError(Exception ex)
{
- return ex is ToolPackageException
- || ex is ToolConfigurationException
+ return ex is ToolConfigurationException
|| ex is ShellShimException;
}
}
diff --git a/src/Cli/dotnet/Commands/Tool/Install/ToolInstallGlobalOrToolPathCommand.cs b/src/Cli/dotnet/Commands/Tool/Install/ToolInstallGlobalOrToolPathCommand.cs
index 36b1f77be81a..1107e8558214 100644
--- a/src/Cli/dotnet/Commands/Tool/Install/ToolInstallGlobalOrToolPathCommand.cs
+++ b/src/Cli/dotnet/Commands/Tool/Install/ToolInstallGlobalOrToolPathCommand.cs
@@ -91,7 +91,7 @@ public ToolInstallGlobalOrToolPathCommand(
var tempDir = new DirectoryPath(PathUtilities.CreateTempSubdirectory());
var configOption = parseResult.GetValue(ToolInstallCommandParser.ConfigOption);
var sourceOption = parseResult.GetValue(ToolInstallCommandParser.AddSourceOption);
- var packageSourceLocation = new PackageSourceLocation(string.IsNullOrEmpty(configOption) ? null : new FilePath(configOption), additionalSourceFeeds: sourceOption);
+ var packageSourceLocation = new PackageSourceLocation(string.IsNullOrEmpty(configOption) ? null : new FilePath(configOption), additionalSourceFeeds: sourceOption, basePath: _currentWorkingDirectory);
restoreActionConfig = new RestoreActionConfig(DisableParallel: parseResult.GetValue(ToolCommandRestorePassThroughOptions.DisableParallelOption),
NoCache: parseResult.GetValue(ToolCommandRestorePassThroughOptions.NoCacheOption) || parseResult.GetValue(ToolCommandRestorePassThroughOptions.NoHttpCacheOption),
IgnoreFailedSources: parseResult.GetValue(ToolCommandRestorePassThroughOptions.IgnoreFailedSourcesOption),
@@ -175,15 +175,13 @@ private int ExecuteInstallCommand(PackageId packageId)
}
}
- using (var scope = new TransactionScope(
- TransactionScopeOption.Required,
- TimeSpan.Zero))
+ TransactionalAction.Run(() =>
{
if (oldPackageNullable != null)
{
RunWithHandlingUninstallError(() =>
{
- shellShimRepository.RemoveShim(oldPackageNullable.Command.Name);
+ shellShimRepository.RemoveShim(oldPackageNullable.Command);
toolPackageUninstaller.Uninstall(oldPackageNullable.PackageDirectory);
}, packageId);
}
@@ -219,7 +217,7 @@ private int ExecuteInstallCommand(PackageId packageId)
}
string appHostSourceDirectory = _shellShimTemplateFinder.ResolveAppHostSourceDirectoryAsync(_architectureOption, framework, RuntimeInformation.ProcessArchitecture).Result;
- shellShimRepository.CreateShim(newInstalledPackage.Command.Executable, newInstalledPackage.Command.Name, newInstalledPackage.PackagedShims);
+ shellShimRepository.CreateShim(newInstalledPackage.Command, newInstalledPackage.PackagedShims);
foreach (string w in newInstalledPackage.Warnings)
{
@@ -232,10 +230,7 @@ private int ExecuteInstallCommand(PackageId packageId)
PrintSuccessMessage(oldPackageNullable, newInstalledPackage);
}, packageId);
-
- scope.Complete();
-
- }
+ });
return 0;
}
diff --git a/src/Cli/dotnet/Commands/Tool/Install/ToolInstallLocalInstaller.cs b/src/Cli/dotnet/Commands/Tool/Install/ToolInstallLocalInstaller.cs
index 720a2e7e3102..ad4985e42f3c 100644
--- a/src/Cli/dotnet/Commands/Tool/Install/ToolInstallLocalInstaller.cs
+++ b/src/Cli/dotnet/Commands/Tool/Install/ToolInstallLocalInstaller.cs
@@ -66,11 +66,17 @@ public IToolPackage Install(FilePath manifestFile, PackageId packageId)
try
{
+ // NOTE: The manifest file may or may not be under a .config folder. If it is, we will use
+ // that directory as the root config directory. This should be OK, as usually there won't be
+ // a NuGet.config in the .config folder, and if there is it's better to use it than to go one
+ // more level up and miss the root repo folder if the manifest file is not under a .config folder.
+ var rootConfigDirectory = manifestFile.GetDirectoryPath();
+
IToolPackage toolDownloadedPackage = _toolPackageDownloader.InstallPackage(
new PackageLocation(
nugetConfig: configFile,
additionalFeeds: _sources,
- rootConfigDirectory: manifestFile.GetDirectoryPath().GetParentPath()),
+ rootConfigDirectory: rootConfigDirectory),
packageId,
verbosity: _verbosity,
versionRange,
diff --git a/src/Cli/dotnet/Commands/Tool/Restore/ToolRestoreCommand.cs b/src/Cli/dotnet/Commands/Tool/Restore/ToolRestoreCommand.cs
index f4712b9508c1..465d598d81e2 100644
--- a/src/Cli/dotnet/Commands/Tool/Restore/ToolRestoreCommand.cs
+++ b/src/Cli/dotnet/Commands/Tool/Restore/ToolRestoreCommand.cs
@@ -108,7 +108,7 @@ [.. packagesFromManifest
.AsEnumerable()
.Select(package => InstallPackages(package, configFile))];
- Dictionary downloaded =
+ Dictionary downloaded =
toolRestoreResults.SelectMany(result => result.SaveToCache)
.ToDictionary(pair => pair.Item1, pair => pair.Item2);
@@ -216,7 +216,7 @@ private int PrintConclusionAndReturn(ToolRestoreResult[] toolRestoreResults)
private static bool ManifestCommandMatchesActualInPackage(
ToolCommandName[] commandsFromManifest,
- IReadOnlyList toolPackageCommands)
+ IReadOnlyList toolPackageCommands)
{
ToolCommandName[] commandsFromPackage = [.. toolPackageCommands.Select(t => t.Name)];
foreach (var command in commandsFromManifest)
@@ -251,8 +251,8 @@ private bool PackageHasBeenRestored(
return _localToolsResolverCache.TryLoad(
sampleRestoredCommandIdentifierOfThePackage,
- out var restoredCommand)
- && _fileSystem.File.Exists(restoredCommand.Executable.Value);
+ out var toolCommand)
+ && _fileSystem.File.Exists(toolCommand.Executable.Value);
}
private FilePath? GetCustomManifestFileLocation()
@@ -271,7 +271,7 @@ private bool PackageHasBeenRestored(
return customManifestFileLocation;
}
- private static void EnsureNoCommandNameCollision(Dictionary dictionary)
+ private static void EnsureNoCommandNameCollision(Dictionary dictionary)
{
string[] errors = [.. dictionary
.Select(pair => (pair.Key.PackageId, pair.Key.CommandName))
@@ -308,12 +308,12 @@ private static VersionRange ToVersionRangeWithOnlyOneVersion(NuGetVersion versio
private struct ToolRestoreResult
{
- public (RestoredCommandIdentifier, RestoredCommand)[] SaveToCache { get; }
+ public (RestoredCommandIdentifier, ToolCommand)[] SaveToCache { get; }
public bool IsSuccess { get; }
public string Message { get; }
private ToolRestoreResult(
- (RestoredCommandIdentifier, RestoredCommand)[] saveToCache,
+ (RestoredCommandIdentifier, ToolCommand)[] saveToCache,
bool isSuccess, string message)
{
if (string.IsNullOrWhiteSpace(message))
@@ -327,7 +327,7 @@ private ToolRestoreResult(
}
public static ToolRestoreResult Success(
- (RestoredCommandIdentifier, RestoredCommand)[] saveToCache,
+ (RestoredCommandIdentifier, ToolCommand)[] saveToCache,
string message)
{
return new ToolRestoreResult(saveToCache, true, message);
diff --git a/src/Cli/dotnet/Commands/Tool/Uninstall/ToolUninstallGlobalOrToolPathCommand.cs b/src/Cli/dotnet/Commands/Tool/Uninstall/ToolUninstallGlobalOrToolPathCommand.cs
index 8ce5e0b888af..58db9f55cc04 100644
--- a/src/Cli/dotnet/Commands/Tool/Uninstall/ToolUninstallGlobalOrToolPathCommand.cs
+++ b/src/Cli/dotnet/Commands/Tool/Uninstall/ToolUninstallGlobalOrToolPathCommand.cs
@@ -70,16 +70,12 @@ public override int Execute()
try
{
- using (var scope = new TransactionScope(
- TransactionScopeOption.Required,
- TimeSpan.Zero))
+ TransactionalAction.Run(() =>
{
- shellShimRepository.RemoveShim(package.Command.Name);
+ shellShimRepository.RemoveShim(package.Command);
toolPackageUninstaller.Uninstall(package.PackageDirectory);
-
- scope.Complete();
- }
+ });
_reporter.WriteLine(
string.Format(
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.cs.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.cs.xlf
index 905e767f24ab..40a1e5189fa6 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.cs.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.cs.xlf
@@ -3055,25 +3055,6 @@ If you would like to create a manifest, use the `--create-manifest-if-needed` fl
Tool '{0}' failed to install. Contact the tool author for assistance.
-
- Tool '{0}' failed to install. This failure may have been caused by:
-
-* You are attempting to install a preview release and did not use the --version option to specify the version.
-* A package by this name was found, but it was not a .NET tool.
-* The required NuGet feed cannot be accessed, perhaps because of an Internet connection problem.
-* You mistyped the name of the tool.
-
-For more reasons, including package naming enforcement, visit https://aka.ms/failure-installing-tool
- Tool '{0}' failed to install. This failure may have been caused by:
-
-* You are attempting to install a preview release and did not use the --version option to specify the version.
-* A package by this name was found, but it was not a .NET tool.
-* The required NuGet feed cannot be accessed, perhaps because of an Internet connection problem.
-* You mistyped the name of the tool.
-
-For more reasons, including package naming enforcement, visit https://aka.ms/failure-installing-tool
-
- The tool package could not be restored.The tool package could not be restored.
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.de.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.de.xlf
index 3896c64b9e61..c795c89be56b 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.de.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.de.xlf
@@ -3055,25 +3055,6 @@ If you would like to create a manifest, use the `--create-manifest-if-needed` fl
Tool '{0}' failed to install. Contact the tool author for assistance.
-
- Tool '{0}' failed to install. This failure may have been caused by:
-
-* You are attempting to install a preview release and did not use the --version option to specify the version.
-* A package by this name was found, but it was not a .NET tool.
-* The required NuGet feed cannot be accessed, perhaps because of an Internet connection problem.
-* You mistyped the name of the tool.
-
-For more reasons, including package naming enforcement, visit https://aka.ms/failure-installing-tool
- Tool '{0}' failed to install. This failure may have been caused by:
-
-* You are attempting to install a preview release and did not use the --version option to specify the version.
-* A package by this name was found, but it was not a .NET tool.
-* The required NuGet feed cannot be accessed, perhaps because of an Internet connection problem.
-* You mistyped the name of the tool.
-
-For more reasons, including package naming enforcement, visit https://aka.ms/failure-installing-tool
-
- The tool package could not be restored.The tool package could not be restored.
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.es.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.es.xlf
index 20afd4520f23..87c250c83c14 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.es.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.es.xlf
@@ -3055,25 +3055,6 @@ If you would like to create a manifest, use the `--create-manifest-if-needed` fl
Tool '{0}' failed to install. Contact the tool author for assistance.
-
- Tool '{0}' failed to install. This failure may have been caused by:
-
-* You are attempting to install a preview release and did not use the --version option to specify the version.
-* A package by this name was found, but it was not a .NET tool.
-* The required NuGet feed cannot be accessed, perhaps because of an Internet connection problem.
-* You mistyped the name of the tool.
-
-For more reasons, including package naming enforcement, visit https://aka.ms/failure-installing-tool
- Tool '{0}' failed to install. This failure may have been caused by:
-
-* You are attempting to install a preview release and did not use the --version option to specify the version.
-* A package by this name was found, but it was not a .NET tool.
-* The required NuGet feed cannot be accessed, perhaps because of an Internet connection problem.
-* You mistyped the name of the tool.
-
-For more reasons, including package naming enforcement, visit https://aka.ms/failure-installing-tool
-
- The tool package could not be restored.The tool package could not be restored.
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.fr.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.fr.xlf
index 71ff36a7e759..ef30f2a8ef9c 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.fr.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.fr.xlf
@@ -3055,25 +3055,6 @@ If you would like to create a manifest, use the `--create-manifest-if-needed` fl
Tool '{0}' failed to install. Contact the tool author for assistance.
-
- Tool '{0}' failed to install. This failure may have been caused by:
-
-* You are attempting to install a preview release and did not use the --version option to specify the version.
-* A package by this name was found, but it was not a .NET tool.
-* The required NuGet feed cannot be accessed, perhaps because of an Internet connection problem.
-* You mistyped the name of the tool.
-
-For more reasons, including package naming enforcement, visit https://aka.ms/failure-installing-tool
- Tool '{0}' failed to install. This failure may have been caused by:
-
-* You are attempting to install a preview release and did not use the --version option to specify the version.
-* A package by this name was found, but it was not a .NET tool.
-* The required NuGet feed cannot be accessed, perhaps because of an Internet connection problem.
-* You mistyped the name of the tool.
-
-For more reasons, including package naming enforcement, visit https://aka.ms/failure-installing-tool
-
- The tool package could not be restored.The tool package could not be restored.
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.it.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.it.xlf
index 3a29e67f41db..66e863b40a8a 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.it.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.it.xlf
@@ -3055,25 +3055,6 @@ If you would like to create a manifest, use the `--create-manifest-if-needed` fl
Tool '{0}' failed to install. Contact the tool author for assistance.
-
- Tool '{0}' failed to install. This failure may have been caused by:
-
-* You are attempting to install a preview release and did not use the --version option to specify the version.
-* A package by this name was found, but it was not a .NET tool.
-* The required NuGet feed cannot be accessed, perhaps because of an Internet connection problem.
-* You mistyped the name of the tool.
-
-For more reasons, including package naming enforcement, visit https://aka.ms/failure-installing-tool
- Tool '{0}' failed to install. This failure may have been caused by:
-
-* You are attempting to install a preview release and did not use the --version option to specify the version.
-* A package by this name was found, but it was not a .NET tool.
-* The required NuGet feed cannot be accessed, perhaps because of an Internet connection problem.
-* You mistyped the name of the tool.
-
-For more reasons, including package naming enforcement, visit https://aka.ms/failure-installing-tool
-
- The tool package could not be restored.The tool package could not be restored.
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ja.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ja.xlf
index 5c1579261b1a..b1bc5a8d953d 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ja.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ja.xlf
@@ -3055,25 +3055,6 @@ If you would like to create a manifest, use the `--create-manifest-if-needed` fl
Tool '{0}' failed to install. Contact the tool author for assistance.
-
- Tool '{0}' failed to install. This failure may have been caused by:
-
-* You are attempting to install a preview release and did not use the --version option to specify the version.
-* A package by this name was found, but it was not a .NET tool.
-* The required NuGet feed cannot be accessed, perhaps because of an Internet connection problem.
-* You mistyped the name of the tool.
-
-For more reasons, including package naming enforcement, visit https://aka.ms/failure-installing-tool
- Tool '{0}' failed to install. This failure may have been caused by:
-
-* You are attempting to install a preview release and did not use the --version option to specify the version.
-* A package by this name was found, but it was not a .NET tool.
-* The required NuGet feed cannot be accessed, perhaps because of an Internet connection problem.
-* You mistyped the name of the tool.
-
-For more reasons, including package naming enforcement, visit https://aka.ms/failure-installing-tool
-
- The tool package could not be restored.The tool package could not be restored.
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ko.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ko.xlf
index 2b3218faac44..b40650d304bc 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ko.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ko.xlf
@@ -3055,25 +3055,6 @@ If you would like to create a manifest, use the `--create-manifest-if-needed` fl
Tool '{0}' failed to install. Contact the tool author for assistance.
-
- Tool '{0}' failed to install. This failure may have been caused by:
-
-* You are attempting to install a preview release and did not use the --version option to specify the version.
-* A package by this name was found, but it was not a .NET tool.
-* The required NuGet feed cannot be accessed, perhaps because of an Internet connection problem.
-* You mistyped the name of the tool.
-
-For more reasons, including package naming enforcement, visit https://aka.ms/failure-installing-tool
- Tool '{0}' failed to install. This failure may have been caused by:
-
-* You are attempting to install a preview release and did not use the --version option to specify the version.
-* A package by this name was found, but it was not a .NET tool.
-* The required NuGet feed cannot be accessed, perhaps because of an Internet connection problem.
-* You mistyped the name of the tool.
-
-For more reasons, including package naming enforcement, visit https://aka.ms/failure-installing-tool
-
- The tool package could not be restored.The tool package could not be restored.
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pl.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pl.xlf
index 9a75d810dd44..8e34a1a7e43f 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pl.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pl.xlf
@@ -3055,25 +3055,6 @@ If you would like to create a manifest, use the `--create-manifest-if-needed` fl
Tool '{0}' failed to install. Contact the tool author for assistance.
-
- Tool '{0}' failed to install. This failure may have been caused by:
-
-* You are attempting to install a preview release and did not use the --version option to specify the version.
-* A package by this name was found, but it was not a .NET tool.
-* The required NuGet feed cannot be accessed, perhaps because of an Internet connection problem.
-* You mistyped the name of the tool.
-
-For more reasons, including package naming enforcement, visit https://aka.ms/failure-installing-tool
- Tool '{0}' failed to install. This failure may have been caused by:
-
-* You are attempting to install a preview release and did not use the --version option to specify the version.
-* A package by this name was found, but it was not a .NET tool.
-* The required NuGet feed cannot be accessed, perhaps because of an Internet connection problem.
-* You mistyped the name of the tool.
-
-For more reasons, including package naming enforcement, visit https://aka.ms/failure-installing-tool
-
- The tool package could not be restored.The tool package could not be restored.
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pt-BR.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pt-BR.xlf
index 72a2415040df..0b308fd9d0f7 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pt-BR.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pt-BR.xlf
@@ -3055,25 +3055,6 @@ If you would like to create a manifest, use the `--create-manifest-if-needed` fl
Tool '{0}' failed to install. Contact the tool author for assistance.
-
- Tool '{0}' failed to install. This failure may have been caused by:
-
-* You are attempting to install a preview release and did not use the --version option to specify the version.
-* A package by this name was found, but it was not a .NET tool.
-* The required NuGet feed cannot be accessed, perhaps because of an Internet connection problem.
-* You mistyped the name of the tool.
-
-For more reasons, including package naming enforcement, visit https://aka.ms/failure-installing-tool
- Tool '{0}' failed to install. This failure may have been caused by:
-
-* You are attempting to install a preview release and did not use the --version option to specify the version.
-* A package by this name was found, but it was not a .NET tool.
-* The required NuGet feed cannot be accessed, perhaps because of an Internet connection problem.
-* You mistyped the name of the tool.
-
-For more reasons, including package naming enforcement, visit https://aka.ms/failure-installing-tool
-
- The tool package could not be restored.The tool package could not be restored.
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ru.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ru.xlf
index 04df2e5813ca..15be059276e5 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ru.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ru.xlf
@@ -3055,25 +3055,6 @@ If you would like to create a manifest, use the `--create-manifest-if-needed` fl
Tool '{0}' failed to install. Contact the tool author for assistance.
-
- Tool '{0}' failed to install. This failure may have been caused by:
-
-* You are attempting to install a preview release and did not use the --version option to specify the version.
-* A package by this name was found, but it was not a .NET tool.
-* The required NuGet feed cannot be accessed, perhaps because of an Internet connection problem.
-* You mistyped the name of the tool.
-
-For more reasons, including package naming enforcement, visit https://aka.ms/failure-installing-tool
- Tool '{0}' failed to install. This failure may have been caused by:
-
-* You are attempting to install a preview release and did not use the --version option to specify the version.
-* A package by this name was found, but it was not a .NET tool.
-* The required NuGet feed cannot be accessed, perhaps because of an Internet connection problem.
-* You mistyped the name of the tool.
-
-For more reasons, including package naming enforcement, visit https://aka.ms/failure-installing-tool
-
- The tool package could not be restored.The tool package could not be restored.
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.tr.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.tr.xlf
index 892aecbdce6b..0b7b2addb199 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.tr.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.tr.xlf
@@ -3055,25 +3055,6 @@ If you would like to create a manifest, use the `--create-manifest-if-needed` fl
Tool '{0}' failed to install. Contact the tool author for assistance.
-
- Tool '{0}' failed to install. This failure may have been caused by:
-
-* You are attempting to install a preview release and did not use the --version option to specify the version.
-* A package by this name was found, but it was not a .NET tool.
-* The required NuGet feed cannot be accessed, perhaps because of an Internet connection problem.
-* You mistyped the name of the tool.
-
-For more reasons, including package naming enforcement, visit https://aka.ms/failure-installing-tool
- Tool '{0}' failed to install. This failure may have been caused by:
-
-* You are attempting to install a preview release and did not use the --version option to specify the version.
-* A package by this name was found, but it was not a .NET tool.
-* The required NuGet feed cannot be accessed, perhaps because of an Internet connection problem.
-* You mistyped the name of the tool.
-
-For more reasons, including package naming enforcement, visit https://aka.ms/failure-installing-tool
-
- The tool package could not be restored.The tool package could not be restored.
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hans.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hans.xlf
index 08f128a0eeab..fd53a87098be 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hans.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hans.xlf
@@ -3055,25 +3055,6 @@ If you would like to create a manifest, use the `--create-manifest-if-needed` fl
Tool '{0}' failed to install. Contact the tool author for assistance.
-
- Tool '{0}' failed to install. This failure may have been caused by:
-
-* You are attempting to install a preview release and did not use the --version option to specify the version.
-* A package by this name was found, but it was not a .NET tool.
-* The required NuGet feed cannot be accessed, perhaps because of an Internet connection problem.
-* You mistyped the name of the tool.
-
-For more reasons, including package naming enforcement, visit https://aka.ms/failure-installing-tool
- Tool '{0}' failed to install. This failure may have been caused by:
-
-* You are attempting to install a preview release and did not use the --version option to specify the version.
-* A package by this name was found, but it was not a .NET tool.
-* The required NuGet feed cannot be accessed, perhaps because of an Internet connection problem.
-* You mistyped the name of the tool.
-
-For more reasons, including package naming enforcement, visit https://aka.ms/failure-installing-tool
-
- The tool package could not be restored.The tool package could not be restored.
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hant.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hant.xlf
index 61319bc77d40..20c06fd3cd4a 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hant.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hant.xlf
@@ -3055,25 +3055,6 @@ If you would like to create a manifest, use the `--create-manifest-if-needed` fl
Tool '{0}' failed to install. Contact the tool author for assistance.
-
- Tool '{0}' failed to install. This failure may have been caused by:
-
-* You are attempting to install a preview release and did not use the --version option to specify the version.
-* A package by this name was found, but it was not a .NET tool.
-* The required NuGet feed cannot be accessed, perhaps because of an Internet connection problem.
-* You mistyped the name of the tool.
-
-For more reasons, including package naming enforcement, visit https://aka.ms/failure-installing-tool
- Tool '{0}' failed to install. This failure may have been caused by:
-
-* You are attempting to install a preview release and did not use the --version option to specify the version.
-* A package by this name was found, but it was not a .NET tool.
-* The required NuGet feed cannot be accessed, perhaps because of an Internet connection problem.
-* You mistyped the name of the tool.
-
-For more reasons, including package naming enforcement, visit https://aka.ms/failure-installing-tool
-
- The tool package could not be restored.The tool package could not be restored.
diff --git a/src/Cli/dotnet/NugetPackageDownloader/NuGetPackageDownloader.cs b/src/Cli/dotnet/NugetPackageDownloader/NuGetPackageDownloader.cs
index cc5727904e7c..3de046a03122 100644
--- a/src/Cli/dotnet/NugetPackageDownloader/NuGetPackageDownloader.cs
+++ b/src/Cli/dotnet/NugetPackageDownloader/NuGetPackageDownloader.cs
@@ -114,7 +114,13 @@ public async Task DownloadPackageAsync(PackageId packageId,
string.Format(CliStrings.IsNotFoundInNuGetFeeds, packageId, source.Source));
}
- var pathResolver = new VersionFolderPathResolver(downloadFolder == null || !downloadFolder.HasValue ? _packageInstallDir.Value : downloadFolder.Value.Value);
+ var resolvedDownloadFolder = downloadFolder == null || !downloadFolder.HasValue ? _packageInstallDir.Value : downloadFolder.Value.Value;
+ if (string.IsNullOrEmpty(resolvedDownloadFolder))
+ {
+ throw new ArgumentException($"Package download folder must be specified either via {nameof(NuGetPackageDownloader)} constructor or via {nameof(downloadFolder)} method argument.");
+ }
+ var pathResolver = new VersionFolderPathResolver(resolvedDownloadFolder);
+
string nupkgPath = pathResolver.GetPackageFilePath(packageId.ToString(), resolvedPackageVersion);
Directory.CreateDirectory(Path.GetDirectoryName(nupkgPath));
diff --git a/src/Cli/dotnet/NugetPackageDownloader/PackageSourceLocation.cs b/src/Cli/dotnet/NugetPackageDownloader/PackageSourceLocation.cs
index 38bae2aaf930..ed70adeaf924 100644
--- a/src/Cli/dotnet/NugetPackageDownloader/PackageSourceLocation.cs
+++ b/src/Cli/dotnet/NugetPackageDownloader/PackageSourceLocation.cs
@@ -13,14 +13,17 @@ public PackageSourceLocation(
FilePath? nugetConfig = null,
DirectoryPath? rootConfigDirectory = null,
string[] sourceFeedOverrides = null,
- string[] additionalSourceFeeds = null)
+ string[] additionalSourceFeeds = null,
+ string basePath = null)
{
+ basePath = basePath ?? Directory.GetCurrentDirectory();
+
NugetConfig = nugetConfig;
RootConfigDirectory = rootConfigDirectory;
// Overrides other feeds
- SourceFeedOverrides = ExpandLocalFeed(sourceFeedOverrides);
+ SourceFeedOverrides = ExpandLocalFeed(sourceFeedOverrides, basePath);
// Feeds to be using in addition to config
- AdditionalSourceFeed = ExpandLocalFeed(additionalSourceFeeds);
+ AdditionalSourceFeed = ExpandLocalFeed(additionalSourceFeeds, basePath);
}
public FilePath? NugetConfig { get; }
@@ -28,7 +31,7 @@ public PackageSourceLocation(
public string[] SourceFeedOverrides { get; private set; }
public string[] AdditionalSourceFeed { get; private set; }
- private static string[] ExpandLocalFeed(string[] sourceFeedOverrides)
+ private static string[] ExpandLocalFeed(string[] sourceFeedOverrides, string basePath)
{
if (sourceFeedOverrides != null)
{
@@ -38,7 +41,7 @@ private static string[] ExpandLocalFeed(string[] sourceFeedOverrides)
string feed = sourceFeedOverrides[index];
if (!Uri.IsWellFormedUriString(feed, UriKind.Absolute) && !Path.IsPathRooted(feed))
{
- localFeedsThatIsRooted[index] = Path.GetFullPath(feed);
+ localFeedsThatIsRooted[index] = Path.GetFullPath(feed, basePath);
}
else
{
diff --git a/src/Cli/dotnet/ShellShim/IShellShimRepository.cs b/src/Cli/dotnet/ShellShim/IShellShimRepository.cs
index 68db0c04a879..9d8c41545e5e 100644
--- a/src/Cli/dotnet/ShellShim/IShellShimRepository.cs
+++ b/src/Cli/dotnet/ShellShim/IShellShimRepository.cs
@@ -3,6 +3,7 @@
#nullable disable
+using Microsoft.DotNet.Cli.ToolPackage;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.Extensions.EnvironmentAbstractions;
@@ -10,7 +11,7 @@ namespace Microsoft.DotNet.Cli.ShellShim;
internal interface IShellShimRepository
{
- void CreateShim(FilePath targetExecutablePath, ToolCommandName commandName, IReadOnlyList packagedShims = null);
+ void CreateShim(ToolCommand toolCommand, IReadOnlyList packagedShims = null);
- void RemoveShim(ToolCommandName commandName);
+ void RemoveShim(ToolCommand toolCommand);
}
diff --git a/src/Cli/dotnet/ShellShim/ShellShimRepository.cs b/src/Cli/dotnet/ShellShim/ShellShimRepository.cs
index 51b0fb60d56b..cdc1b8ed8b31 100644
--- a/src/Cli/dotnet/ShellShim/ShellShimRepository.cs
+++ b/src/Cli/dotnet/ShellShim/ShellShimRepository.cs
@@ -3,6 +3,7 @@
#nullable disable
+using Microsoft.DotNet.Cli.ToolPackage;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.Extensions.EnvironmentAbstractions;
@@ -20,19 +21,19 @@ internal class ShellShimRepository(
private readonly IAppHostShellShimMaker _appHostShellShimMaker = appHostShellShimMaker ?? new AppHostShellShimMaker(appHostSourceDirectory: appHostSourceDirectory);
private readonly IFilePermissionSetter _filePermissionSetter = filePermissionSetter ?? new FilePermissionSetter();
- public void CreateShim(FilePath targetExecutablePath, ToolCommandName commandName, IReadOnlyList packagedShims = null)
+ public void CreateShim(ToolCommand toolCommand, IReadOnlyList packagedShims = null)
{
- if (string.IsNullOrEmpty(targetExecutablePath.Value))
+ if (string.IsNullOrEmpty(toolCommand.Executable.Value))
{
throw new ShellShimException(CliStrings.CannotCreateShimForEmptyExecutablePath);
}
- if (ShimExists(commandName))
+ if (ShimExists(toolCommand))
{
throw new ShellShimException(
string.Format(
CliStrings.ShellShimConflict,
- commandName));
+ toolCommand.Name));
}
TransactionalAction.Run(
@@ -45,16 +46,46 @@ public void CreateShim(FilePath targetExecutablePath, ToolCommandName commandNam
_fileSystem.Directory.CreateDirectory(_shimsDirectory.Value);
}
- if (TryGetPackagedShim(packagedShims, commandName, out FilePath? packagedShim))
+ if (toolCommand.Runner == "dotnet")
{
- _fileSystem.File.Copy(packagedShim.Value.Value, GetShimPath(commandName).Value);
- _filePermissionSetter.SetUserExecutionPermission(GetShimPath(commandName).Value);
+ if (TryGetPackagedShim(packagedShims, toolCommand, out FilePath? packagedShim))
+ {
+ _fileSystem.File.Copy(packagedShim.Value.Value, GetShimPath(toolCommand).Value);
+ _filePermissionSetter.SetUserExecutionPermission(GetShimPath(toolCommand).Value);
+ }
+ else
+ {
+ _appHostShellShimMaker.CreateApphostShellShim(
+ toolCommand.Executable,
+ GetShimPath(toolCommand));
+ }
+ }
+ else if (toolCommand.Runner == "executable")
+ {
+ var shimPath = GetShimPath(toolCommand).Value;
+ string relativePathToExe = Path.GetRelativePath(_shimsDirectory.Value, toolCommand.Executable.Value);
+
+ if (OperatingSystem.IsWindows())
+ {
+ // Generate a batch / .cmd file to call the executable inside the package, and forward all arguments to it.
+ // %~dp0 expands to the directory of the batch file, so this will work regardless of the current working directory.
+ // %* forwards all arguments passed to the batch file to the executable.
+ string batchContent = $"@echo off\r\n\"%~dp0{relativePathToExe}\" %*\r\n";
+ File.WriteAllText(shimPath, batchContent);
+ }
+ else
+ {
+ File.CreateSymbolicLink(shimPath, relativePathToExe);
+ _filePermissionSetter.SetUserExecutionPermission(shimPath);
+ }
}
else
{
- _appHostShellShimMaker.CreateApphostShellShim(
- targetExecutablePath,
- GetShimPath(commandName));
+ throw new ToolConfigurationException(
+ string.Format(
+ CliStrings.ToolSettingsUnsupportedRunner,
+ toolCommand.Name,
+ toolCommand.Runner));
}
}
catch (FilePermissionSettingException ex)
@@ -67,7 +98,7 @@ public void CreateShim(FilePath targetExecutablePath, ToolCommandName commandNam
throw new ShellShimException(
string.Format(
CliStrings.FailedToCreateShellShim,
- commandName,
+ toolCommand.Name,
ex.Message
),
ex);
@@ -75,14 +106,14 @@ public void CreateShim(FilePath targetExecutablePath, ToolCommandName commandNam
},
rollback: () =>
{
- foreach (var file in GetShimFiles(commandName).Where(f => _fileSystem.File.Exists(f.Value)))
+ foreach (var file in GetShimFiles(toolCommand).Where(f => _fileSystem.File.Exists(f.Value)))
{
File.Delete(file.Value);
}
});
}
- public void RemoveShim(ToolCommandName commandName)
+ public void RemoveShim(ToolCommand toolCommand)
{
var files = new Dictionary();
TransactionalAction.Run(
@@ -90,7 +121,7 @@ public void RemoveShim(ToolCommandName commandName)
{
try
{
- foreach (var file in GetShimFiles(commandName).Where(f => _fileSystem.File.Exists(f.Value)))
+ foreach (var file in GetShimFiles(toolCommand).Where(f => _fileSystem.File.Exists(f.Value)))
{
var tempPath = Path.Combine(_fileSystem.Directory.CreateTemporarySubdirectory(), Path.GetRandomFileName());
FileAccessRetrier.RetryOnMoveAccessFailure(() => _fileSystem.File.Move(file.Value, tempPath));
@@ -102,7 +133,7 @@ public void RemoveShim(ToolCommandName commandName)
throw new ShellShimException(
string.Format(
CliStrings.FailedToRemoveShellShim,
- commandName.ToString(),
+ toolCommand.Name.ToString(),
ex.Message
),
ex);
@@ -134,38 +165,45 @@ private class RootObject
public StartupOptions startupOptions { get; set; }
}
- private bool ShimExists(ToolCommandName commandName)
+ private bool ShimExists(ToolCommand toolCommand)
{
- return GetShimFiles(commandName).Any(p => _fileSystem.File.Exists(p.Value));
+ return GetShimFiles(toolCommand).Any(p => _fileSystem.File.Exists(p.Value));
}
- private IEnumerable GetShimFiles(ToolCommandName commandName)
+ private IEnumerable GetShimFiles(ToolCommand toolCommand)
{
- yield return GetShimPath(commandName);
+ yield return GetShimPath(toolCommand);
}
- private FilePath GetShimPath(ToolCommandName commandName)
+ private FilePath GetShimPath(ToolCommand toolCommand)
{
if (OperatingSystem.IsWindows())
{
- return _shimsDirectory.WithFile(commandName.Value + ".exe");
+ if (toolCommand.Runner == "dotnet")
+ {
+ return _shimsDirectory.WithFile(toolCommand.Name.Value + ".exe");
+ }
+ else
+ {
+ return _shimsDirectory.WithFile(toolCommand.Name.Value + ".cmd");
+ }
}
else
{
- return _shimsDirectory.WithFile(commandName.Value);
+ return _shimsDirectory.WithFile(toolCommand.Name.Value);
}
}
private bool TryGetPackagedShim(
IReadOnlyList packagedShims,
- ToolCommandName commandName,
+ ToolCommand toolCommand,
out FilePath? packagedShim)
{
packagedShim = null;
if (packagedShims != null && packagedShims.Count > 0)
{
- FilePath[] candidatepackagedShim = [.. packagedShims.Where(s => string.Equals(Path.GetFileName(s.Value), Path.GetFileName(GetShimPath(commandName).Value)))];
+ FilePath[] candidatepackagedShim = [.. packagedShims.Where(s => string.Equals(Path.GetFileName(s.Value), Path.GetFileName(GetShimPath(toolCommand).Value)))];
if (candidatepackagedShim.Length > 1)
{
diff --git a/src/Cli/dotnet/ToolPackage/ILocalToolsResolverCache.cs b/src/Cli/dotnet/ToolPackage/ILocalToolsResolverCache.cs
index 4ad7ad3bc2af..c2207f6c81b9 100644
--- a/src/Cli/dotnet/ToolPackage/ILocalToolsResolverCache.cs
+++ b/src/Cli/dotnet/ToolPackage/ILocalToolsResolverCache.cs
@@ -8,13 +8,9 @@ namespace Microsoft.DotNet.Cli.ToolPackage;
internal interface ILocalToolsResolverCache
{
void Save(
- IDictionary restoredCommandMap);
+ IDictionary restoredCommandMap);
bool TryLoad(
RestoredCommandIdentifier restoredCommandIdentifier,
- out RestoredCommand restoredCommand);
-
- bool TryLoadHighestVersion(
- RestoredCommandIdentifierVersionRange query,
- out RestoredCommand restoredCommandList);
+ out ToolCommand toolCommand);
}
diff --git a/src/Cli/dotnet/ToolPackage/IToolPackage.cs b/src/Cli/dotnet/ToolPackage/IToolPackage.cs
index bc6606377c3e..2efd933658cb 100644
--- a/src/Cli/dotnet/ToolPackage/IToolPackage.cs
+++ b/src/Cli/dotnet/ToolPackage/IToolPackage.cs
@@ -15,9 +15,13 @@ internal interface IToolPackage
NuGetVersion Version { get; }
+ public PackageId ResolvedPackageId { get; }
+
+ public NuGetVersion ResolvedPackageVersion { get; }
+
DirectoryPath PackageDirectory { get; }
- RestoredCommand Command { get; }
+ ToolCommand Command { get; }
IEnumerable Warnings { get; }
diff --git a/src/Cli/dotnet/ToolPackage/LocalToolsResolverCache.cs b/src/Cli/dotnet/ToolPackage/LocalToolsResolverCache.cs
index 3e1919d03c87..1fec1d02c237 100644
--- a/src/Cli/dotnet/ToolPackage/LocalToolsResolverCache.cs
+++ b/src/Cli/dotnet/ToolPackage/LocalToolsResolverCache.cs
@@ -29,7 +29,7 @@ public LocalToolsResolverCache(IFileSystem fileSystem = null,
}
public void Save(
- IDictionary restoredCommandMap)
+ IDictionary restoredCommandMap)
{
EnsureFileStorageExists();
@@ -69,7 +69,7 @@ public void Save(
public bool TryLoad(
RestoredCommandIdentifier restoredCommandIdentifier,
- out RestoredCommand restoredCommand)
+ out ToolCommand toolCommand)
{
string packageCacheFile = GetCacheFile(restoredCommandIdentifier.PackageId);
if (_fileSystem.File.Exists(packageCacheFile))
@@ -77,13 +77,13 @@ public bool TryLoad(
if (TryGetMatchingRestoredCommand(
restoredCommandIdentifier,
GetCacheTable(packageCacheFile),
- out restoredCommand))
+ out toolCommand))
{
return true;
}
}
- restoredCommand = null;
+ toolCommand = null;
return false;
}
@@ -104,34 +104,6 @@ private CacheRow[] GetCacheTable(string packageCacheFile)
return cacheTable;
}
- public bool TryLoadHighestVersion(
- RestoredCommandIdentifierVersionRange query,
- out RestoredCommand restoredCommandList)
- {
- restoredCommandList = null;
- string packageCacheFile = GetCacheFile(query.PackageId);
- if (_fileSystem.File.Exists(packageCacheFile))
- {
- var list = GetCacheTable(packageCacheFile)
- .Select(c => Convert(query.PackageId, c))
- .Where(strongTypeStored =>
- query.VersionRange.Satisfies(strongTypeStored.restoredCommandIdentifier.Version))
- .Where(onlyVersionSatisfies =>
- onlyVersionSatisfies.restoredCommandIdentifier ==
- query.WithVersion(onlyVersionSatisfies.restoredCommandIdentifier.Version))
- .OrderByDescending(allMatched => allMatched.restoredCommandIdentifier.Version)
- .FirstOrDefault();
-
- if (!list.restoredCommand.Equals(default(RestoredCommand)))
- {
- restoredCommandList = list.restoredCommand;
- return true;
- }
- }
-
- return false;
- }
-
private string GetCacheFile(PackageId packageId)
{
return _cacheVersionedDirectory.WithFile(packageId.ToString()).Value;
@@ -144,7 +116,7 @@ private void EnsureFileStorageExists()
private static CacheRow ConvertToCacheRow(
RestoredCommandIdentifier restoredCommandIdentifier,
- RestoredCommand restoredCommandList)
+ ToolCommand toolCommand)
{
return new CacheRow
{
@@ -152,14 +124,14 @@ private static CacheRow ConvertToCacheRow(
TargetFramework = restoredCommandIdentifier.TargetFramework.GetShortFolderName(),
RuntimeIdentifier = restoredCommandIdentifier.RuntimeIdentifier.ToLowerInvariant(),
Name = restoredCommandIdentifier.CommandName.Value,
- Runner = restoredCommandList.Runner,
- PathToExecutable = restoredCommandList.Executable.Value
+ Runner = toolCommand.Runner,
+ PathToExecutable = toolCommand.Executable.Value
};
}
private static
(RestoredCommandIdentifier restoredCommandIdentifier,
- RestoredCommand restoredCommand)
+ ToolCommand toolCommand)
Convert(
PackageId packageId,
CacheRow cacheRow)
@@ -172,21 +144,21 @@ private static
cacheRow.RuntimeIdentifier,
new ToolCommandName(cacheRow.Name));
- RestoredCommand restoredCommand =
+ ToolCommand toolCommand =
new(
new ToolCommandName(cacheRow.Name),
cacheRow.Runner,
new FilePath(cacheRow.PathToExecutable));
- return (restoredCommandIdentifier, restoredCommand);
+ return (restoredCommandIdentifier, toolCommand);
}
private static bool TryGetMatchingRestoredCommand(
RestoredCommandIdentifier restoredCommandIdentifier,
CacheRow[] cacheTable,
- out RestoredCommand restoredCommandList)
+ out ToolCommand toolCommandList)
{
- (RestoredCommandIdentifier restoredCommandIdentifier, RestoredCommand restoredCommand)[] matchingRow =
+ (RestoredCommandIdentifier restoredCommandIdentifier, ToolCommand toolCommand)[] matchingRow =
[.. cacheTable
.Select(c => Convert(restoredCommandIdentifier.PackageId, c))
.Where(candidate => candidate.restoredCommandIdentifier == restoredCommandIdentifier)];
@@ -199,11 +171,11 @@ [.. cacheTable
if (matchingRow.Length == 1)
{
- restoredCommandList = matchingRow[0].restoredCommand;
+ toolCommandList = matchingRow[0].toolCommand;
return true;
}
- restoredCommandList = null;
+ toolCommandList = null;
return false;
}
diff --git a/src/Cli/dotnet/ToolPackage/RestoredCommandIdentifierVersionRange.cs b/src/Cli/dotnet/ToolPackage/RestoredCommandIdentifierVersionRange.cs
deleted file mode 100644
index f6ab17803306..000000000000
--- a/src/Cli/dotnet/ToolPackage/RestoredCommandIdentifierVersionRange.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-#nullable disable
-
-using Microsoft.DotNet.Cli.Utils;
-using NuGet.Frameworks;
-using NuGet.Versioning;
-
-namespace Microsoft.DotNet.Cli.ToolPackage;
-
-///
-/// A range of RestoredCommandIdentifier that is only different in the Version field.
-///
-internal class RestoredCommandIdentifierVersionRange(
- PackageId packageId,
- VersionRange versionRange,
- NuGetFramework targetFramework,
- string runtimeIdentifier,
- ToolCommandName commandName)
-{
- public PackageId PackageId { get; } = packageId;
- public VersionRange VersionRange { get; } = versionRange ?? throw new ArgumentException(nameof(versionRange));
- public NuGetFramework TargetFramework { get; } = targetFramework ?? throw new ArgumentException(nameof(targetFramework));
- public string RuntimeIdentifier { get; } = runtimeIdentifier ?? throw new ArgumentException(nameof(runtimeIdentifier));
- public ToolCommandName CommandName { get; } = commandName;
-
- public RestoredCommandIdentifier WithVersion(NuGetVersion version)
- {
- return new RestoredCommandIdentifier(PackageId, version, TargetFramework, RuntimeIdentifier, CommandName);
- }
-}
diff --git a/src/Cli/dotnet/ToolPackage/RestoredCommand.cs b/src/Cli/dotnet/ToolPackage/ToolCommand.cs
similarity index 95%
rename from src/Cli/dotnet/ToolPackage/RestoredCommand.cs
rename to src/Cli/dotnet/ToolPackage/ToolCommand.cs
index 319d0b6c2e7b..2e00f57d5743 100644
--- a/src/Cli/dotnet/ToolPackage/RestoredCommand.cs
+++ b/src/Cli/dotnet/ToolPackage/ToolCommand.cs
@@ -8,7 +8,7 @@
namespace Microsoft.DotNet.Cli.ToolPackage;
-internal class RestoredCommand(
+internal class ToolCommand(
ToolCommandName name,
string runner,
FilePath executable)
diff --git a/src/Cli/dotnet/ToolPackage/ToolConfiguration.cs b/src/Cli/dotnet/ToolPackage/ToolConfiguration.cs
index d903868bae1b..641c8c583a7c 100644
--- a/src/Cli/dotnet/ToolPackage/ToolConfiguration.cs
+++ b/src/Cli/dotnet/ToolPackage/ToolConfiguration.cs
@@ -1,7 +1,8 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-#nullable disable
+
+using NuGet.Packaging.Core;
namespace Microsoft.DotNet.Cli.ToolPackage;
@@ -10,14 +11,16 @@ internal class ToolConfiguration
public ToolConfiguration(
string commandName,
string toolAssemblyEntryPoint,
- IEnumerable warnings = null)
+ string runner,
+ IDictionary? ridSpecificPackages = null,
+ IEnumerable? warnings = null)
{
if (string.IsNullOrWhiteSpace(commandName))
{
throw new ToolConfigurationException(CliStrings.ToolSettingsMissingCommandName);
}
- if (string.IsNullOrWhiteSpace(toolAssemblyEntryPoint))
+ if (string.IsNullOrWhiteSpace(toolAssemblyEntryPoint) && ridSpecificPackages?.Any() != true)
{
throw new ToolConfigurationException(
string.Format(
@@ -30,6 +33,8 @@ public ToolConfiguration(
CommandName = commandName;
ToolAssemblyEntryPoint = toolAssemblyEntryPoint;
+ Runner = runner;
+ RidSpecificPackages = ridSpecificPackages;
Warnings = warnings ?? [];
}
@@ -57,7 +62,13 @@ private static void EnsureNoLeadingDot(string commandName)
}
}
+
+
public string CommandName { get; }
public string ToolAssemblyEntryPoint { get; }
+ public string Runner { get; }
+
+ public IDictionary? RidSpecificPackages { get; }
+
public IEnumerable Warnings { get; }
}
diff --git a/src/Cli/dotnet/ToolPackage/ToolConfigurationDeserialization/DotNetCliTool.cs b/src/Cli/dotnet/ToolPackage/ToolConfigurationDeserialization/DotNetCliTool.cs
index e67807f9485c..1bd39e46c03b 100644
--- a/src/Cli/dotnet/ToolPackage/ToolConfigurationDeserialization/DotNetCliTool.cs
+++ b/src/Cli/dotnet/ToolPackage/ToolConfigurationDeserialization/DotNetCliTool.cs
@@ -15,6 +15,9 @@ public class DotNetCliTool
[XmlArrayItem("Command", IsNullable = false)]
public DotNetCliToolCommand[] Commands { get; set; }
+ [XmlArrayItem("RuntimeIdentifierPackage", IsNullable = false)]
+ public DotNetCliToolRuntimeIdentifierPackage[] RuntimeIdentifierPackages { get; set; }
+
[XmlAttribute(AttributeName = "Version")]
public string Version { get; set; }
}
diff --git a/src/Cli/dotnet/ToolPackage/ToolConfigurationDeserialization/DotNetCliToolRuntimeIdentifierPackage.cs b/src/Cli/dotnet/ToolPackage/ToolConfigurationDeserialization/DotNetCliToolRuntimeIdentifierPackage.cs
new file mode 100644
index 000000000000..aea13c17260d
--- /dev/null
+++ b/src/Cli/dotnet/ToolPackage/ToolConfigurationDeserialization/DotNetCliToolRuntimeIdentifierPackage.cs
@@ -0,0 +1,22 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Diagnostics;
+using System.Xml.Serialization;
+
+namespace Microsoft.DotNet.Cli.ToolPackage.ToolConfigurationDeserialization;
+
+[Serializable]
+[DebuggerStepThrough]
+[XmlType(AnonymousType = true)]
+public class DotNetCliToolRuntimeIdentifierPackage
+{
+ [XmlAttribute]
+ public string? RuntimeIdentifier { get; set; }
+
+ [XmlAttribute]
+ public string? Id { get; set; }
+
+ [XmlAttribute]
+ public string? Version { get; set; }
+}
diff --git a/src/Cli/dotnet/ToolPackage/ToolConfigurationDeserializer.cs b/src/Cli/dotnet/ToolPackage/ToolConfigurationDeserializer.cs
index ac29602f963a..29f731c60bff 100644
--- a/src/Cli/dotnet/ToolPackage/ToolConfigurationDeserializer.cs
+++ b/src/Cli/dotnet/ToolPackage/ToolConfigurationDeserializer.cs
@@ -6,6 +6,8 @@
using System.Xml;
using System.Xml.Serialization;
using Microsoft.DotNet.Cli.ToolPackage.ToolConfigurationDeserialization;
+using Microsoft.Extensions.EnvironmentAbstractions;
+using NuGet.Packaging.Core;
namespace Microsoft.DotNet.Cli.ToolPackage;
@@ -13,19 +15,21 @@ internal static class ToolConfigurationDeserializer
{
// The supported tool configuration schema version.
// This should match the schema version in the GenerateToolsSettingsFile task from the SDK.
- private const int SupportedVersion = 1;
+ private const int SupportedVersion = 2;
- public static ToolConfiguration Deserialize(string pathToXml)
+ public static ToolConfiguration Deserialize(string pathToXml, IFileSystem fileSystem = null)
{
+ fileSystem ??= new FileSystemWrapper();
+
var serializer = new XmlSerializer(typeof(DotNetCliTool));
DotNetCliTool dotNetCliTool;
try
{
- using (var fs = File.OpenRead(pathToXml))
+ using (var stream = fileSystem.File.OpenRead(pathToXml))
{
- var reader = XmlReader.Create(fs);
+ var reader = XmlReader.Create(stream);
dotNetCliTool = (DotNetCliTool)serializer.Deserialize(reader);
}
}
@@ -53,7 +57,21 @@ public static ToolConfiguration Deserialize(string pathToXml)
throw new ToolConfigurationException(CliStrings.ToolSettingsMoreThanOneCommand);
}
- if (dotNetCliTool.Commands[0].Runner != "dotnet")
+ var runner = dotNetCliTool.Commands[0].Runner;
+ if (!string.IsNullOrEmpty(runner) && runner != "dotnet" && runner != "executable")
+ {
+ throw new ToolConfigurationException(
+ string.Format(
+ CliStrings.ToolSettingsUnsupportedRunner,
+ dotNetCliTool.Commands[0].Name,
+ dotNetCliTool.Commands[0].Runner));
+ }
+
+ var ridSpecificPackages = dotNetCliTool.RuntimeIdentifierPackages?.ToDictionary(p => p.RuntimeIdentifier, p => new PackageIdentity(p.Id, new NuGet.Versioning.NuGetVersion(p.Version)))
+ .AsReadOnly();
+
+ // Also error out if there are no RID-specific packages and the runner is empty
+ if (string.IsNullOrEmpty(runner) && !ridSpecificPackages.Any())
{
throw new ToolConfigurationException(
string.Format(
@@ -65,7 +83,9 @@ public static ToolConfiguration Deserialize(string pathToXml)
return new ToolConfiguration(
dotNetCliTool.Commands[0].Name,
dotNetCliTool.Commands[0].EntryPoint,
- warnings);
+ dotNetCliTool.Commands[0].Runner,
+ ridSpecificPackages: ridSpecificPackages,
+ warnings: warnings);
}
private static List GenerateWarningAccordingToVersionAttribute(DotNetCliTool dotNetCliTool)
diff --git a/src/Cli/dotnet/ToolPackage/ToolPackageDownloader.cs b/src/Cli/dotnet/ToolPackage/ToolPackageDownloader.cs
index 0b50a69f48d1..31b4b528af35 100644
--- a/src/Cli/dotnet/ToolPackage/ToolPackageDownloader.cs
+++ b/src/Cli/dotnet/ToolPackage/ToolPackageDownloader.cs
@@ -11,6 +11,7 @@
using Microsoft.TemplateEngine.Utils;
using Newtonsoft.Json.Linq;
using NuGet.Client;
+using NuGet.Commands;
using NuGet.Common;
using NuGet.Configuration;
using NuGet.ContentModel;
@@ -25,296 +26,105 @@
namespace Microsoft.DotNet.Cli.ToolPackage;
-internal class ToolPackageDownloader : IToolPackageDownloader
+internal class ToolPackageDownloader : ToolPackageDownloaderBase
{
- private readonly IToolPackageStore _toolPackageStore;
-
- // The directory that the tool package is returned
- protected DirectoryPath _toolReturnPackageDirectory;
-
- // The directory that the tool asset file is returned
- protected DirectoryPath _toolReturnJsonParentDirectory;
-
- // The directory that global tools first downloaded
- // example: C:\Users\username\.dotnet\tools\.store\.stage\tempFolder
- protected readonly DirectoryPath _globalToolStageDir;
-
- // The directory that local tools first downloaded
- // example: C:\Users\username\.nuget\package
- protected readonly DirectoryPath _localToolDownloadDir;
-
- // The directory that local tools' asset files located
- // example: C:\Users\username\AppData\Local\Temp\tempFolder
- protected readonly DirectoryPath _localToolAssetDir;
-
- protected readonly string _runtimeJsonPath;
-
- private readonly string _currentWorkingDirectory;
-
public ToolPackageDownloader(
IToolPackageStore store,
string runtimeJsonPathForTests = null,
string currentWorkingDirectory = null
- )
+ ) : base(store, runtimeJsonPathForTests, currentWorkingDirectory, FileSystemWrapper.Default)
+ {
+ }
+
+ protected override INuGetPackageDownloader CreateNuGetPackageDownloader(
+ bool verifySignatures,
+ VerbosityOptions verbosity,
+ RestoreActionConfig restoreActionConfig)
{
- _toolPackageStore = store ?? throw new ArgumentNullException(nameof(store));
- _globalToolStageDir = _toolPackageStore.GetRandomStagingDirectory();
- ISettings settings = Settings.LoadDefaultSettings(currentWorkingDirectory ?? Directory.GetCurrentDirectory());
- _localToolDownloadDir = new DirectoryPath(SettingsUtility.GetGlobalPackagesFolder(settings));
- _currentWorkingDirectory = currentWorkingDirectory;
+ ILogger verboseLogger = new NullLogger();
+ if (verbosity.IsDetailedOrDiagnostic())
+ {
+ verboseLogger = new NuGetConsoleLogger();
+ }
- _localToolAssetDir = new DirectoryPath(PathUtilities.CreateTempSubdirectory());
- _runtimeJsonPath = runtimeJsonPathForTests ?? Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "RuntimeIdentifierGraph.json");
+ return new NuGetPackageDownloader.NuGetPackageDownloader(
+ new DirectoryPath(),
+ verboseLogger: verboseLogger,
+ verifySignatures: verifySignatures,
+ shouldUsePackageSourceMapping: true,
+ restoreActionConfig: restoreActionConfig,
+ verbosityOptions: verbosity,
+ currentWorkingDirectory: _currentWorkingDirectory);
}
- public IToolPackage InstallPackage(PackageLocation packageLocation, PackageId packageId,
- VerbosityOptions verbosity = VerbosityOptions.normal,
- VersionRange versionRange = null,
- string targetFramework = null,
- bool isGlobalTool = false,
- bool isGlobalToolRollForward = false,
- bool verifySignatures = true,
- RestoreActionConfig restoreActionConfig = null
+ protected override NuGetVersion DownloadAndExtractPackage(
+ PackageId packageId,
+ INuGetPackageDownloader nugetPackageDownloader,
+ string packagesRootPath,
+ NuGetVersion packageVersion,
+ PackageSourceLocation packageSourceLocation,
+ bool includeUnlisted = false
)
{
- var packageRootDirectory = _toolPackageStore.GetRootPackageDirectory(packageId);
- string rollbackDirectory = null;
-
- return TransactionalAction.Run(
- action: () =>
- {
- ILogger nugetLogger = new NullLogger();
- if (verbosity.IsDetailedOrDiagnostic())
- {
- nugetLogger = new NuGetConsoleLogger();
- }
-
- if (versionRange == null)
- {
- var versionString = "*";
- versionRange = VersionRange.Parse(versionString);
- }
-
- var toolDownloadDir = isGlobalTool ? _globalToolStageDir : _localToolDownloadDir;
- var assetFileDirectory = isGlobalTool ? _globalToolStageDir : _localToolAssetDir;
-
- var nugetPackageDownloader = new NuGetPackageDownloader.NuGetPackageDownloader(
- toolDownloadDir,
- verboseLogger: nugetLogger,
- verifySignatures: verifySignatures,
- shouldUsePackageSourceMapping: true,
- restoreActionConfig: restoreActionConfig,
- verbosityOptions: verbosity,
- currentWorkingDirectory: _currentWorkingDirectory);
+ var versionFolderPathResolver = new VersionFolderPathResolver(packagesRootPath);
- var packageSourceLocation = new PackageSourceLocation(packageLocation.NugetConfig, packageLocation.RootConfigDirectory, packageLocation.SourceFeedOverrides, packageLocation.AdditionalFeeds);
-
- bool givenSpecificVersion = false;
- if (versionRange.MinVersion != null && versionRange.MaxVersion != null && versionRange.MinVersion == versionRange.MaxVersion)
- {
- givenSpecificVersion = true;
- }
- NuGetVersion packageVersion = nugetPackageDownloader.GetBestPackageVersionAsync(packageId, versionRange, packageSourceLocation).GetAwaiter().GetResult();
-
- rollbackDirectory = isGlobalTool ? toolDownloadDir.Value: new VersionFolderPathResolver(toolDownloadDir.Value).GetInstallPath(packageId.ToString(), packageVersion);
-
- if (isGlobalTool)
- {
- NuGetv3LocalRepository nugetPackageRootDirectory = new(new VersionFolderPathResolver(_toolPackageStore.Root.Value).GetInstallPath(packageId.ToString(), packageVersion));
- var globalPackage = nugetPackageRootDirectory.FindPackage(packageId.ToString(), packageVersion);
-
- if (globalPackage != null)
- {
- throw new ToolPackageException(
- string.Format(
- CliStrings.ToolPackageConflictPackageId,
- packageId,
- packageVersion.ToNormalizedString()));
- }
- }
- NuGetv3LocalRepository localRepository = new(toolDownloadDir.Value);
- var package = localRepository.FindPackage(packageId.ToString(), packageVersion);
-
- if (package == null)
- {
- DownloadAndExtractPackage(packageId, nugetPackageDownloader, toolDownloadDir.Value, packageVersion, packageSourceLocation, includeUnlisted: givenSpecificVersion).GetAwaiter().GetResult();
- }
- else if(isGlobalTool)
- {
- throw new ToolPackageException(
- string.Format(
- CliStrings.ToolPackageConflictPackageId,
- packageId,
- packageVersion.ToNormalizedString()));
- }
-
- CreateAssetFile(packageId, packageVersion, toolDownloadDir, assetFileDirectory, _runtimeJsonPath, targetFramework);
-
- DirectoryPath toolReturnPackageDirectory;
- DirectoryPath toolReturnJsonParentDirectory;
-
- if (isGlobalTool)
- {
- toolReturnPackageDirectory = _toolPackageStore.GetPackageDirectory(packageId, packageVersion);
- toolReturnJsonParentDirectory = _toolPackageStore.GetPackageDirectory(packageId, packageVersion);
- var packageRootDirectory = _toolPackageStore.GetRootPackageDirectory(packageId);
- Directory.CreateDirectory(packageRootDirectory.Value);
- FileAccessRetrier.RetryOnMoveAccessFailure(() => Directory.Move(_globalToolStageDir.Value, toolReturnPackageDirectory.Value));
- rollbackDirectory = toolReturnPackageDirectory.Value;
- }
- else
- {
- toolReturnPackageDirectory = toolDownloadDir;
- toolReturnJsonParentDirectory = _localToolAssetDir;
- }
+ string folderToDeleteOnFailure = null;
+ return TransactionalAction.Run(() =>
+ {
+ var packagePath = nugetPackageDownloader.DownloadPackageAsync(packageId, packageVersion, packageSourceLocation,
+ includeUnlisted: includeUnlisted, downloadFolder: new DirectoryPath(packagesRootPath)).ConfigureAwait(false).GetAwaiter().GetResult();
- var toolPackageInstance = new ToolPackageInstance(id: packageId,
- version: packageVersion,
- packageDirectory: toolReturnPackageDirectory,
- assetsJsonParentDirectory: toolReturnJsonParentDirectory);
+ folderToDeleteOnFailure = Path.GetDirectoryName(packagePath);
- if (isGlobalToolRollForward)
- {
- UpdateRuntimeConfig(toolPackageInstance);
- }
+ // look for package on disk and read the version
+ NuGetVersion version;
- return toolPackageInstance;
- },
- rollback: () =>
+ using (FileStream packageStream = File.OpenRead(packagePath))
{
- if (rollbackDirectory != null && Directory.Exists(rollbackDirectory))
- {
- Directory.Delete(rollbackDirectory, true);
- }
- // Delete the root if it is empty
- if (Directory.Exists(packageRootDirectory.Value) &&
- !Directory.EnumerateFileSystemEntries(packageRootDirectory.Value).Any())
- {
- Directory.Delete(packageRootDirectory.Value, false);
- }
- });
- }
+ PackageArchiveReader reader = new(packageStream);
+ version = new NuspecReader(reader.GetNuspec()).GetVersion();
- // The following methods are copied from the LockFileUtils class in Nuget.Client
- private static void AddToolsAssets(
- ManagedCodeConventions managedCodeConventions,
- LockFileTargetLibrary lockFileLib,
- ContentItemCollection contentItems,
- IReadOnlyList orderedCriteria)
- {
- var toolsGroup = GetLockFileItems(
- orderedCriteria,
- contentItems,
- managedCodeConventions.Patterns.ToolsAssemblies);
+ var packageHash = Convert.ToBase64String(new CryptoHashProvider("SHA512").CalculateHash(reader.GetNuspec()));
+ var hashPath = versionFolderPathResolver.GetHashPath(packageId.ToString(), version);
- lockFileLib.ToolsAssemblies.AddRange(toolsGroup);
- }
+ Directory.CreateDirectory(Path.GetDirectoryName(hashPath));
+ File.WriteAllText(hashPath, packageHash);
+ }
- private static void UpdateRuntimeConfig(
- ToolPackageInstance toolPackageInstance
- )
- {
- var runtimeConfigFilePath = Path.ChangeExtension(toolPackageInstance.Command.Executable.Value, ".runtimeconfig.json");
+ // Extract the package
+ var nupkgDir = versionFolderPathResolver.GetInstallPath(packageId.ToString(), version);
+ nugetPackageDownloader.ExtractPackageAsync(packagePath, new DirectoryPath(nupkgDir)).ConfigureAwait(false).GetAwaiter().GetResult();
- // Update the runtimeconfig.json file
- if (File.Exists(runtimeConfigFilePath))
+ return version;
+ }, rollback: () =>
{
- string existingJson = File.ReadAllText(runtimeConfigFilePath);
-
- var jsonObject = JObject.Parse(existingJson);
- if (jsonObject["runtimeOptions"] is JObject runtimeOptions)
+ // If something fails, don't leave a folder with partial contents (such as a .nupkg but no hash or extracted contents)
+ if (folderToDeleteOnFailure != null && Directory.Exists(folderToDeleteOnFailure))
{
- runtimeOptions["rollForward"] = "Major";
- string updateJson = jsonObject.ToString();
- File.WriteAllText(runtimeConfigFilePath, updateJson);
+ Directory.Delete(folderToDeleteOnFailure, true);
}
- }
+ });
}
- private static IEnumerable GetLockFileItems(
- IReadOnlyList criteria,
- ContentItemCollection items,
- params PatternSet[] patterns)
- {
- return GetLockFileItems(criteria, items, additionalAction: null, patterns);
- }
-
- private static IEnumerable GetLockFileItems(
- IReadOnlyList criteria,
- ContentItemCollection items,
- Action additionalAction,
- params PatternSet[] patterns)
+ protected override bool IsPackageInstalled(PackageId packageId, NuGetVersion packageVersion, string packagesRootPath)
{
- // Loop through each criteria taking the first one that matches one or more items.
- foreach (var managedCriteria in criteria)
- {
- var group = items.FindBestItemGroup(
- managedCriteria,
- patterns);
-
- if (group != null)
- {
- foreach (var item in group.Items)
- {
- var newItem = new LockFileItem(item.Path);
- if (item.Properties.TryGetValue("locale", out var locale))
- {
- newItem.Properties["locale"] = (string)locale;
- }
+ NuGetv3LocalRepository nugetLocalRepository = new(packagesRootPath);
- if (item.Properties.TryGetValue("related", out var related))
- {
- newItem.Properties["related"] = (string)related;
- }
- additionalAction?.Invoke(newItem);
- yield return newItem;
- }
- // Take only the first group that has items
- break;
- }
- }
+ var package = nugetLocalRepository.FindPackage(packageId.ToString(), packageVersion);
- yield break;
+ return package != null;
}
- private static async Task DownloadAndExtractPackage(
- PackageId packageId,
- INuGetPackageDownloader nugetPackageDownloader,
- string packagesRootPath,
- NuGetVersion packageVersion,
- PackageSourceLocation packageSourceLocation,
- bool includeUnlisted = false
- )
+ protected override ToolConfiguration GetToolConfiguration(PackageId id, DirectoryPath packageDirectory, DirectoryPath assetsJsonParentDirectory)
{
- var packagePath = await nugetPackageDownloader.DownloadPackageAsync(packageId, packageVersion, packageSourceLocation, includeUnlisted: includeUnlisted).ConfigureAwait(false);
-
- // look for package on disk and read the version
- NuGetVersion version;
-
- using (FileStream packageStream = File.OpenRead(packagePath))
- {
- PackageArchiveReader reader = new(packageStream);
- version = new NuspecReader(reader.GetNuspec()).GetVersion();
-
- var packageHash = Convert.ToBase64String(new CryptoHashProvider("SHA512").CalculateHash(reader.GetNuspec()));
- var hashPath = new VersionFolderPathResolver(packagesRootPath).GetHashPath(packageId.ToString(), version);
-
- Directory.CreateDirectory(Path.GetDirectoryName(hashPath));
- File.WriteAllText(hashPath, packageHash);
- }
-
- // Extract the package
- var nupkgDir = new VersionFolderPathResolver(packagesRootPath).GetInstallPath(packageId.ToString(), version);
- await nugetPackageDownloader.ExtractPackageAsync(packagePath, new DirectoryPath(nupkgDir));
-
- return version;
+ return ToolPackageInstance.GetToolConfiguration(id, packageDirectory, assetsJsonParentDirectory, _fileSystem);
}
- private static void CreateAssetFile(
+ protected override void CreateAssetFile(
PackageId packageId,
NuGetVersion version,
DirectoryPath packagesRootPath,
- DirectoryPath assetFileDirectory,
+ string assetFilePath,
string runtimeJsonGraph,
string targetFramework = null
)
@@ -325,19 +135,26 @@ private static void CreateAssetFile(
// Create ManagedCodeConventions:
var conventions = new ManagedCodeConventions(runtimeGraph);
+ // Create NuGetv3LocalRepository
+ NuGetv3LocalRepository localRepository = new(packagesRootPath.Value);
+ var package = localRepository.FindPackage(packageId.ToString(), version);
+
+ if (!package.Nuspec.GetPackageTypes().Any(pt => pt.Name.Equals(PackageType.DotnetTool.Name, StringComparison.OrdinalIgnoreCase) ||
+ pt.Name.Equals("DotnetToolRidPackage", StringComparison.OrdinalIgnoreCase)))
+ {
+ throw new ToolPackageException(string.Format(CliStrings.ToolPackageNotATool, packageId));
+ }
+
// Create LockFileTargetLibrary
var lockFileLib = new LockFileTargetLibrary()
{
Name = packageId.ToString(),
Version = version,
Type = LibraryType.Package,
+ // Actual package type might be DotnetToolRidPackage but for asset file processing we treat them the same
PackageType = [PackageType.DotnetTool]
};
- // Create NuGetv3LocalRepository
- NuGetv3LocalRepository localRepository = new(packagesRootPath.Value);
- var package = localRepository.FindPackage(packageId.ToString(), version);
-
var collection = new ContentItemCollection();
collection.Load(package.Files);
@@ -345,9 +162,9 @@ private static void CreateAssetFile(
var managedCriteria = new List(1);
// Use major.minor version of currently running version of .NET
NuGetFramework currentTargetFramework;
- if(targetFramework != null)
+ if (targetFramework != null)
{
- currentTargetFramework = NuGetFramework.Parse(targetFramework);
+ currentTargetFramework = NuGetFramework.Parse(targetFramework);
}
else
{
@@ -360,6 +177,8 @@ private static void CreateAssetFile(
managedCriteria.Add(standardCriteria);
// Create asset file
+ // Note that we know that the package type for the lock file is DotnetTool because we just set it to that.
+ // This if statement is still here because this mirrors code in NuGet for restore so maybe it will be easier to keep in sync if need be
if (lockFileLib.PackageType.Contains(PackageType.DotnetTool))
{
AddToolsAssets(conventions, lockFileLib, collection, managedCriteria);
@@ -373,43 +192,68 @@ private static void CreateAssetFile(
};
lockFileTarget.Libraries.Add(lockFileLib);
lockFile.Targets.Add(lockFileTarget);
- new LockFileFormat().Write(Path.Combine(assetFileDirectory.Value, "project.assets.json"), lockFile);
+ new LockFileFormat().Write(assetFilePath, lockFile);
}
- public NuGetVersion GetNuGetVersion(
- PackageLocation packageLocation,
- PackageId packageId,
- VerbosityOptions verbosity,
- VersionRange versionRange = null,
- bool isGlobalTool = false,
- RestoreActionConfig restoreActionConfig = null)
+
+ // The following methods are copied from the LockFileUtils class in Nuget.Client
+ protected static void AddToolsAssets(
+ ManagedCodeConventions managedCodeConventions,
+ LockFileTargetLibrary lockFileLib,
+ ContentItemCollection contentItems,
+ IReadOnlyList orderedCriteria)
{
- ILogger nugetLogger = new NullLogger();
+ var toolsGroup = GetLockFileItems(
+ orderedCriteria,
+ contentItems,
+ managedCodeConventions.Patterns.ToolsAssemblies);
- if (verbosity.IsDetailedOrDiagnostic())
- {
- nugetLogger = new NuGetConsoleLogger();
- }
+ lockFileLib.ToolsAssemblies.AddRange(toolsGroup);
+ }
- if (versionRange == null)
+ protected static IEnumerable GetLockFileItems(
+ IReadOnlyList criteria,
+ ContentItemCollection items,
+ params PatternSet[] patterns)
+ {
+ return GetLockFileItems(criteria, items, additionalAction: null, patterns);
+ }
+
+ protected static IEnumerable GetLockFileItems(
+ IReadOnlyList criteria,
+ ContentItemCollection items,
+ Action additionalAction,
+ params PatternSet[] patterns)
+ {
+ // Loop through each criteria taking the first one that matches one or more items.
+ foreach (var managedCriteria in criteria)
{
- var versionString = "*";
- versionRange = VersionRange.Parse(versionString);
- }
+ var group = items.FindBestItemGroup(
+ managedCriteria,
+ patterns);
- var nugetPackageDownloader = new NuGetPackageDownloader.NuGetPackageDownloader(
- packageInstallDir: isGlobalTool ? _globalToolStageDir : _localToolDownloadDir,
- verboseLogger: nugetLogger,
- shouldUsePackageSourceMapping: true,
- verbosityOptions: verbosity,
- restoreActionConfig: restoreActionConfig);
+ if (group != null)
+ {
+ foreach (var item in group.Items)
+ {
+ var newItem = new LockFileItem(item.Path);
+ if (item.Properties.TryGetValue("locale", out var locale))
+ {
+ newItem.Properties["locale"] = (string)locale;
+ }
- var packageSourceLocation = new PackageSourceLocation(
- nugetConfig: packageLocation.NugetConfig,
- rootConfigDirectory: packageLocation.RootConfigDirectory,
- sourceFeedOverrides: packageLocation.SourceFeedOverrides,
- additionalSourceFeeds: packageLocation.AdditionalFeeds);
+ if (item.Properties.TryGetValue("related", out var related))
+ {
+ newItem.Properties["related"] = (string)related;
+ }
+ additionalAction?.Invoke(newItem);
+ yield return newItem;
+ }
+ // Take only the first group that has items
+ break;
+ }
+ }
- return nugetPackageDownloader.GetBestPackageVersionAsync(packageId, versionRange, packageSourceLocation).GetAwaiter().GetResult();
+ yield break;
}
}
diff --git a/src/Cli/dotnet/ToolPackage/ToolPackageDownloaderBase.cs b/src/Cli/dotnet/ToolPackage/ToolPackageDownloaderBase.cs
new file mode 100644
index 000000000000..062ed393bee5
--- /dev/null
+++ b/src/Cli/dotnet/ToolPackage/ToolPackageDownloaderBase.cs
@@ -0,0 +1,351 @@
+// 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.Reflection;
+using Microsoft.DotNet.Cli.Extensions;
+using Microsoft.DotNet.Cli.NuGetPackageDownloader;
+using Microsoft.DotNet.Cli.Utils;
+using Microsoft.Extensions.EnvironmentAbstractions;
+using Microsoft.TemplateEngine.Utils;
+using Newtonsoft.Json.Linq;
+using NuGet.Client;
+using NuGet.Commands;
+using NuGet.Common;
+using NuGet.Configuration;
+using NuGet.ContentModel;
+using NuGet.Frameworks;
+using NuGet.LibraryModel;
+using NuGet.Packaging;
+using NuGet.Packaging.Core;
+using NuGet.ProjectModel;
+using NuGet.Repositories;
+using NuGet.RuntimeModel;
+using NuGet.Versioning;
+
+namespace Microsoft.DotNet.Cli.ToolPackage;
+
+internal abstract class ToolPackageDownloaderBase : IToolPackageDownloader
+{
+ private readonly IToolPackageStore _toolPackageStore;
+
+ protected readonly IFileSystem _fileSystem;
+
+ // The directory that global tools first downloaded
+ // example: C:\Users\username\.dotnet\tools\.store\.stage\tempFolder
+ protected readonly DirectoryPath _globalToolStageDir;
+
+ // The directory that local tools first downloaded
+ // example: C:\Users\username\.nuget\package
+ protected readonly DirectoryPath _localToolDownloadDir;
+
+ // The directory that local tools' asset files located
+ // example: C:\Users\username\AppData\Local\Temp\tempFolder
+ protected readonly DirectoryPath _localToolAssetDir;
+
+ protected readonly string _runtimeJsonPath;
+
+ protected readonly string? _currentWorkingDirectory;
+
+ protected ToolPackageDownloaderBase(
+ IToolPackageStore store,
+ string? runtimeJsonPathForTests = null,
+ string? currentWorkingDirectory = null,
+ IFileSystem? fileSystem = null
+ )
+ {
+ _toolPackageStore = store ?? throw new ArgumentNullException(nameof(store));
+ _fileSystem = fileSystem ?? throw new ArgumentNullException(nameof(fileSystem));
+ _globalToolStageDir = _toolPackageStore.GetRandomStagingDirectory();
+ // NuGet settings can't use mock file system. This means in testing we will get the real global packages folder, but that is fine because we
+ // mock the whole file system anyway.
+ ISettings settings = Settings.LoadDefaultSettings(currentWorkingDirectory ?? Directory.GetCurrentDirectory());
+ _localToolDownloadDir = new DirectoryPath(SettingsUtility.GetGlobalPackagesFolder(settings));
+ _currentWorkingDirectory = currentWorkingDirectory;
+
+ _localToolAssetDir = new DirectoryPath(_fileSystem.Directory.CreateTemporarySubdirectory());
+ _runtimeJsonPath = runtimeJsonPathForTests ?? Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!, "RuntimeIdentifierGraph.json");
+ }
+
+ protected abstract INuGetPackageDownloader CreateNuGetPackageDownloader(
+ bool verifySignatures,
+ VerbosityOptions verbosity,
+ RestoreActionConfig? restoreActionConfig);
+
+ protected abstract NuGetVersion DownloadAndExtractPackage(
+ PackageId packageId,
+ INuGetPackageDownloader nugetPackageDownloader,
+ string packagesRootPath,
+ NuGetVersion packageVersion,
+ PackageSourceLocation packageSourceLocation,
+ bool includeUnlisted = false
+ );
+
+ protected abstract bool IsPackageInstalled(
+ PackageId packageId,
+ NuGetVersion packageVersion,
+ string packagesRootPath);
+
+ protected abstract void CreateAssetFile(
+ PackageId packageId,
+ NuGetVersion version,
+ DirectoryPath packagesRootPath,
+ string assetFilePath,
+ string runtimeJsonGraph,
+ string? targetFramework = null);
+
+ protected abstract ToolConfiguration GetToolConfiguration(PackageId id,
+ DirectoryPath packageDirectory,
+ DirectoryPath assetsJsonParentDirectory);
+
+ public IToolPackage InstallPackage(PackageLocation packageLocation, PackageId packageId,
+ VerbosityOptions verbosity = VerbosityOptions.normal,
+ VersionRange? versionRange = null,
+ string? targetFramework = null,
+ bool isGlobalTool = false,
+ bool isGlobalToolRollForward = false,
+ bool verifySignatures = true,
+ RestoreActionConfig? restoreActionConfig = null)
+ {
+ if (versionRange == null)
+ {
+ var versionString = "*";
+ versionRange = VersionRange.Parse(versionString);
+ }
+
+ var nugetPackageDownloader = CreateNuGetPackageDownloader(
+ verifySignatures,
+ verbosity,
+ restoreActionConfig);
+
+ var packageSourceLocation = new PackageSourceLocation(packageLocation.NugetConfig, packageLocation.RootConfigDirectory, packageLocation.SourceFeedOverrides, packageLocation.AdditionalFeeds, _currentWorkingDirectory);
+
+ NuGetVersion packageVersion = nugetPackageDownloader.GetBestPackageVersionAsync(packageId, versionRange, packageSourceLocation).GetAwaiter().GetResult();
+
+ bool givenSpecificVersion = false;
+ if (versionRange.MinVersion != null && versionRange.MaxVersion != null && versionRange.MinVersion == versionRange.MaxVersion)
+ {
+ givenSpecificVersion = true;
+ }
+
+ if (isGlobalTool)
+ {
+ return InstallGlobalToolPackageInternal(
+ packageSourceLocation,
+ nugetPackageDownloader,
+ packageId,
+ packageVersion,
+ givenSpecificVersion,
+ targetFramework,
+ isGlobalToolRollForward);
+ }
+ else
+ {
+ return InstallLocalToolPackageInternal(
+ packageSourceLocation,
+ nugetPackageDownloader,
+ packageId,
+ packageVersion,
+ givenSpecificVersion,
+ targetFramework);
+ }
+ }
+
+ protected IToolPackage InstallGlobalToolPackageInternal(
+ PackageSourceLocation packageSourceLocation,
+ INuGetPackageDownloader nugetPackageDownloader,
+ PackageId packageId,
+ NuGetVersion packageVersion,
+ bool givenSpecificVersion,
+ string? targetFramework,
+ bool isGlobalToolRollForward)
+ {
+ // Check if package already exists in global tools location
+ var nugetPackageRootDirectory = new VersionFolderPathResolver(_toolPackageStore.Root.Value).GetInstallPath(packageId.ToString(), packageVersion);
+ if (IsPackageInstalled(packageId, packageVersion, nugetPackageRootDirectory))
+ {
+ throw new ToolPackageException(
+ string.Format(
+ CliStrings.ToolPackageConflictPackageId,
+ packageId,
+ packageVersion.ToNormalizedString()));
+ }
+
+ string rollbackDirectory = _globalToolStageDir.Value;
+
+ return TransactionalAction.Run(
+ action: () =>
+ {
+ DownloadTool(
+ packageDownloadDir: _globalToolStageDir,
+ packageId,
+ packageVersion,
+ nugetPackageDownloader,
+ packageSourceLocation,
+ givenSpecificVersion,
+ assetFileDirectory: _globalToolStageDir,
+ targetFramework);
+
+ var toolStoreTargetDirectory = _toolPackageStore.GetPackageDirectory(packageId, packageVersion);
+
+ // Create parent directory in global tool store, for example dotnet\tools\.store\powershell
+ _fileSystem.Directory.CreateDirectory(toolStoreTargetDirectory.GetParentPath().Value);
+
+ // Move tool files from stage to final location
+ FileAccessRetrier.RetryOnMoveAccessFailure(() => _fileSystem.Directory.Move(_globalToolStageDir.Value, toolStoreTargetDirectory.Value));
+
+ rollbackDirectory = toolStoreTargetDirectory.Value;
+
+ var toolPackageInstance = new ToolPackageInstance(id: packageId,
+ version: packageVersion,
+ packageDirectory: toolStoreTargetDirectory,
+ assetsJsonParentDirectory: toolStoreTargetDirectory,
+ fileSystem: _fileSystem);
+
+ if (isGlobalToolRollForward)
+ {
+ UpdateRuntimeConfig(toolPackageInstance);
+ }
+
+ return toolPackageInstance;
+ },
+ rollback: () =>
+ {
+ if (rollbackDirectory != null && _fileSystem.Directory.Exists(rollbackDirectory))
+ {
+ _fileSystem.Directory.Delete(rollbackDirectory, true);
+ }
+
+ // Delete global tool store package ID directory if it's empty (ie no other versions are installed)
+ DirectoryPath packageRootDirectory = _toolPackageStore.GetRootPackageDirectory(packageId);
+ if (_fileSystem.Directory.Exists(packageRootDirectory.Value) &&
+ !_fileSystem.Directory.EnumerateFileSystemEntries(packageRootDirectory.Value).Any())
+ {
+ _fileSystem.Directory.Delete(packageRootDirectory.Value, false);
+ }
+ });
+ }
+
+ protected IToolPackage InstallLocalToolPackageInternal(
+ PackageSourceLocation packageSourceLocation,
+ INuGetPackageDownloader nugetPackageDownloader,
+ PackageId packageId,
+ NuGetVersion packageVersion,
+ bool givenSpecificVersion,
+ string? targetFramework)
+ {
+ return TransactionalAction.Run(
+ action: () =>
+ {
+ DownloadTool(
+ packageDownloadDir: _localToolDownloadDir,
+ packageId,
+ packageVersion,
+ nugetPackageDownloader,
+ packageSourceLocation,
+ givenSpecificVersion,
+ assetFileDirectory: _localToolAssetDir,
+ targetFramework);
+
+ var toolPackageInstance = new ToolPackageInstance(id: packageId,
+ version: packageVersion,
+ packageDirectory: _localToolDownloadDir,
+ assetsJsonParentDirectory: _localToolAssetDir,
+ fileSystem: _fileSystem);
+
+ return toolPackageInstance;
+ });
+ }
+
+ protected virtual void DownloadTool(
+ DirectoryPath packageDownloadDir,
+ PackageId packageId,
+ NuGetVersion packageVersion,
+ INuGetPackageDownloader nugetPackageDownloader,
+ PackageSourceLocation packageSourceLocation,
+ bool givenSpecificVersion,
+ DirectoryPath assetFileDirectory,
+ string? targetFramework)
+ {
+
+ if (!IsPackageInstalled(packageId, packageVersion, packageDownloadDir.Value))
+ {
+ DownloadAndExtractPackage(packageId, nugetPackageDownloader, packageDownloadDir.Value, packageVersion, packageSourceLocation, includeUnlisted: givenSpecificVersion);
+ }
+
+ CreateAssetFile(packageId, packageVersion, packageDownloadDir, Path.Combine(assetFileDirectory.Value, "project.assets.json"), _runtimeJsonPath, targetFramework);
+
+ // Also download RID-specific package if needed
+ var toolConfiguration = GetToolConfiguration(packageId, packageDownloadDir, assetFileDirectory);
+ if (toolConfiguration.RidSpecificPackages?.Any() == true)
+ {
+ var runtimeGraph = JsonRuntimeFormat.ReadRuntimeGraph(_runtimeJsonPath);
+ var bestRuntimeIdentifier = Microsoft.NET.Build.Tasks.NuGetUtils.GetBestMatchingRid(runtimeGraph, RuntimeInformation.RuntimeIdentifier, toolConfiguration.RidSpecificPackages.Keys, out bool wasInGraph);
+ if (bestRuntimeIdentifier == null)
+ {
+ throw new ToolPackageException(string.Format(CliStrings.ToolUnsupportedRuntimeIdentifier, RuntimeInformation.RuntimeIdentifier,
+ string.Join(" ", toolConfiguration.RidSpecificPackages.Keys)));
+ }
+
+ var resolvedPackage = toolConfiguration.RidSpecificPackages[bestRuntimeIdentifier];
+
+ if (!IsPackageInstalled(new PackageId(resolvedPackage.Id), resolvedPackage.Version, packageDownloadDir.Value))
+ {
+ DownloadAndExtractPackage(new PackageId(resolvedPackage.Id), nugetPackageDownloader, packageDownloadDir.Value, resolvedPackage.Version, packageSourceLocation, includeUnlisted: true);
+ }
+
+ CreateAssetFile(new PackageId(resolvedPackage.Id), resolvedPackage.Version, packageDownloadDir, Path.Combine(assetFileDirectory.Value, ToolPackageInstance.RidSpecificPackageAssetsFileName), _runtimeJsonPath, targetFramework);
+ }
+ }
+
+
+
+ protected void UpdateRuntimeConfig(
+ ToolPackageInstance toolPackageInstance
+ )
+ {
+ var runtimeConfigFilePath = Path.ChangeExtension(toolPackageInstance.Command.Executable.Value, ".runtimeconfig.json");
+
+ // Update the runtimeconfig.json file
+ if (_fileSystem.File.Exists(runtimeConfigFilePath))
+ {
+ string existingJson = _fileSystem.File.ReadAllText(runtimeConfigFilePath);
+
+ var jsonObject = JObject.Parse(existingJson);
+ if (jsonObject["runtimeOptions"] is JObject runtimeOptions)
+ {
+ runtimeOptions["rollForward"] = "Major";
+ string updateJson = jsonObject.ToString();
+ _fileSystem.File.WriteAllText(runtimeConfigFilePath, updateJson);
+ }
+ }
+ }
+
+ public virtual NuGetVersion GetNuGetVersion(
+ PackageLocation packageLocation,
+ PackageId packageId,
+ VerbosityOptions verbosity,
+ VersionRange? versionRange = null,
+ bool isGlobalTool = false,
+ RestoreActionConfig? restoreActionConfig = null)
+ {
+ if (versionRange == null)
+ {
+ var versionString = "*";
+ versionRange = VersionRange.Parse(versionString);
+ }
+
+ var nugetPackageDownloader = CreateNuGetPackageDownloader(
+ false,
+ verbosity,
+ restoreActionConfig);
+
+ var packageSourceLocation = new PackageSourceLocation(
+ nugetConfig: packageLocation.NugetConfig,
+ rootConfigDirectory: packageLocation.RootConfigDirectory,
+ sourceFeedOverrides: packageLocation.SourceFeedOverrides,
+ additionalSourceFeeds: packageLocation.AdditionalFeeds,
+ basePath: _currentWorkingDirectory);
+
+ return nugetPackageDownloader.GetBestPackageVersionAsync(packageId, versionRange, packageSourceLocation).GetAwaiter().GetResult();
+ }
+}
diff --git a/src/Cli/dotnet/ToolPackage/ToolPackageInstance.cs b/src/Cli/dotnet/ToolPackage/ToolPackageInstance.cs
index cb380e9fae9e..ca03522dbf2e 100644
--- a/src/Cli/dotnet/ToolPackage/ToolPackageInstance.cs
+++ b/src/Cli/dotnet/ToolPackage/ToolPackageInstance.cs
@@ -15,205 +15,196 @@ namespace Microsoft.DotNet.Cli.ToolPackage;
// This is named "ToolPackageInstance" because "ToolPackage" would conflict with the namespace
internal class ToolPackageInstance : IToolPackage
{
- public static ToolPackageInstance CreateFromAssetFile(PackageId id, DirectoryPath assetsJsonParentDirectory)
- {
- var lockFile = new LockFileFormat().Read(assetsJsonParentDirectory.WithFile(AssetsFileName).Value);
- var packageDirectory = new DirectoryPath(lockFile.PackageFolders[0].Path);
- var library = FindLibraryInLockFile(lockFile, id);
- var version = library.Version;
-
- return new ToolPackageInstance(id, version, packageDirectory, assetsJsonParentDirectory);
- }
private const string PackagedShimsDirectoryConvention = "shims";
- public IEnumerable Warnings => _toolConfiguration.Value.Warnings;
+ public IEnumerable Warnings { get; private set; }
public PackageId Id { get; private set; }
public NuGetVersion Version { get; private set; }
+ public PackageId ResolvedPackageId { get; private set; }
+
+ public NuGetVersion ResolvedPackageVersion { get; private set; }
+
public DirectoryPath PackageDirectory { get; private set; }
- public RestoredCommand Command
- {
- get
- {
- return _command.Value;
- }
- }
+ public ToolCommand Command { get; private set; }
- public IReadOnlyList PackagedShims
- {
- get
- {
- return _packagedShims.Value;
- }
- }
+ public IReadOnlyList PackagedShims { get; private set; }
public IEnumerable Frameworks { get; private set; }
+ private IFileSystem _fileSystem;
+
private const string AssetsFileName = "project.assets.json";
+ public const string RidSpecificPackageAssetsFileName = "project.assets.ridpackage.json";
private const string ToolSettingsFileName = "DotnetToolSettings.xml";
- private readonly Lazy _command;
- private readonly Lazy _toolConfiguration;
- private readonly Lazy _lockFile;
- private readonly Lazy> _packagedShims;
-
public ToolPackageInstance(PackageId id,
NuGetVersion version,
DirectoryPath packageDirectory,
- DirectoryPath assetsJsonParentDirectory)
+ DirectoryPath assetsJsonParentDirectory,
+ IFileSystem fileSystem = null)
{
- _command = new Lazy(GetCommand);
- _packagedShims = new Lazy>(GetPackagedShims);
-
Id = id;
Version = version ?? throw new ArgumentNullException(nameof(version));
PackageDirectory = packageDirectory;
- _toolConfiguration = new Lazy(GetToolConfiguration);
- _lockFile =
- new Lazy(
- () => new LockFileFormat().Read(assetsJsonParentDirectory.WithFile(AssetsFileName).Value));
- var installPath = new VersionFolderPathResolver(PackageDirectory.Value).GetInstallPath(Id.ToString(), Version);
- var toolsPackagePath = Path.Combine(installPath, "tools");
- Frameworks = Directory.GetDirectories(toolsPackagePath)
- .Select(path => NuGetFramework.ParseFolder(Path.GetFileName(path)));
- }
+ _fileSystem = fileSystem ?? new FileSystemWrapper();
- private RestoredCommand GetCommand()
- {
- try
- {
- LockFileTargetLibrary library = FindLibraryInLockFile(_lockFile.Value);
- ToolConfiguration configuration = _toolConfiguration.Value;
- LockFileItem entryPointFromLockFile = FindItemInTargetLibrary(library, configuration.ToolAssemblyEntryPoint);
- if (entryPointFromLockFile == null)
- {
- throw new ToolConfigurationException(
- string.Format(
- CliStrings.MissingToolEntryPointFile,
- configuration.ToolAssemblyEntryPoint,
- configuration.CommandName));
- }
+ bool usingRidSpecificPackage = _fileSystem.File.Exists(assetsJsonParentDirectory.WithFile(RidSpecificPackageAssetsFileName).Value);
- // Currently only "dotnet" commands are supported
- return new RestoredCommand(
- new ToolCommandName(configuration.CommandName),
- "dotnet",
- LockFileRelativePathToFullFilePath(entryPointFromLockFile.Path, library));
+ string resolvedAssetsFileNameFullPath;
+ if (usingRidSpecificPackage)
+ {
+ resolvedAssetsFileNameFullPath = assetsJsonParentDirectory.WithFile(RidSpecificPackageAssetsFileName).Value;
}
- catch (Exception ex) when (ex is UnauthorizedAccessException || ex is IOException)
+ else
{
- throw new ToolConfigurationException(
- string.Format(
- CliStrings.FailedToRetrieveToolConfiguration,
- ex.Message),
- ex);
+ resolvedAssetsFileNameFullPath = assetsJsonParentDirectory.WithFile(AssetsFileName).Value;
}
- }
- private FilePath LockFileRelativePathToFullFilePath(string lockFileRelativePath, LockFileTargetLibrary library)
- {
- return PackageDirectory
- .WithSubDirectories(
- Id.ToString(),
- library.Version.ToNormalizedString().ToLowerInvariant())
- .WithFile(lockFileRelativePath);
- }
+ LockFile lockFile;
- private ToolConfiguration GetToolConfiguration()
- {
try
{
- var library = FindLibraryInLockFile(_lockFile.Value);
- return DeserializeToolConfiguration(library);
+ using (var stream = _fileSystem.File.OpenRead(resolvedAssetsFileNameFullPath))
+ {
+ lockFile = new LockFileFormat().Read(stream, resolvedAssetsFileNameFullPath);
+ }
}
catch (Exception ex) when (ex is UnauthorizedAccessException || ex is IOException)
{
- throw new ToolConfigurationException(
- string.Format(
- CliStrings.FailedToRetrieveToolConfiguration,
- ex.Message),
- ex);
+ throw new ToolPackageException(string.Format(CliStrings.FailedToReadNuGetLockFile, Id, ex.Message), ex);
}
- }
- private IReadOnlyList GetPackagedShims()
- {
- LockFileTargetLibrary library;
- try
+ var library = FindLibraryInLockFile(lockFile);
+ if (library == null)
{
- library = FindLibraryInLockFile(_lockFile.Value);
+ throw new ToolPackageException(
+ string.Format(CliStrings.FailedToFindLibraryInAssetsFile, Id, resolvedAssetsFileNameFullPath));
}
- catch (Exception ex) when (ex is UnauthorizedAccessException || ex is IOException)
+
+
+ if (usingRidSpecificPackage)
{
- throw new ToolPackageException(
+ ResolvedPackageId = new PackageId(library.Name);
+ ResolvedPackageVersion = library.Version;
+ }
+ else
+ {
+ ResolvedPackageId = Id;
+ ResolvedPackageVersion = Version;
+ }
+
+ var toolConfiguration = DeserializeToolConfiguration(library, packageDirectory, _fileSystem);
+ Warnings = toolConfiguration.Warnings;
+
+ var installPath = new VersionFolderPathResolver(PackageDirectory.Value).GetInstallPath(ResolvedPackageId.ToString(), ResolvedPackageVersion);
+ var toolsPackagePath = Path.Combine(installPath, "tools");
+ Frameworks = _fileSystem.Directory.EnumerateDirectories(toolsPackagePath)
+ .Select(path => NuGetFramework.ParseFolder(Path.GetFileName(path))).ToList();
+
+ LockFileItem entryPointFromLockFile = FindItemInTargetLibrary(library, toolConfiguration.ToolAssemblyEntryPoint);
+ if (entryPointFromLockFile == null)
+ {
+ throw new ToolConfigurationException(
string.Format(
- CliStrings.FailedToReadNuGetLockFile,
- Id,
- ex.Message),
- ex);
+ CliStrings.MissingToolEntryPointFile,
+ toolConfiguration.ToolAssemblyEntryPoint,
+ toolConfiguration.CommandName));
}
+ Command = new ToolCommand(
+ new ToolCommandName(toolConfiguration.CommandName),
+ toolConfiguration.Runner,
+ LockFileRelativePathToFullFilePath(entryPointFromLockFile.Path, library));
+
IEnumerable filesUnderShimsDirectory = library
?.ToolsAssemblies
?.Where(t => LockFileMatcher.MatchesDirectoryPath(t, PackagedShimsDirectoryConvention));
if (filesUnderShimsDirectory == null)
{
- return [];
- }
-
- IEnumerable allAvailableShimRuntimeIdentifiers = filesUnderShimsDirectory
- .Select(f => f.Path.Split('\\', '/')?[4]) // ex: "tools/netcoreapp2.1/any/shims/osx-x64/demo" osx-x64 is at [4]
- .Where(f => !string.IsNullOrEmpty(f));
-
- if (new FrameworkDependencyFile().TryGetMostFitRuntimeIdentifier(
- DotnetFiles.VersionFileObject.BuildRid,
- [.. allAvailableShimRuntimeIdentifiers],
- out var mostFitRuntimeIdentifier))
- {
- return library?.ToolsAssemblies?.Where(l => LockFileMatcher.MatchesDirectoryPath(l, $"{PackagedShimsDirectoryConvention}/{mostFitRuntimeIdentifier}"))
- .Select(l => LockFileRelativePathToFullFilePath(l.Path, library)).ToArray() ?? [];
+ PackagedShims = [];
}
else
{
- return [];
+ IEnumerable allAvailableShimRuntimeIdentifiers = filesUnderShimsDirectory
+ .Select(f => f.Path.Split('\\', '/')?[4]) // ex: "tools/netcoreapp2.1/any/shims/osx-x64/demo" osx-x64 is at [4]
+ .Where(f => !string.IsNullOrEmpty(f));
+
+ if (new FrameworkDependencyFile().TryGetMostFitRuntimeIdentifier(
+ DotnetFiles.VersionFileObject.BuildRid,
+ [.. allAvailableShimRuntimeIdentifiers],
+ out var mostFitRuntimeIdentifier))
+ {
+ PackagedShims = library?.ToolsAssemblies?.Where(l => LockFileMatcher.MatchesDirectoryPath(l, $"{PackagedShimsDirectoryConvention}/{mostFitRuntimeIdentifier}"))
+ .Select(l => LockFileRelativePathToFullFilePath(l.Path, library)).ToArray() ?? [];
+ }
+ else
+ {
+ PackagedShims = [];
+ }
}
}
- private ToolConfiguration DeserializeToolConfiguration(LockFileTargetLibrary library)
+ private FilePath LockFileRelativePathToFullFilePath(string lockFileRelativePath, LockFileTargetLibrary library)
{
- var dotnetToolSettings = FindItemInTargetLibrary(library, ToolSettingsFileName);
- if (dotnetToolSettings == null)
- {
- throw new ToolConfigurationException(
- CliStrings.MissingToolSettingsFile);
- }
+ return PackageDirectory
+ .WithSubDirectories(
+ library.Name,
+ library.Version.ToNormalizedString().ToLowerInvariant())
+ .WithFile(lockFileRelativePath);
+ }
- var toolConfigurationPath =
- PackageDirectory
- .WithSubDirectories(
- Id.ToString(),
- library.Version.ToNormalizedString().ToLowerInvariant())
- .WithFile(dotnetToolSettings.Path);
- var configuration = ToolConfigurationDeserializer.Deserialize(toolConfigurationPath.Value);
- return configuration;
+ public static ToolConfiguration GetToolConfiguration(PackageId id,
+ DirectoryPath packageDirectory,
+ DirectoryPath assetsJsonParentDirectory, IFileSystem fileSystem)
+ {
+ var lockFile = new LockFileFormat().Read(assetsJsonParentDirectory.WithFile(AssetsFileName).Value);
+ var lockFileTargetLibrary = FindLibraryInLockFile(lockFile);
+ return DeserializeToolConfiguration(lockFileTargetLibrary, packageDirectory, fileSystem);
+
}
- private static LockFileTargetLibrary FindLibraryInLockFile(LockFile lockFile, PackageId id)
+ private static ToolConfiguration DeserializeToolConfiguration(LockFileTargetLibrary library, DirectoryPath packageDirectory, IFileSystem fileSystem)
{
- return lockFile
- ?.Targets?.SingleOrDefault(t => t.RuntimeIdentifier != null)
- ?.Libraries?.SingleOrDefault(l =>
- string.Compare(l.Name, id.ToString(), StringComparison.OrdinalIgnoreCase) == 0);
+ try
+ {
+ var dotnetToolSettings = FindItemInTargetLibrary(library, ToolSettingsFileName);
+ if (dotnetToolSettings == null)
+ {
+ throw new ToolConfigurationException(
+ CliStrings.MissingToolSettingsFile);
+ }
+
+ var toolConfigurationPath =
+ packageDirectory
+ .WithSubDirectories(
+ new PackageId(library.Name).ToString(),
+ library.Version.ToNormalizedString().ToLowerInvariant())
+ .WithFile(dotnetToolSettings.Path);
+
+ var configuration = ToolConfigurationDeserializer.Deserialize(toolConfigurationPath.Value, fileSystem);
+ return configuration;
+ }
+ catch (Exception ex) when (ex is UnauthorizedAccessException || ex is IOException)
+ {
+ throw new ToolConfigurationException(
+ string.Format(
+ CliStrings.FailedToRetrieveToolConfiguration,
+ ex.Message),
+ ex);
+ }
}
- private LockFileTargetLibrary FindLibraryInLockFile(LockFile lockFile)
+ private static LockFileTargetLibrary FindLibraryInLockFile(LockFile lockFile)
{
- return FindLibraryInLockFile(lockFile, Id);
+ return lockFile
+ ?.Targets?.SingleOrDefault(t => t.RuntimeIdentifier != null)
+ ?.Libraries?.SingleOrDefault();
}
private static LockFileItem FindItemInTargetLibrary(LockFileTargetLibrary library, string targetRelativeFilePath)
diff --git a/src/Cli/dotnet/ToolPackage/ToolPackageStoreAndQuery.cs b/src/Cli/dotnet/ToolPackage/ToolPackageStoreAndQuery.cs
index 9c9dcec5d8dc..a415f2951fc2 100644
--- a/src/Cli/dotnet/ToolPackage/ToolPackageStoreAndQuery.cs
+++ b/src/Cli/dotnet/ToolPackage/ToolPackageStoreAndQuery.cs
@@ -8,12 +8,14 @@
namespace Microsoft.DotNet.Cli.ToolPackage;
-internal class ToolPackageStoreAndQuery(DirectoryPath root) : IToolPackageStoreQuery, IToolPackageStore
+internal class ToolPackageStoreAndQuery(DirectoryPath root, IFileSystem fileSystem = null) : IToolPackageStoreQuery, IToolPackageStore
{
public const string StagingDirectory = ".stage";
public DirectoryPath Root { get; private set; } = new DirectoryPath(Path.GetFullPath(root.Value));
+ private IFileSystem _fileSystem = fileSystem ?? new FileSystemWrapper();
+
public DirectoryPath GetRandomStagingDirectory()
{
return Root.WithSubDirectories(StagingDirectory, Path.GetRandomFileName());
@@ -23,7 +25,7 @@ public NuGetVersion GetStagedPackageVersion(DirectoryPath stagingDirectory, Pack
{
if (NuGetVersion.TryParse(
Path.GetFileName(
- Directory.EnumerateDirectories(
+ _fileSystem.Directory.EnumerateDirectories(
stagingDirectory.WithSubDirectories(packageId.ToString()).Value).FirstOrDefault()),
out var version))
{
@@ -54,12 +56,12 @@ public DirectoryPath GetPackageDirectory(PackageId packageId, NuGetVersion versi
public IEnumerable EnumeratePackages()
{
- if (!Directory.Exists(Root.Value))
+ if (!_fileSystem.Directory.Exists(Root.Value))
{
yield break;
}
- foreach (var subdirectory in Directory.EnumerateDirectories(Root.Value))
+ foreach (var subdirectory in _fileSystem.Directory.EnumerateDirectories(Root.Value))
{
var name = Path.GetFileName(subdirectory);
var packageId = new PackageId(name);
@@ -80,17 +82,17 @@ public IEnumerable EnumeratePackages()
public IEnumerable EnumeratePackageVersions(PackageId packageId)
{
var packageRootDirectory = Root.WithSubDirectories(packageId.ToString());
- if (!Directory.Exists(packageRootDirectory.Value))
+ if (!_fileSystem.Directory.Exists(packageRootDirectory.Value))
{
yield break;
}
- foreach (var subdirectory in Directory.EnumerateDirectories(packageRootDirectory.Value))
+ foreach (var subdirectory in _fileSystem.Directory.EnumerateDirectories(packageRootDirectory.Value))
{
yield return new ToolPackageInstance(id: packageId,
version: NuGetVersion.Parse(Path.GetFileName(subdirectory)),
packageDirectory: new DirectoryPath(subdirectory),
- assetsJsonParentDirectory: new DirectoryPath(subdirectory));
+ assetsJsonParentDirectory: new DirectoryPath(subdirectory), _fileSystem);
}
}
@@ -102,7 +104,7 @@ public IToolPackage GetPackage(PackageId packageId, NuGetVersion version)
}
var directory = GetPackageDirectory(packageId, version);
- if (!Directory.Exists(directory.Value))
+ if (!_fileSystem.Directory.Exists(directory.Value))
{
return null;
}
@@ -110,6 +112,7 @@ public IToolPackage GetPackage(PackageId packageId, NuGetVersion version)
return new ToolPackageInstance(id: packageId,
version: version,
packageDirectory: directory,
- assetsJsonParentDirectory: directory);
+ assetsJsonParentDirectory: directory,
+ fileSystem: _fileSystem);
}
}
diff --git a/src/Cli/dotnet/dotnet.csproj b/src/Cli/dotnet/dotnet.csproj
index f6b9b0a7015d..295df7753ff3 100644
--- a/src/Cli/dotnet/dotnet.csproj
+++ b/src/Cli/dotnet/dotnet.csproj
@@ -26,6 +26,7 @@
+
diff --git a/src/Cli/dotnet/xlf/CliStrings.cs.xlf b/src/Cli/dotnet/xlf/CliStrings.cs.xlf
index 271dc12ceb98..f63c632009a3 100644
--- a/src/Cli/dotnet/xlf/CliStrings.cs.xlf
+++ b/src/Cli/dotnet/xlf/CliStrings.cs.xlf
@@ -369,6 +369,11 @@ setx PATH "%PATH%;{0}"
{0}: failed to find commandPath {1}
+
+ Failed to find library in NuGet assets file for tool package '{0}': {1}
+ Failed to find library in NuGet assets file for tool package '{0}': {1}
+
+ Package Source Mapping is enabled, but no source found under the specified package ID: {0}. See the documentation for Package Source Mapping at https://aka.ms/nuget-package-source-mapping for more details.Package Source Mapping is enabled, but no source found under the specified package ID: {0}. See the documentation for Package Source Mapping at https://aka.ms/nuget-package-source-mapping for more details.
@@ -395,8 +400,8 @@ setx PATH "%PATH%;{0}"
- Failed to read NuGet LockFile for tool package '{0}': {1}
- Failed to read NuGet LockFile for tool package '{0}': {1}
+ Failed to read NuGet assets file for tool package '{0}': {1}
+ Failed to read NuGet assets file for tool package '{0}': {1}
@@ -1037,6 +1042,11 @@ The default is 'false.' However, when targeting .NET 7 or lower, the default is
Tool '{0}' (version '{1}') is already installed.
+
+ Package {0} is not a .NET tool.
+ Package {0} is not a .NET tool.
+
+ Command '{0}' contains one or more of the following invalid characters: {1}.Command '{0}' contains one or more of the following invalid characters: {1}.
@@ -1072,6 +1082,11 @@ The default is 'false.' However, when targeting .NET 7 or lower, the default is
Command '{0}' uses unsupported runner '{1}'."
+
+ The tool does not support the current architecture or operating system ({0}). Supported runtimes: {1}
+ The tool does not support the current architecture or operating system ({0}). Supported runtimes: {1}
+
+ TypeType
diff --git a/src/Cli/dotnet/xlf/CliStrings.de.xlf b/src/Cli/dotnet/xlf/CliStrings.de.xlf
index f7192562bbdd..534ba566fc55 100644
--- a/src/Cli/dotnet/xlf/CliStrings.de.xlf
+++ b/src/Cli/dotnet/xlf/CliStrings.de.xlf
@@ -369,6 +369,11 @@ setx PATH "%PATH%;{0}"
{0}: failed to find commandPath {1}
+
+ Failed to find library in NuGet assets file for tool package '{0}': {1}
+ Failed to find library in NuGet assets file for tool package '{0}': {1}
+
+ Package Source Mapping is enabled, but no source found under the specified package ID: {0}. See the documentation for Package Source Mapping at https://aka.ms/nuget-package-source-mapping for more details.Package Source Mapping is enabled, but no source found under the specified package ID: {0}. See the documentation for Package Source Mapping at https://aka.ms/nuget-package-source-mapping for more details.
@@ -395,8 +400,8 @@ setx PATH "%PATH%;{0}"
- Failed to read NuGet LockFile for tool package '{0}': {1}
- Failed to read NuGet LockFile for tool package '{0}': {1}
+ Failed to read NuGet assets file for tool package '{0}': {1}
+ Failed to read NuGet assets file for tool package '{0}': {1}
@@ -1037,6 +1042,11 @@ The default is 'false.' However, when targeting .NET 7 or lower, the default is
Tool '{0}' (version '{1}') is already installed.
+
+ Package {0} is not a .NET tool.
+ Package {0} is not a .NET tool.
+
+ Command '{0}' contains one or more of the following invalid characters: {1}.Command '{0}' contains one or more of the following invalid characters: {1}.
@@ -1072,6 +1082,11 @@ The default is 'false.' However, when targeting .NET 7 or lower, the default is
Command '{0}' uses unsupported runner '{1}'."
+
+ The tool does not support the current architecture or operating system ({0}). Supported runtimes: {1}
+ The tool does not support the current architecture or operating system ({0}). Supported runtimes: {1}
+
+ TypeType
diff --git a/src/Cli/dotnet/xlf/CliStrings.es.xlf b/src/Cli/dotnet/xlf/CliStrings.es.xlf
index f9d18989e2f4..0eb90c7d4778 100644
--- a/src/Cli/dotnet/xlf/CliStrings.es.xlf
+++ b/src/Cli/dotnet/xlf/CliStrings.es.xlf
@@ -369,6 +369,11 @@ setx PATH "%PATH%;{0}"
{0}: failed to find commandPath {1}
+
+ Failed to find library in NuGet assets file for tool package '{0}': {1}
+ Failed to find library in NuGet assets file for tool package '{0}': {1}
+
+ Package Source Mapping is enabled, but no source found under the specified package ID: {0}. See the documentation for Package Source Mapping at https://aka.ms/nuget-package-source-mapping for more details.Package Source Mapping is enabled, but no source found under the specified package ID: {0}. See the documentation for Package Source Mapping at https://aka.ms/nuget-package-source-mapping for more details.
@@ -395,8 +400,8 @@ setx PATH "%PATH%;{0}"
- Failed to read NuGet LockFile for tool package '{0}': {1}
- Failed to read NuGet LockFile for tool package '{0}': {1}
+ Failed to read NuGet assets file for tool package '{0}': {1}
+ Failed to read NuGet assets file for tool package '{0}': {1}
@@ -1037,6 +1042,11 @@ The default is 'false.' However, when targeting .NET 7 or lower, the default is
Tool '{0}' (version '{1}') is already installed.
+
+ Package {0} is not a .NET tool.
+ Package {0} is not a .NET tool.
+
+ Command '{0}' contains one or more of the following invalid characters: {1}.Command '{0}' contains one or more of the following invalid characters: {1}.
@@ -1072,6 +1082,11 @@ The default is 'false.' However, when targeting .NET 7 or lower, the default is
Command '{0}' uses unsupported runner '{1}'."
+
+ The tool does not support the current architecture or operating system ({0}). Supported runtimes: {1}
+ The tool does not support the current architecture or operating system ({0}). Supported runtimes: {1}
+
+ TypeType
diff --git a/src/Cli/dotnet/xlf/CliStrings.fr.xlf b/src/Cli/dotnet/xlf/CliStrings.fr.xlf
index 4de69d570b01..6a0e4c843aa7 100644
--- a/src/Cli/dotnet/xlf/CliStrings.fr.xlf
+++ b/src/Cli/dotnet/xlf/CliStrings.fr.xlf
@@ -369,6 +369,11 @@ setx PATH "%PATH%;{0}"
{0}: failed to find commandPath {1}
+
+ Failed to find library in NuGet assets file for tool package '{0}': {1}
+ Failed to find library in NuGet assets file for tool package '{0}': {1}
+
+ Package Source Mapping is enabled, but no source found under the specified package ID: {0}. See the documentation for Package Source Mapping at https://aka.ms/nuget-package-source-mapping for more details.Package Source Mapping is enabled, but no source found under the specified package ID: {0}. See the documentation for Package Source Mapping at https://aka.ms/nuget-package-source-mapping for more details.
@@ -395,8 +400,8 @@ setx PATH "%PATH%;{0}"
- Failed to read NuGet LockFile for tool package '{0}': {1}
- Failed to read NuGet LockFile for tool package '{0}': {1}
+ Failed to read NuGet assets file for tool package '{0}': {1}
+ Failed to read NuGet assets file for tool package '{0}': {1}
@@ -1037,6 +1042,11 @@ The default is 'false.' However, when targeting .NET 7 or lower, the default is
Tool '{0}' (version '{1}') is already installed.
+
+ Package {0} is not a .NET tool.
+ Package {0} is not a .NET tool.
+
+ Command '{0}' contains one or more of the following invalid characters: {1}.Command '{0}' contains one or more of the following invalid characters: {1}.
@@ -1072,6 +1082,11 @@ The default is 'false.' However, when targeting .NET 7 or lower, the default is
Command '{0}' uses unsupported runner '{1}'."
+
+ The tool does not support the current architecture or operating system ({0}). Supported runtimes: {1}
+ The tool does not support the current architecture or operating system ({0}). Supported runtimes: {1}
+
+ TypeType
diff --git a/src/Cli/dotnet/xlf/CliStrings.it.xlf b/src/Cli/dotnet/xlf/CliStrings.it.xlf
index a566d521423f..e61372265e98 100644
--- a/src/Cli/dotnet/xlf/CliStrings.it.xlf
+++ b/src/Cli/dotnet/xlf/CliStrings.it.xlf
@@ -369,6 +369,11 @@ setx PATH "%PATH%;{0}"
{0}: failed to find commandPath {1}
+
+ Failed to find library in NuGet assets file for tool package '{0}': {1}
+ Failed to find library in NuGet assets file for tool package '{0}': {1}
+
+ Package Source Mapping is enabled, but no source found under the specified package ID: {0}. See the documentation for Package Source Mapping at https://aka.ms/nuget-package-source-mapping for more details.Package Source Mapping is enabled, but no source found under the specified package ID: {0}. See the documentation for Package Source Mapping at https://aka.ms/nuget-package-source-mapping for more details.
@@ -395,8 +400,8 @@ setx PATH "%PATH%;{0}"
- Failed to read NuGet LockFile for tool package '{0}': {1}
- Failed to read NuGet LockFile for tool package '{0}': {1}
+ Failed to read NuGet assets file for tool package '{0}': {1}
+ Failed to read NuGet assets file for tool package '{0}': {1}
@@ -1037,6 +1042,11 @@ The default is 'false.' However, when targeting .NET 7 or lower, the default is
Tool '{0}' (version '{1}') is already installed.
+
+ Package {0} is not a .NET tool.
+ Package {0} is not a .NET tool.
+
+ Command '{0}' contains one or more of the following invalid characters: {1}.Command '{0}' contains one or more of the following invalid characters: {1}.
@@ -1072,6 +1082,11 @@ The default is 'false.' However, when targeting .NET 7 or lower, the default is
Command '{0}' uses unsupported runner '{1}'."
+
+ The tool does not support the current architecture or operating system ({0}). Supported runtimes: {1}
+ The tool does not support the current architecture or operating system ({0}). Supported runtimes: {1}
+
+ TypeType
diff --git a/src/Cli/dotnet/xlf/CliStrings.ja.xlf b/src/Cli/dotnet/xlf/CliStrings.ja.xlf
index 528dcc1e8296..c9df2114d91c 100644
--- a/src/Cli/dotnet/xlf/CliStrings.ja.xlf
+++ b/src/Cli/dotnet/xlf/CliStrings.ja.xlf
@@ -369,6 +369,11 @@ setx PATH "%PATH%;{0}"
{0}: failed to find commandPath {1}
+
+ Failed to find library in NuGet assets file for tool package '{0}': {1}
+ Failed to find library in NuGet assets file for tool package '{0}': {1}
+
+ Package Source Mapping is enabled, but no source found under the specified package ID: {0}. See the documentation for Package Source Mapping at https://aka.ms/nuget-package-source-mapping for more details.Package Source Mapping is enabled, but no source found under the specified package ID: {0}. See the documentation for Package Source Mapping at https://aka.ms/nuget-package-source-mapping for more details.
@@ -395,8 +400,8 @@ setx PATH "%PATH%;{0}"
- Failed to read NuGet LockFile for tool package '{0}': {1}
- Failed to read NuGet LockFile for tool package '{0}': {1}
+ Failed to read NuGet assets file for tool package '{0}': {1}
+ Failed to read NuGet assets file for tool package '{0}': {1}
@@ -1037,6 +1042,11 @@ The default is 'false.' However, when targeting .NET 7 or lower, the default is
Tool '{0}' (version '{1}') is already installed.
+
+ Package {0} is not a .NET tool.
+ Package {0} is not a .NET tool.
+
+ Command '{0}' contains one or more of the following invalid characters: {1}.Command '{0}' contains one or more of the following invalid characters: {1}.
@@ -1072,6 +1082,11 @@ The default is 'false.' However, when targeting .NET 7 or lower, the default is
Command '{0}' uses unsupported runner '{1}'."
+
+ The tool does not support the current architecture or operating system ({0}). Supported runtimes: {1}
+ The tool does not support the current architecture or operating system ({0}). Supported runtimes: {1}
+
+ TypeType
diff --git a/src/Cli/dotnet/xlf/CliStrings.ko.xlf b/src/Cli/dotnet/xlf/CliStrings.ko.xlf
index 242ce343de45..13c743594420 100644
--- a/src/Cli/dotnet/xlf/CliStrings.ko.xlf
+++ b/src/Cli/dotnet/xlf/CliStrings.ko.xlf
@@ -369,6 +369,11 @@ setx PATH "%PATH%;{0}"
{0}: failed to find commandPath {1}
+
+ Failed to find library in NuGet assets file for tool package '{0}': {1}
+ Failed to find library in NuGet assets file for tool package '{0}': {1}
+
+ Package Source Mapping is enabled, but no source found under the specified package ID: {0}. See the documentation for Package Source Mapping at https://aka.ms/nuget-package-source-mapping for more details.Package Source Mapping is enabled, but no source found under the specified package ID: {0}. See the documentation for Package Source Mapping at https://aka.ms/nuget-package-source-mapping for more details.
@@ -395,8 +400,8 @@ setx PATH "%PATH%;{0}"
- Failed to read NuGet LockFile for tool package '{0}': {1}
- Failed to read NuGet LockFile for tool package '{0}': {1}
+ Failed to read NuGet assets file for tool package '{0}': {1}
+ Failed to read NuGet assets file for tool package '{0}': {1}
@@ -1037,6 +1042,11 @@ The default is 'false.' However, when targeting .NET 7 or lower, the default is
Tool '{0}' (version '{1}') is already installed.
+
+ Package {0} is not a .NET tool.
+ Package {0} is not a .NET tool.
+
+ Command '{0}' contains one or more of the following invalid characters: {1}.Command '{0}' contains one or more of the following invalid characters: {1}.
@@ -1072,6 +1082,11 @@ The default is 'false.' However, when targeting .NET 7 or lower, the default is
Command '{0}' uses unsupported runner '{1}'."
+
+ The tool does not support the current architecture or operating system ({0}). Supported runtimes: {1}
+ The tool does not support the current architecture or operating system ({0}). Supported runtimes: {1}
+
+ TypeType
diff --git a/src/Cli/dotnet/xlf/CliStrings.pl.xlf b/src/Cli/dotnet/xlf/CliStrings.pl.xlf
index fe204fdd12a6..93a290b184d9 100644
--- a/src/Cli/dotnet/xlf/CliStrings.pl.xlf
+++ b/src/Cli/dotnet/xlf/CliStrings.pl.xlf
@@ -369,6 +369,11 @@ setx PATH "%PATH%;{0}"
{0}: failed to find commandPath {1}
+
+ Failed to find library in NuGet assets file for tool package '{0}': {1}
+ Failed to find library in NuGet assets file for tool package '{0}': {1}
+
+ Package Source Mapping is enabled, but no source found under the specified package ID: {0}. See the documentation for Package Source Mapping at https://aka.ms/nuget-package-source-mapping for more details.Package Source Mapping is enabled, but no source found under the specified package ID: {0}. See the documentation for Package Source Mapping at https://aka.ms/nuget-package-source-mapping for more details.
@@ -395,8 +400,8 @@ setx PATH "%PATH%;{0}"
- Failed to read NuGet LockFile for tool package '{0}': {1}
- Failed to read NuGet LockFile for tool package '{0}': {1}
+ Failed to read NuGet assets file for tool package '{0}': {1}
+ Failed to read NuGet assets file for tool package '{0}': {1}
@@ -1037,6 +1042,11 @@ The default is 'false.' However, when targeting .NET 7 or lower, the default is
Tool '{0}' (version '{1}') is already installed.
+
+ Package {0} is not a .NET tool.
+ Package {0} is not a .NET tool.
+
+ Command '{0}' contains one or more of the following invalid characters: {1}.Command '{0}' contains one or more of the following invalid characters: {1}.
@@ -1072,6 +1082,11 @@ The default is 'false.' However, when targeting .NET 7 or lower, the default is
Command '{0}' uses unsupported runner '{1}'."
+
+ The tool does not support the current architecture or operating system ({0}). Supported runtimes: {1}
+ The tool does not support the current architecture or operating system ({0}). Supported runtimes: {1}
+
+ TypeType
diff --git a/src/Cli/dotnet/xlf/CliStrings.pt-BR.xlf b/src/Cli/dotnet/xlf/CliStrings.pt-BR.xlf
index 42ee8b4062c3..6b1844b87678 100644
--- a/src/Cli/dotnet/xlf/CliStrings.pt-BR.xlf
+++ b/src/Cli/dotnet/xlf/CliStrings.pt-BR.xlf
@@ -369,6 +369,11 @@ setx PATH "%PATH%;{0}"
{0}: failed to find commandPath {1}
+
+ Failed to find library in NuGet assets file for tool package '{0}': {1}
+ Failed to find library in NuGet assets file for tool package '{0}': {1}
+
+ Package Source Mapping is enabled, but no source found under the specified package ID: {0}. See the documentation for Package Source Mapping at https://aka.ms/nuget-package-source-mapping for more details.Package Source Mapping is enabled, but no source found under the specified package ID: {0}. See the documentation for Package Source Mapping at https://aka.ms/nuget-package-source-mapping for more details.
@@ -395,8 +400,8 @@ setx PATH "%PATH%;{0}"
- Failed to read NuGet LockFile for tool package '{0}': {1}
- Failed to read NuGet LockFile for tool package '{0}': {1}
+ Failed to read NuGet assets file for tool package '{0}': {1}
+ Failed to read NuGet assets file for tool package '{0}': {1}
@@ -1037,6 +1042,11 @@ The default is 'false.' However, when targeting .NET 7 or lower, the default is
Tool '{0}' (version '{1}') is already installed.
+
+ Package {0} is not a .NET tool.
+ Package {0} is not a .NET tool.
+
+ Command '{0}' contains one or more of the following invalid characters: {1}.Command '{0}' contains one or more of the following invalid characters: {1}.
@@ -1072,6 +1082,11 @@ The default is 'false.' However, when targeting .NET 7 or lower, the default is
Command '{0}' uses unsupported runner '{1}'."
+
+ The tool does not support the current architecture or operating system ({0}). Supported runtimes: {1}
+ The tool does not support the current architecture or operating system ({0}). Supported runtimes: {1}
+
+ TypeType
diff --git a/src/Cli/dotnet/xlf/CliStrings.ru.xlf b/src/Cli/dotnet/xlf/CliStrings.ru.xlf
index 5748a0d29601..5ae630abba78 100644
--- a/src/Cli/dotnet/xlf/CliStrings.ru.xlf
+++ b/src/Cli/dotnet/xlf/CliStrings.ru.xlf
@@ -369,6 +369,11 @@ setx PATH "%PATH%;{0}"
{0}: failed to find commandPath {1}
+
+ Failed to find library in NuGet assets file for tool package '{0}': {1}
+ Failed to find library in NuGet assets file for tool package '{0}': {1}
+
+ Package Source Mapping is enabled, but no source found under the specified package ID: {0}. See the documentation for Package Source Mapping at https://aka.ms/nuget-package-source-mapping for more details.Package Source Mapping is enabled, but no source found under the specified package ID: {0}. See the documentation for Package Source Mapping at https://aka.ms/nuget-package-source-mapping for more details.
@@ -395,8 +400,8 @@ setx PATH "%PATH%;{0}"
- Failed to read NuGet LockFile for tool package '{0}': {1}
- Failed to read NuGet LockFile for tool package '{0}': {1}
+ Failed to read NuGet assets file for tool package '{0}': {1}
+ Failed to read NuGet assets file for tool package '{0}': {1}
@@ -1037,6 +1042,11 @@ The default is 'false.' However, when targeting .NET 7 or lower, the default is
Tool '{0}' (version '{1}') is already installed.
+
+ Package {0} is not a .NET tool.
+ Package {0} is not a .NET tool.
+
+ Command '{0}' contains one or more of the following invalid characters: {1}.Command '{0}' contains one or more of the following invalid characters: {1}.
@@ -1072,6 +1082,11 @@ The default is 'false.' However, when targeting .NET 7 or lower, the default is
Command '{0}' uses unsupported runner '{1}'."
+
+ The tool does not support the current architecture or operating system ({0}). Supported runtimes: {1}
+ The tool does not support the current architecture or operating system ({0}). Supported runtimes: {1}
+
+ TypeType
diff --git a/src/Cli/dotnet/xlf/CliStrings.tr.xlf b/src/Cli/dotnet/xlf/CliStrings.tr.xlf
index c694a19b6cb9..8e371f35753f 100644
--- a/src/Cli/dotnet/xlf/CliStrings.tr.xlf
+++ b/src/Cli/dotnet/xlf/CliStrings.tr.xlf
@@ -369,6 +369,11 @@ setx PATH "%PATH%;{0}"
{0}: failed to find commandPath {1}
+
+ Failed to find library in NuGet assets file for tool package '{0}': {1}
+ Failed to find library in NuGet assets file for tool package '{0}': {1}
+
+ Package Source Mapping is enabled, but no source found under the specified package ID: {0}. See the documentation for Package Source Mapping at https://aka.ms/nuget-package-source-mapping for more details.Package Source Mapping is enabled, but no source found under the specified package ID: {0}. See the documentation for Package Source Mapping at https://aka.ms/nuget-package-source-mapping for more details.
@@ -395,8 +400,8 @@ setx PATH "%PATH%;{0}"
- Failed to read NuGet LockFile for tool package '{0}': {1}
- Failed to read NuGet LockFile for tool package '{0}': {1}
+ Failed to read NuGet assets file for tool package '{0}': {1}
+ Failed to read NuGet assets file for tool package '{0}': {1}
@@ -1037,6 +1042,11 @@ The default is 'false.' However, when targeting .NET 7 or lower, the default is
Tool '{0}' (version '{1}') is already installed.
+
+ Package {0} is not a .NET tool.
+ Package {0} is not a .NET tool.
+
+ Command '{0}' contains one or more of the following invalid characters: {1}.Command '{0}' contains one or more of the following invalid characters: {1}.
@@ -1072,6 +1082,11 @@ The default is 'false.' However, when targeting .NET 7 or lower, the default is
Command '{0}' uses unsupported runner '{1}'."
+
+ The tool does not support the current architecture or operating system ({0}). Supported runtimes: {1}
+ The tool does not support the current architecture or operating system ({0}). Supported runtimes: {1}
+
+ TypeType
diff --git a/src/Cli/dotnet/xlf/CliStrings.zh-Hans.xlf b/src/Cli/dotnet/xlf/CliStrings.zh-Hans.xlf
index 02551c8c7e27..1d4643fc5738 100644
--- a/src/Cli/dotnet/xlf/CliStrings.zh-Hans.xlf
+++ b/src/Cli/dotnet/xlf/CliStrings.zh-Hans.xlf
@@ -369,6 +369,11 @@ setx PATH "%PATH%;{0}"
{0}: failed to find commandPath {1}
+
+ Failed to find library in NuGet assets file for tool package '{0}': {1}
+ Failed to find library in NuGet assets file for tool package '{0}': {1}
+
+ Package Source Mapping is enabled, but no source found under the specified package ID: {0}. See the documentation for Package Source Mapping at https://aka.ms/nuget-package-source-mapping for more details.Package Source Mapping is enabled, but no source found under the specified package ID: {0}. See the documentation for Package Source Mapping at https://aka.ms/nuget-package-source-mapping for more details.
@@ -395,8 +400,8 @@ setx PATH "%PATH%;{0}"
- Failed to read NuGet LockFile for tool package '{0}': {1}
- Failed to read NuGet LockFile for tool package '{0}': {1}
+ Failed to read NuGet assets file for tool package '{0}': {1}
+ Failed to read NuGet assets file for tool package '{0}': {1}
@@ -1037,6 +1042,11 @@ The default is 'false.' However, when targeting .NET 7 or lower, the default is
Tool '{0}' (version '{1}') is already installed.
+
+ Package {0} is not a .NET tool.
+ Package {0} is not a .NET tool.
+
+ Command '{0}' contains one or more of the following invalid characters: {1}.Command '{0}' contains one or more of the following invalid characters: {1}.
@@ -1072,6 +1082,11 @@ The default is 'false.' However, when targeting .NET 7 or lower, the default is
Command '{0}' uses unsupported runner '{1}'."
+
+ The tool does not support the current architecture or operating system ({0}). Supported runtimes: {1}
+ The tool does not support the current architecture or operating system ({0}). Supported runtimes: {1}
+
+ TypeType
diff --git a/src/Cli/dotnet/xlf/CliStrings.zh-Hant.xlf b/src/Cli/dotnet/xlf/CliStrings.zh-Hant.xlf
index 6bd11b5a149f..da11764e28b1 100644
--- a/src/Cli/dotnet/xlf/CliStrings.zh-Hant.xlf
+++ b/src/Cli/dotnet/xlf/CliStrings.zh-Hant.xlf
@@ -369,6 +369,11 @@ setx PATH "%PATH%;{0}"
{0}: failed to find commandPath {1}
+
+ Failed to find library in NuGet assets file for tool package '{0}': {1}
+ Failed to find library in NuGet assets file for tool package '{0}': {1}
+
+ Package Source Mapping is enabled, but no source found under the specified package ID: {0}. See the documentation for Package Source Mapping at https://aka.ms/nuget-package-source-mapping for more details.Package Source Mapping is enabled, but no source found under the specified package ID: {0}. See the documentation for Package Source Mapping at https://aka.ms/nuget-package-source-mapping for more details.
@@ -395,8 +400,8 @@ setx PATH "%PATH%;{0}"
- Failed to read NuGet LockFile for tool package '{0}': {1}
- Failed to read NuGet LockFile for tool package '{0}': {1}
+ Failed to read NuGet assets file for tool package '{0}': {1}
+ Failed to read NuGet assets file for tool package '{0}': {1}
@@ -1037,6 +1042,11 @@ The default is 'false.' However, when targeting .NET 7 or lower, the default is
Tool '{0}' (version '{1}') is already installed.
+
+ Package {0} is not a .NET tool.
+ Package {0} is not a .NET tool.
+
+ Command '{0}' contains one or more of the following invalid characters: {1}.Command '{0}' contains one or more of the following invalid characters: {1}.
@@ -1072,6 +1082,11 @@ The default is 'false.' However, when targeting .NET 7 or lower, the default is
Command '{0}' uses unsupported runner '{1}'."
+
+ The tool does not support the current architecture or operating system ({0}). Supported runtimes: {1}
+ The tool does not support the current architecture or operating system ({0}). Supported runtimes: {1}
+
+ TypeType
diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/NuGetUtils.NuGet.cs b/src/Common/NuGetUtils.NuGet.cs
similarity index 100%
rename from src/Tasks/Microsoft.NET.Build.Tasks/NuGetUtils.NuGet.cs
rename to src/Common/NuGetUtils.NuGet.cs
diff --git a/src/Tasks/Common/Resources/Strings.resx b/src/Tasks/Common/Resources/Strings.resx
index c64308267967..ed582f18d773 100644
--- a/src/Tasks/Common/Resources/Strings.resx
+++ b/src/Tasks/Common/Resources/Strings.resx
@@ -987,4 +987,8 @@ You may need to build the project on another operating system or architecture, o
NETSDK1226: Prune Package data not found {0} {1} {2}. To ignore this error, set the AllowMissingPrunePackageData to true.{StrBegins="NETSDK1226: "}
+
+ NETSDK1227: Unsupported ToolCommandRunner value: {0}
+ {StrBegins="NETSDK1227: "}
+
diff --git a/src/Tasks/Common/Resources/xlf/Strings.cs.xlf b/src/Tasks/Common/Resources/xlf/Strings.cs.xlf
index 5fb24ba71bd3..2c4b932fc6e3 100644
--- a/src/Tasks/Common/Resources/xlf/Strings.cs.xlf
+++ b/src/Tasks/Common/Resources/xlf/Strings.cs.xlf
@@ -1013,6 +1013,11 @@ The following are names of parameters or literal values and should not be transl
NETSDK1139: Identifikátor cílové platformy {0} se nerozpoznal.{StrBegins="NETSDK1139: "}
+
+ NETSDK1227: Unsupported ToolCommandRunner value: {0}
+ NETSDK1227: Unsupported ToolCommandRunner value: {0}
+ {StrBegins="NETSDK1227: "}
+ NETSDK1200: If UseArtifactsPath is set to true and ArtifactsPath is not set, there must be a Directory.Build.props file in order to determine where the artifacts folder should be located.NETSDK1200: Pokud je vlastnost UseArtifactsPath nastavena na hodnotu true a parametr ArtifactsPath není nastaven, musí existovat soubor Directory.Build.props, aby bylo možné určit, kde má být složka artefaktů umístěna.
diff --git a/src/Tasks/Common/Resources/xlf/Strings.de.xlf b/src/Tasks/Common/Resources/xlf/Strings.de.xlf
index 5b6df335522b..e9a852574ba7 100644
--- a/src/Tasks/Common/Resources/xlf/Strings.de.xlf
+++ b/src/Tasks/Common/Resources/xlf/Strings.de.xlf
@@ -1013,6 +1013,11 @@ The following are names of parameters or literal values and should not be transl
NETSDK1139: Der Zielplattformbezeichner "{0}" wurde nicht erkannt.{StrBegins="NETSDK1139: "}
+
+ NETSDK1227: Unsupported ToolCommandRunner value: {0}
+ NETSDK1227: Unsupported ToolCommandRunner value: {0}
+ {StrBegins="NETSDK1227: "}
+ NETSDK1200: If UseArtifactsPath is set to true and ArtifactsPath is not set, there must be a Directory.Build.props file in order to determine where the artifacts folder should be located.NETSDK1200: Wenn UseArtifactsPath auf TRUE und ArtifactsPath nicht festgelegt ist, muss eine Directory.Build.props-Datei vorhanden sein, um zu bestimmen, wo sich der Ordner "artifacts" befinden soll.
diff --git a/src/Tasks/Common/Resources/xlf/Strings.es.xlf b/src/Tasks/Common/Resources/xlf/Strings.es.xlf
index 04e6af9d54c9..f3a0b2b31e7f 100644
--- a/src/Tasks/Common/Resources/xlf/Strings.es.xlf
+++ b/src/Tasks/Common/Resources/xlf/Strings.es.xlf
@@ -1013,6 +1013,11 @@ The following are names of parameters or literal values and should not be transl
NETSDK1139: No se reconoció el identificador de la plataforma de destino {0}.{StrBegins="NETSDK1139: "}
+
+ NETSDK1227: Unsupported ToolCommandRunner value: {0}
+ NETSDK1227: Unsupported ToolCommandRunner value: {0}
+ {StrBegins="NETSDK1227: "}
+ NETSDK1200: If UseArtifactsPath is set to true and ArtifactsPath is not set, there must be a Directory.Build.props file in order to determine where the artifacts folder should be located.NETSDK1200: Si UseArtifactsPath se establece en true y ArtifactsPath no está establecido, debe haber un archivo Directory.Build.props para determinar dónde debe ubicarse la carpeta de artefactos.
diff --git a/src/Tasks/Common/Resources/xlf/Strings.fr.xlf b/src/Tasks/Common/Resources/xlf/Strings.fr.xlf
index 97da1b1b8c67..46b9818b2d6e 100644
--- a/src/Tasks/Common/Resources/xlf/Strings.fr.xlf
+++ b/src/Tasks/Common/Resources/xlf/Strings.fr.xlf
@@ -1013,6 +1013,11 @@ The following are names of parameters or literal values and should not be transl
NETSDK1139: L'identificateur de la plateforme cible {0} n'a pas été reconnu.{StrBegins="NETSDK1139: "}
+
+ NETSDK1227: Unsupported ToolCommandRunner value: {0}
+ NETSDK1227: Unsupported ToolCommandRunner value: {0}
+ {StrBegins="NETSDK1227: "}
+ NETSDK1200: If UseArtifactsPath is set to true and ArtifactsPath is not set, there must be a Directory.Build.props file in order to determine where the artifacts folder should be located.NETSDK1200: si UseArtifactsPath est défini sur true et que le chemin de l'artefact n'est pas défini, il doit y avoir un fichier Directory.Build.props afin de déterminer l'emplacement du dossier des artefacts.
diff --git a/src/Tasks/Common/Resources/xlf/Strings.it.xlf b/src/Tasks/Common/Resources/xlf/Strings.it.xlf
index e300af1729af..9fab527c96de 100644
--- a/src/Tasks/Common/Resources/xlf/Strings.it.xlf
+++ b/src/Tasks/Common/Resources/xlf/Strings.it.xlf
@@ -1013,6 +1013,11 @@ The following are names of parameters or literal values and should not be transl
NETSDK1139: l'identificatore di piattaforma di destinazione {0} non è stato riconosciuto.{StrBegins="NETSDK1139: "}
+
+ NETSDK1227: Unsupported ToolCommandRunner value: {0}
+ NETSDK1227: Unsupported ToolCommandRunner value: {0}
+ {StrBegins="NETSDK1227: "}
+ NETSDK1200: If UseArtifactsPath is set to true and ArtifactsPath is not set, there must be a Directory.Build.props file in order to determine where the artifacts folder should be located.NETSDK1200: se UseArtifactsPath è impostato su true e ArtifactsPath non è impostato, deve essere presente un file Directory.Build.props per determinare la posizione della cartella artefatti.
diff --git a/src/Tasks/Common/Resources/xlf/Strings.ja.xlf b/src/Tasks/Common/Resources/xlf/Strings.ja.xlf
index 352d029a6a5d..74f00a75adf3 100644
--- a/src/Tasks/Common/Resources/xlf/Strings.ja.xlf
+++ b/src/Tasks/Common/Resources/xlf/Strings.ja.xlf
@@ -1013,6 +1013,11 @@ The following are names of parameters or literal values and should not be transl
NETSDK1139: ターゲット プラットフォーム識別子 {0} は認識されませんでした。{StrBegins="NETSDK1139: "}
+
+ NETSDK1227: Unsupported ToolCommandRunner value: {0}
+ NETSDK1227: Unsupported ToolCommandRunner value: {0}
+ {StrBegins="NETSDK1227: "}
+ NETSDK1200: If UseArtifactsPath is set to true and ArtifactsPath is not set, there must be a Directory.Build.props file in order to determine where the artifacts folder should be located.NETSDK1200: UseArtifactsPath が true に設定されていて ArtifactsPath が設定されていない場合は、成果物フォルダーの場所を特定するには Directory.Build.props ファイルが必要です。
diff --git a/src/Tasks/Common/Resources/xlf/Strings.ko.xlf b/src/Tasks/Common/Resources/xlf/Strings.ko.xlf
index 7da884efc812..86dc5d810815 100644
--- a/src/Tasks/Common/Resources/xlf/Strings.ko.xlf
+++ b/src/Tasks/Common/Resources/xlf/Strings.ko.xlf
@@ -1013,6 +1013,11 @@ The following are names of parameters or literal values and should not be transl
NETSDK1139: 대상 플랫폼 식별자 {0}을(를) 인식할 수 없습니다.{StrBegins="NETSDK1139: "}
+
+ NETSDK1227: Unsupported ToolCommandRunner value: {0}
+ NETSDK1227: Unsupported ToolCommandRunner value: {0}
+ {StrBegins="NETSDK1227: "}
+ NETSDK1200: If UseArtifactsPath is set to true and ArtifactsPath is not set, there must be a Directory.Build.props file in order to determine where the artifacts folder should be located.NETSDK1200: UseArtifactsPath가 true로 설정되어 있고 ArtifactsPath가 설정되지 않은 경우 아티팩트 폴더의 위치를 확인하려면 Directory.Build.props 파일이 있어야 합니다.
diff --git a/src/Tasks/Common/Resources/xlf/Strings.pl.xlf b/src/Tasks/Common/Resources/xlf/Strings.pl.xlf
index 0d941957b36b..5d30611e24f0 100644
--- a/src/Tasks/Common/Resources/xlf/Strings.pl.xlf
+++ b/src/Tasks/Common/Resources/xlf/Strings.pl.xlf
@@ -1013,6 +1013,11 @@ The following are names of parameters or literal values and should not be transl
NETSDK1139: nie rozpoznano identyfikatora platformy docelowej {0}.{StrBegins="NETSDK1139: "}
+
+ NETSDK1227: Unsupported ToolCommandRunner value: {0}
+ NETSDK1227: Unsupported ToolCommandRunner value: {0}
+ {StrBegins="NETSDK1227: "}
+ NETSDK1200: If UseArtifactsPath is set to true and ArtifactsPath is not set, there must be a Directory.Build.props file in order to determine where the artifacts folder should be located.NETSDK1200: Jeśli parametr UseArtifactsPath ma wartość true, a właściwość ArtifactsPath nie jest ustawiona, musi istnieć plik Directory.Build.props, aby określić, gdzie powinien znajdować się folder artefaktów.
diff --git a/src/Tasks/Common/Resources/xlf/Strings.pt-BR.xlf b/src/Tasks/Common/Resources/xlf/Strings.pt-BR.xlf
index 22b5e74189e5..218b6e25506e 100644
--- a/src/Tasks/Common/Resources/xlf/Strings.pt-BR.xlf
+++ b/src/Tasks/Common/Resources/xlf/Strings.pt-BR.xlf
@@ -1013,6 +1013,11 @@ The following are names of parameters or literal values and should not be transl
NETSDK1139: o identificador de plataforma de destino {0} não foi reconhecido.{StrBegins="NETSDK1139: "}
+
+ NETSDK1227: Unsupported ToolCommandRunner value: {0}
+ NETSDK1227: Unsupported ToolCommandRunner value: {0}
+ {StrBegins="NETSDK1227: "}
+ NETSDK1200: If UseArtifactsPath is set to true and ArtifactsPath is not set, there must be a Directory.Build.props file in order to determine where the artifacts folder should be located.NETSDK1200: Se UseArtifactsPath for definido como verdadeiro e Artifact Path não for definido, deve haver um arquivo Directory.Build.props para determinar onde a pasta de artefatos deve ser localizada.
diff --git a/src/Tasks/Common/Resources/xlf/Strings.ru.xlf b/src/Tasks/Common/Resources/xlf/Strings.ru.xlf
index 84621a1872ed..6816a4dcece5 100644
--- a/src/Tasks/Common/Resources/xlf/Strings.ru.xlf
+++ b/src/Tasks/Common/Resources/xlf/Strings.ru.xlf
@@ -1018,6 +1018,11 @@ The following are names of parameters or literal values and should not be transl
NETSDK1208: The target platform identifier {0} was not recognized. This is because MSBuildEnableWorkloadResolver is set to false which disables .NET SDK Workloads which is required for this identifer. Unset this environment variable or MSBuild property to enable workloads.{StrBegins="NETSDK1208: "}
+
+ NETSDK1227: Unsupported ToolCommandRunner value: {0}
+ NETSDK1227: Unsupported ToolCommandRunner value: {0}
+ {StrBegins="NETSDK1227: "}
+ NETSDK1209: The current Visual Studio version does not support targeting {0} {1}. Either target {0} {2} or lower, or use Visual Studio version {3} or higherNETSDK1209: The current Visual Studio version does not support targeting {0} {1}. Either target {0} {2} or lower, or use Visual Studio version {3} or higher
diff --git a/src/Tasks/Common/Resources/xlf/Strings.tr.xlf b/src/Tasks/Common/Resources/xlf/Strings.tr.xlf
index 78fe0194edbd..b308e87e1627 100644
--- a/src/Tasks/Common/Resources/xlf/Strings.tr.xlf
+++ b/src/Tasks/Common/Resources/xlf/Strings.tr.xlf
@@ -1013,6 +1013,11 @@ The following are names of parameters or literal values and should not be transl
NETSDK1139: {0} hedef platform tanımlayıcısı tanınmadı.{StrBegins="NETSDK1139: "}
+
+ NETSDK1227: Unsupported ToolCommandRunner value: {0}
+ NETSDK1227: Unsupported ToolCommandRunner value: {0}
+ {StrBegins="NETSDK1227: "}
+ NETSDK1200: If UseArtifactsPath is set to true and ArtifactsPath is not set, there must be a Directory.Build.props file in order to determine where the artifacts folder should be located.NETSDK1200: UseArtifactsPath true olarak ayarlanırsa ve ArtifactsPath ayarlanmazsa, yapıtlar klasörünün nerede bulunacağını belirlemek için bir Directory.Build.props dosyası olmalıdır.
diff --git a/src/Tasks/Common/Resources/xlf/Strings.zh-Hans.xlf b/src/Tasks/Common/Resources/xlf/Strings.zh-Hans.xlf
index a611d1e22382..1b631ea3798a 100644
--- a/src/Tasks/Common/Resources/xlf/Strings.zh-Hans.xlf
+++ b/src/Tasks/Common/Resources/xlf/Strings.zh-Hans.xlf
@@ -1013,6 +1013,11 @@ The following are names of parameters or literal values and should not be transl
NETSDK1139: 无法识别目标平台标识符 {0}。{StrBegins="NETSDK1139: "}
+
+ NETSDK1227: Unsupported ToolCommandRunner value: {0}
+ NETSDK1227: Unsupported ToolCommandRunner value: {0}
+ {StrBegins="NETSDK1227: "}
+ NETSDK1200: If UseArtifactsPath is set to true and ArtifactsPath is not set, there must be a Directory.Build.props file in order to determine where the artifacts folder should be located.NETSDK1200: 如果 UseArtifactsPath 设置为 true,并且未设置 ArtifactsPath,则必须具有 Directory.Build.props 文件才能确定工件文件夹的位置。
diff --git a/src/Tasks/Common/Resources/xlf/Strings.zh-Hans.xlf~RF3afe8107.TMP b/src/Tasks/Common/Resources/xlf/Strings.zh-Hans.xlf~RF3afe8107.TMP
new file mode 100644
index 000000000000..a611d1e22382
--- /dev/null
+++ b/src/Tasks/Common/Resources/xlf/Strings.zh-Hans.xlf~RF3afe8107.TMP
@@ -0,0 +1,1112 @@
+
+
+
+
+
+ NETSDK1076: AddResource can only be used with integer resource types.
+ NETSDK1076: AddResource 只能使用整数资源类型。
+ {StrBegins="NETSDK1076: "}
+
+
+ NETSDK1196: The SDK does not support ahead-of-time compilation. Set the PublishAot property to false.
+ NETSDK1196: SDK 不支持提前编译。请将 PublishAot 属性设置为 false。
+ {StrBegins="NETSDK1196: "}
+
+
+ NETSDK1204: Ahead-of-time compilation is not supported on the current platform '{0}'.
+ NETSDK1204: 当前平台“{0}”不支持提前编译。
+ {StrBegins="NETSDK1204: "}
+
+
+ NETSDK1207: Ahead-of-time compilation is not supported for the target framework.
+ NETSDK1207: 目标框架不支持提前编译。
+ {StrBegins="NETSDK1207: "}
+
+
+ NETSDK1203: Ahead-of-time compilation is not supported for the target runtime identifier '{0}'.
+ NETSDK1203: 目标运行时标识符“{0}”不支持提前编译。
+ {StrBegins="NETSDK1203: "}
+
+
+ NETSDK1070: The application configuration file must have root configuration element.
+ NETSDK1070: 应用程序配置文件必须具有根配置元素。
+ {StrBegins="NETSDK1070: "}
+
+
+ NETSDK1113: Failed to create apphost (attempt {0} out of {1}): {2}
+ NETSDK1113: 未能创建 apphost (已尝试 {0} 次,共 {1} 次): {2}
+ {StrBegins="NETSDK1113: "}
+
+
+ NETSDK1074: The application host executable will not be customized because adding resources requires that the build be performed on Windows (excluding Nano Server).
+ NETSDK1074: 未自定义应用程序主机可执行文件,因为添加资源要求在 Windows (不包括 Nano 服务器)上执行生成。
+ {StrBegins="NETSDK1074: "}
+
+
+ NETSDK1029: Unable to use '{0}' as application host executable as it does not contain the expected placeholder byte sequence '{1}' that would mark where the application name would be written.
+ NETSDK1029: 未能将“{0}”用作应用程序主机可执行文件,因为它没有必需的占位符字节序列“{1}”,该序列会标记应用程序名称的写入位置。
+ {StrBegins="NETSDK1029: "}
+
+
+ NETSDK1078: Unable to use '{0}' as application host executable because it's not a Windows PE file.
+ NETSDK1078: 无法将“{0}”用作应用程序主机可执行文件,因为它不是 Windows PE 文件。
+ {StrBegins="NETSDK1078: "}
+
+
+ NETSDK1072: Unable to use '{0}' as application host executable because it's not a Windows executable for the CUI (Console) subsystem.
+ NETSDK1072: 无法将“{0}”用作应用程序主机可执行文件,因为它不是 CUI (控制台)子系统的 Windows 可执行文件。
+ {StrBegins="NETSDK1072: "}
+
+
+ NETSDK1177: Failed to sign apphost with error code {1}: {0}
+ NETSDK1177: 无法对 Apphost 进行签名,错误代码为 {1}: {0}
+ {StrBegins="NETSDK1177: "}
+
+
+ NETSDK1199: The ArtifactsPath and UseArtifactsOutput properties cannot be set in a project file, due to MSBuild ordering constraints. They must be set in a Directory.Build.props file or from the command line. See https://aka.ms/netsdk1199 for more information.
+ NETSDK1199: 由于 MSBuild 排序约束,无法在项目文件中设置 ArtifactsPath 和 UseArtifactsOutput 属性。必须在 Directory.Build.props 文件中或通过命令行设置它们。有关详细信息,请参阅 https://aka.ms/netsdk1199。
+ {StrBegins="NETSDK1199: "}
+
+
+ NETSDK1079: The Microsoft.AspNetCore.All package is not supported when targeting .NET Core 3.0 or higher. A FrameworkReference to Microsoft.AspNetCore.App should be used instead, and will be implicitly included by Microsoft.NET.Sdk.Web.
+ NETSDK1079: 当面向 .NET Core 3.0 或更高版本时,不支持 Microsoft.AspNetCore.All 包。应改为使用 Microsoft.AspNetCore.App 的 FrameworkReference,并且 Microsoft.NET.Sdk.Web 将隐式包含它。
+ {StrBegins="NETSDK1079: "}
+
+
+ NETSDK1224: ASP.NET Core framework assets are not supported for the target framework.
+ NETSDK1224: ASP.NET Core framework assets are not supported for the target framework.
+ {StrBegins="NETSDK1224: "}
+
+
+ NETSDK1080: A PackageReference to Microsoft.AspNetCore.App is not necessary when targeting .NET Core 3.0 or higher. If Microsoft.NET.Sdk.Web is used, the shared framework will be referenced automatically. Otherwise, the PackageReference should be replaced with a FrameworkReference.
+ NETSDK1080: 当面向 .NET Core 3.0 或更高版本时,不需要 Microsoft.AspNetCore.App 的 PackageReference。如果使用 Microsoft.NET.Sdk.Web,则将自动引用共享框架。否则,应使用 FrameworkReference 替换 PackageReference。
+ {StrBegins="NETSDK1080: "}
+
+
+ NETSDK1017: Asset preprocessor must be configured before assets are processed.
+ NETSDK1017: 必须在处理资产之前配置资产预处理器。
+ {StrBegins="NETSDK1017: "}
+
+
+ NETSDK1047: Assets file '{0}' doesn't have a target for '{1}'. Ensure that restore has run and that you have included '{2}' in the TargetFrameworks for your project. You may also need to include '{3}' in your project's RuntimeIdentifiers.
+ NETSDK1047: 资产文件“{0}”没有“{1}”的目标。确保已运行还原,且“{2}”已包含在项目的 TargetFrameworks 中。可能需要在项目 RuntimeIdentifiers 中包括“{3}”。
+ {StrBegins="NETSDK1047: "}
+
+
+ NETSDK1005: Assets file '{0}' doesn't have a target for '{1}'. Ensure that restore has run and that you have included '{2}' in the TargetFrameworks for your project.
+ NETSDK1005: 资产文件“{0}”没有“{1}”的目标。确保已运行还原,且“{2}”已包含在项目的 TargetFrameworks 中。
+ {StrBegins="NETSDK1005: "}
+
+
+ NETSDK1004: Assets file '{0}' not found. Run a NuGet package restore to generate this file.
+ NETSDK1004: 找不到资产文件“{0}”。运行 NuGet 包还原以生成此文件。
+ {StrBegins="NETSDK1004: "}
+
+
+ NETSDK1063: The path to the project assets file was not set. Run a NuGet package restore to generate this file.
+ NETSDK1063: 未设置项目资产文件的路径。运行 NuGet 程序包还原以生成此文件。
+ {StrBegins="NETSDK1063: "}
+
+
+ NETSDK1006: Assets file path '{0}' is not rooted. Only full paths are supported.
+ NETSDK1006: 资产文件路径“{0}”不是根路径。仅支持完整路径。
+ {StrBegins="NETSDK1006: "}
+
+
+ NETSDK1001: At least one possible target framework must be specified.
+ NETSDK1001: 必须指定至少一个可能的目标框架。
+ {StrBegins="NETSDK1001: "}
+
+
+ NETSDK1205: The Microsoft.Net.Compilers.Toolset.Framework package should not be set directly. Set the property 'BuildWithNetFrameworkHostedCompiler' to 'true' instead if you need it.
+ NETSDK1205: 不应直接设置 Microsoft.Net.Compilers.Toolset.Framework 包。如果需要,请将属性 "BuildWithNetFrameworkHostedCompiler" 设置为 "true"。
+ {StrBegins="NETSDK1205: "}{Locked="Microsoft.Net.Compilers.Toolset.Framework"}{Locked="BuildWithNetFrameworkHostedCompiler"}
+
+
+ NETSDK1065: Cannot find app host for {0}. {0} could be an invalid runtime identifier (RID). For more information about RID, see https://aka.ms/rid-catalog.
+ NETSDK1065: 无法找到 {0} 的应用主机。{0} 可能是无效的运行时标识符(RID)。有关 RID 的详细信息,请参阅 https://aka.ms/rid-catalog。
+ {StrBegins="NETSDK1065: "}
+
+
+ NETSDK1091: Unable to find a .NET Core COM host. The .NET Core COM host is only available on .NET Core 3.0 or higher when targeting Windows.
+ NETSDK1091: 找不到 .NET Core COM 主机。仅当面向 Windows 时,.NET Core COM 主机才在 .NET Core 3.0 或更高版本上可用。
+ {StrBegins="NETSDK1091: "}
+
+
+ NETSDK1114: Unable to find a .NET Core IJW host. The .NET Core IJW host is only available on .NET Core 3.1 or higher when targeting Windows.
+ NETSDK1114: 找不到 .NET Core IJW 主机。仅当面向 Windows 时,.NET Core IJW 主机才在 .NET Core 3.1 或更高版本上可用。
+ {StrBegins="NETSDK1114: "}
+
+
+ NETSDK1007: Cannot find project info for '{0}'. This can indicate a missing project reference.
+ NETSDK1007: 找不到“{0}”的项目信息。这可以指示缺少一个项目引用。
+ {StrBegins="NETSDK1007: "}
+
+
+ NETSDK1032: The RuntimeIdentifier platform '{0}' and the PlatformTarget '{1}' must be compatible.
+ NETSDK1032: RuntimeIdentifier 平台“{0}”和 PlatformTarget“{1}”必须兼容。
+ {StrBegins="NETSDK1032: "}
+
+
+ NETSDK1031: It is not supported to build or publish a self-contained application without specifying a RuntimeIdentifier. You must either specify a RuntimeIdentifier or set SelfContained to false.
+ NETSDK1031: 不可在未指定 RuntimeIdentifier 的情况下生成或发布自包含应用程序。必须指定 RuntimeIdentifier 或将 SelfContained 设置为 false。
+ {StrBegins="NETSDK1031: "}
+
+
+ NETSDK1097: It is not supported to publish an application to a single-file without specifying a RuntimeIdentifier. You must either specify a RuntimeIdentifier or set PublishSingleFile to false.
+ NETSDK1097: 不可在未指定 RuntimeIdentifier 的情况下发布将应用程序发布到单一文件中。必须指定 RuntimeIdentifier 或将 PublishSingleFile 设置为 false。
+ {StrBegins="NETSDK1097: "}
+
+
+ NETSDK1098: Applications published to a single-file are required to use the application host. You must either set PublishSingleFile to false or set UseAppHost to true.
+ NETSDK1098: 要使用应用程序主机,需具备发布到单一文件中的应用程序。必须将 PublishSingleFile 设置为 false,或将 UseAppHost 设置为 true。
+ {StrBegins="NETSDK1098: "}
+
+
+ NETSDK1099: Publishing to a single-file is only supported for executable applications.
+ NETSDK1099: 发布到单一文件仅适用于可执行应用程序。
+ {StrBegins="NETSDK1099: "}
+
+
+ NETSDK1194: The "--output" option isn't supported when building a solution. Specifying a solution-level output path results in all projects copying outputs to the same directory, which can lead to inconsistent builds.
+ NETSDK1194: 生成解决方案时不支持 "--output" 选项。指定解决方案级输出路径会导致所有项目将输出复制到同一目录,这可能会导致生成不一致。
+ {StrBegins="NETSDK1194: "}{Locked="--output"}
+
+
+ NETSDK1134: Building a solution with a specific RuntimeIdentifier is not supported. If you would like to publish for a single RID, specify the RID at the individual project level instead.
+ NETSDK1134: 不支持使用特定 RuntimeIdentifier 生成解决方案。如果要为单个 RID 发布,请改为在单独的项目级别指定 RID。
+ {StrBegins="NETSDK1134: "}
+
+
+ NETSDK1135: SupportedOSPlatformVersion {0} cannot be higher than TargetPlatformVersion {1}.
+ NETSDK1135: SupportedOSPlatformVersion {0} 不能高于 TargetPlatformVersion {1}。
+ {StrBegins="NETSDK1135: "}
+
+
+ NETSDK1143: Including all content in a single file bundle also includes native libraries. If IncludeAllContentForSelfExtract is true, IncludeNativeLibrariesForSelfExtract must not be false.
+ NETSDK1143: 包含单个文件包中的所有内容意味着也包括本机库。如果 IncludeAllContentForSelfExtract 为 true,则 IncludeNativeLibrariesForSelfExtract 不能为 false。
+ {StrBegins="NETSDK1143: "}
+
+
+ NETSDK1142: Including symbols in a single file bundle is not supported when publishing for .NET5 or higher.
+ NETSDK1142: 针对 .NET5 或更高版本发布时,不支持在单个文件包中包括符号。
+ {StrBegins="NETSDK1142: "}
+
+
+ NETSDK1013: The TargetFramework value '{0}' was not recognized. It may be misspelled. If not, then the TargetFrameworkIdentifier and/or TargetFrameworkVersion properties must be specified explicitly.
+ NETSDK1013: 未识别 TargetFramework 值“{0}”。可能是因为拼写错误。如果拼写正确,必须显式指定 TargetFrameworkIdentifier 和/或 TargetFrameworkVersion 属性。
+ {StrBegins="NETSDK1013: "}
+
+
+ NETSDK1067: Self-contained applications are required to use the application host. Either set SelfContained to false or set UseAppHost to true.
+ NETSDK1067: 需要自包含应用程序才能使用应用程序主机。将 SelfContained 设置为 false,或者将 UseAppHost 设置为 true。
+ {StrBegins="NETSDK1067: "}
+
+
+ NETSDK1125: Publishing to a single-file is only supported for netcoreapp target.
+ NETSDK1125: 仅 netcoreapp 目标支持发布到单个文件。
+ {StrBegins="NETSDK1125: "}
+
+
+ Choosing '{0}' because AssemblyVersion '{1}' is greater than '{2}'.
+ 选择“{0}”,因为 AssemblyVersion“{1}”高于“{2}”。
+
+
+
+ Choosing '{0}' arbitrarily as both items are copy-local and have equal file and assembly versions.
+ 任意选择“{0}”,因为两个项都是本地副本且文件和程序集版本相等。
+
+
+
+ Choosing '{0}' because file version '{1}' is greater than '{2}'.
+ 选择“{0}”,因为文件版本“{1}”高于“{2}”。
+
+
+
+ Choosing '{0}' because it is a platform item.
+ 选择“{0}”,因为它是平台项。
+
+
+
+ Choosing '{0}' because it comes from a package that is preferred.
+ 选择“{0}”,因为它来自首选包。
+
+
+
+ NETSDK1089: The '{0}' and '{1}' types have the same CLSID '{2}' set in their GuidAttribute. Each COMVisible class needs to have a distinct guid for their CLSID.
+ NETSDK1089: “{0}”和“{1}”类型在其 GuidAttribute 中设置了相同的 CLSID“{2}”。每个 COMVisible 类都需要为其 CLSID 提供一个不同的 GUID。
+ {StrBegins="NETSDK1089: "}
+{0} - The first type with the conflicting guid.
+{1} - The second type with the conflicting guid.
+{2} - The guid the two types have.
+
+
+ NETSDK1088: The COMVisible class '{0}' must have a GuidAttribute with the CLSID of the class to be made visible to COM in .NET Core.
+ NETSDK1088: COMVisible 类“{0}”必须具有 GuidAttribute,该类的 CLSID 将在 .NET Core 中对 COM 可见。
+ {StrBegins="NETSDK1088: "}
+{0} - The ComVisible class that doesn't have a GuidAttribute on it.
+
+
+ NETSDK1090: The supplied assembly '{0}' is not valid. Cannot generate a CLSIDMap from it.
+ NETSDK1090: 提供的程序集“{0}”无效。无法从该程序集生成 CLSIDMap。
+ {StrBegins="NETSDK1090: "}
+{0} - The path to the invalid assembly.
+
+
+ NETSDK1167: Compression in a single file bundle is only supported when publishing for .NET6 or higher.
+ NETSDK1167: 仅支持在为 .NET6 或更高版本发布时进行单个文件包的压缩。
+ {StrBegins="NETSDK1167: "}
+
+
+ NETSDK1176: Compression in a single file bundle is only supported when publishing a self-contained application.
+ NETSDK1176: 仅在发布独立应用程序时才支持在单个文件捆绑包中进行压缩。
+ {StrBegins="NETSDK1176: "}
+
+
+ NETSDK1133: There was conflicting information about runtime packs available for {0}:
+{1}
+ NETSDK1133: 可供{0} 使用的运行时包的信息存在冲突:
+{1}
+ {StrBegins="NETSDK1133: "}
+
+
+ NETSDK1014: Content item for '{0}' sets '{1}', but does not provide '{2}' or '{3}'.
+ NETSDK1014: “{0}”的内容项设置为“{1}”,但不提供“{2}”或“{3}”。
+ {StrBegins="NETSDK1014: "}
+
+
+ NETSDK1010: The '{0}' task must be given a value for parameter '{1}' in order to consume preprocessed content.
+ NETSDK1010: 必须向“{0}”任务提供参数“{1}”的值以便使用预处理的内容。
+ {StrBegins="NETSDK1010: "}
+
+
+ Could not determine winner because '{0}' does not exist.
+ “{0}”不存在,因此无法确定优胜者。
+
+
+
+ Could not determine winner due to equal file and assembly versions.
+ 文件和程序集版本相等,因此无法确定优胜者。
+
+
+
+ Could not determine a winner because '{0}' has no file version.
+ “{0}”没有文件版本,因此无法确定优胜者。
+
+
+
+ Could not determine a winner because '{0}' is not an assembly.
+ “{0}”不是程序集,因此无法确定优胜者。
+
+
+
+ NETSDK1181: Error getting pack version: Pack '{0}' was not present in workload manifests.
+ NETSDK1181: 获取包版本时出错: 包“{0}”在工作负载清单中不存在。
+ {StrBegins="NETSDK1181: "}
+
+
+ NETSDK1042: Could not load PlatformManifest from '{0}' because it did not exist.
+ NETSDK1042: 无法从“{0}”中加载 PlatformManifest,因为它不存在。
+ {StrBegins="NETSDK1042: "}
+
+
+ NETSDK1120: C++/CLI projects targeting .NET Core require a target framework of at least 'netcoreapp3.1'.
+ NETSDK1120: 面向 .NET Core 的 C++/CLI 项目要求目标框架至少为 "netcoreapp 3.1"。
+ {StrBegins="NETSDK1120: "}
+
+
+ NETSDK1158: Required '{0}' metadata missing on Crossgen2Tool item.
+ NETSDK1158: Crossgen2Tool 项上缺少必需的“{0}”元数据。
+ {StrBegins="NETSDK1158: "}
+
+
+ NETSDK1126: Publishing ReadyToRun using Crossgen2 is only supported for self-contained applications.
+ NETSDK1126: 仅独立式应用程序支持使用 Crossgen2 发布 ReadyToRun。
+ {StrBegins="NETSDK1126: "}
+
+
+ NETSDK1155: Crossgen2Tool executable '{0}' not found.
+ NETSDK1155: 找不到 Crossgen2Tool 可执行文件“{0}”。
+ {StrBegins="NETSDK1155: "}
+
+
+ NETSDK1154: Crossgen2Tool must be specified when UseCrossgen2 is set to true.
+ NETSDK1154: 当 UseCrossgen2 设置为 true 时,必须指定 Crossgen2Tool。
+ {StrBegins="NETSDK1154: "}
+
+
+ NETSDK1166: Cannot emit symbols when publishing for .NET 5 with Crossgen2 using composite mode.
+ NETSDK1166: 使用复合模式针对具有 Crossgen2 的 .NET 5 发布时,无法发出符号。
+ {StrBegins="NETSDK1166: "}
+
+
+ NETSDK1160: CrossgenTool executable '{0}' not found.
+ NETSDK1160: 找不到 CrossgenTool 可执行文件“{0}”。
+ {StrBegins="NETSDK1160: "}
+
+
+ NETSDK1153: CrossgenTool not specified in PDB compilation mode.
+ NETSDK1153: 在 PDB 编译模式下未指定 CrossgenTool。
+ {StrBegins="NETSDK1153: "}
+
+
+ NETSDK1159: CrossgenTool must be specified when UseCrossgen2 is set to false.
+ NETSDK1159: UseCrossgen2 设置为 false 时,必须指定 CrossgenTool。
+ {StrBegins="NETSDK1159: "}
+
+
+ NETSDK1161: DiaSymReader library '{0}' not found.
+ NETSDK1161: 未找到 DiaSymReader 库“{0}”。
+ {StrBegins="NETSDK1161: "}
+
+
+ NETSDK1156: .NET host executable '{0}' not found.
+ NETSDK1156: 找不到 .NET 主机可执行文件“{0}”。
+ {StrBegins="NETSDK1156: "}
+
+
+ NETSDK1055: DotnetTool does not support target framework lower than netcoreapp2.1.
+ NETSDK1055: DotnetTool 不支持版本低于 netcoreapp2.1 的目标框架。
+ {StrBegins="NETSDK1055: "}
+
+
+ NETSDK1054: only supports .NET Core.
+ NETSDK1054: 仅支持 .NET Core。
+ {StrBegins="NETSDK1054: "}
+
+
+ NETSDK1022: Duplicate '{0}' items were included. The .NET SDK includes '{0}' items from your project directory by default. You can either remove these items from your project file, or set the '{1}' property to '{2}' if you want to explicitly include them in your project file. For more information, see {4}. The duplicate items were: {3}
+ NETSDK1022: 包含了重复的“{0}”项。.NET SDK 默认包含你项目目录中的“{0}”项。可从项目文件中删除这些项;如果希望将其显式包含在项目文件中,可将“{1}”属性设置为“{2}”。有关详细信息,请参阅 {4}。重复项为: {3}
+ {StrBegins="NETSDK1022: "}
+
+
+ NETSDK1015: The preprocessor token '{0}' has been given more than one value. Choosing '{1}' as the value.
+ NETSDK1015: 已向预处理器标记“{0}”提供多个值。选择“{1}”作为值。
+ {StrBegins="NETSDK1015: "}
+
+
+ NETSDK1152: Found multiple publish output files with the same relative path: {0}.
+ NETSDK1152: 找到了多个具有相同相对路径的发布输出文件: {0}。
+ {StrBegins="NETSDK1152: "}
+
+
+ NETSDK1110: More than one asset in the runtime pack has the same destination sub-path of '{0}'. Report this error to the .NET team here: https://aka.ms/dotnet-sdk-issue.
+ NETSDK1110: 运行时包中的多个资产具有“{0}”的相同目标子路径。请在此处将此错误报告给 .NET 团队: https://aka.ms/dotnet-sdk-issue。
+ {StrBegins="NETSDK1110: "}
+
+
+ NETSDK1169: The same resource ID {0} was specified for two type libraries '{1}' and '{2}'. Duplicate type library IDs are not allowed.
+ NETSDK1169: 为两个类型库“{1}”和“{2}”指定了相同的资源 ID {0}。不允许使用重复的类型库 ID。
+ {StrBegins="NETSDK1169: "}
+
+
+ NETSDK1211: EnableSingleFileAnalyzer is not supported for the target framework. Consider multi-targeting to a supported framework to enable single-file analysis, and set EnableSingleFileAnalyzer only for the supported frameworks. For example:
+<EnableSingleFileAnalyzer Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', '{0}'))">true</EnableSingleFileAnalyzer>
+ NETSDK1211: 目标框架不支持 EnableSingleFileAnalyzer。请考虑对受支持的框架进行多目标设定来启用单文件分析,并且仅为受支持的框架设置 EnableSingleFileAnalyzer。例如:
+<EnableSingleFileAnalyzer Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', '{0}'))">true</EnableSingleFileAnalyzer>
+ {StrBegins="NETSDK1211: "}
+
+
+ Encountered conflict between '{0}' and '{1}'.
+ “{0}”和“{1}”之间存在冲突。
+
+
+
+ NETSDK1051: Error parsing FrameworkList from '{0}'. {1} '{2}' was invalid.
+ NETSDK1051: 分析“{0}”中的 FrameworkList 时出错。{1}“{2}”无效。
+ {StrBegins="NETSDK1051: "}
+
+
+ NETSDK1043: Error parsing PlatformManifest from '{0}' line {1}. Lines must have the format {2}.
+ NETSDK1043: 从“{0}”第 {1} 行处分析 PlatformManifest 时出错。行的格式必须为 {2}。
+ {StrBegins="NETSDK1043: "}
+
+
+ NETSDK1044: Error parsing PlatformManifest from '{0}' line {1}. {2} '{3}' was invalid.
+ NETSDK1044: 从“{0}”第 {1} 行处分析 PlatformManifest 时出错。{2} “{3}”无效。
+ {StrBegins="NETSDK1044: "}
+
+
+ NETSDK1060: Error reading assets file: {0}
+ NETSDK1060: 读取资产文件时出错: {0}
+ {StrBegins="NETSDK1060: "}
+
+
+ NETSDK1111: Failed to delete output apphost: {0}
+ NETSDK1111: 未能删除输出 apphost: {0}
+ {StrBegins="NETSDK1111: "}
+
+
+ NETSDK1077: Failed to lock resource.
+ NETSDK1077: 无法锁定资源。
+ {StrBegins="NETSDK1077: "}
+
+
+ NETSDK1030: Given file name '{0}' is longer than 1024 bytes
+ NETSDK1030: 给定文件名“{0}”的长度超过 1024 个字节
+ {StrBegins="NETSDK1030: "}
+
+
+ NETSDK1024: Folder '{0}' already exists either delete it or provide a different ComposeWorkingDir
+ NETSDK1024: 文件夹“{0}”已存在,请将其删除或提供不同的 ComposeWorkingDir
+ {StrBegins="NETSDK1024: "}
+
+
+ NETSDK1068: The framework-dependent application host requires a target framework of at least 'netcoreapp2.1'.
+ NETSDK1068: 框架依赖型应用程序主机需要一个至少 “netcoreapp2.1” 的目标框架。
+ {StrBegins="NETSDK1068: "}
+
+
+ NETSDK1052: Framework list file path '{0}' is not rooted. Only full paths are supported.
+ NETSDK1052: 框架列表路径“{0}”不是根路径。仅支持完整路径。
+ {StrBegins="NETSDK1052: "}
+
+
+ NETSDK1087: Multiple FrameworkReference items for '{0}' were included in the project.
+ NETSDK1087: 项目中包含“{0}”的多个 FrameworkReference 项。
+ {StrBegins="NETSDK1087: "}
+
+
+ NETSDK1086: A FrameworkReference for '{0}' was included in the project. This is implicitly referenced by the .NET SDK and you do not typically need to reference it from your project. For more information, see {1}
+ NETSDK1086: 项目中包含了“{0}”的 FrameworkReference。它由 .NET SDK 隐式引用,且通常情况下无需从项目中对其进行引用。有关详细信息,请参阅 {1}
+ {StrBegins="NETSDK1086: "}
+
+
+ NETSDK1049: Resolved file has a bad image, no metadata, or is otherwise inaccessible. {0} {1}
+ NETSDK1049: 解析的文件包含错误图像、无元数据或不可访问。{0} {1}
+ {StrBegins="NETSDK1049: "}
+
+
+ NETSDK1141: Unable to resolve the .NET SDK version as specified in the global.json located at {0}.
+ NETSDK1141: 无法解析位于 {0} 的 global.json 中指定的 .NET SDK 版本。
+ {StrBegins="NETSDK1141: "}
+
+
+ NETSDK1144: Optimizing assemblies for size failed.
+ NETSDK1144: 优化程序集大小失败。
+ {StrBegins="NETSDK1144: "}
+
+
+ NETSDK1195: Trimming, or code compatibility analysis for trimming, single-file deployment, or ahead-of-time compilation is not supported for the target framework. For more information, see https://aka.ms/netsdk1195
+ NETSDK1195: 目标框架不支持剪裁、单文件部署或提前编译的剪裁或代码兼容性分析。有关详细信息,请参阅 https://aka.ms/netsdk1195
+ {StrBegins="NETSDK1195: "}
+
+
+ NETSDK1102: Optimizing assemblies for size is not supported for the selected publish configuration. Please ensure that you are publishing a self-contained app.
+ NETSDK1102: 所选发布配置不支持优化程序集的大小。请确保你发布的是独立应用。
+ {StrBegins="NETSDK1102: "}
+
+
+ Optimizing assemblies for size may change the behavior of the app. Be sure to test after publishing. See: https://aka.ms/dotnet-illink
+ 优化程序集以调整大小可能会更改应用的行为。请务必在发布后进行测试。请参阅: https://aka.ms/dotnet-illink
+
+
+
+ Optimizing assemblies for size. This process might take a while.
+ 正在优化程序集以调整大小。此过程可能需要一段时间。
+
+
+
+ NETSDK1191: A runtime identifier for the property '{0}' couldn't be inferred. Specify a rid explicitly.
+ NETSDK1191: 无法推断属性“{0}”的运行时标识符。显式指定 rid。
+ {StrBegins="NETSDK1191: "}
+
+
+ NETSDK1020: Package Root {0} was incorrectly given for Resolved library {1}
+ NETSDK1020: 对于“已解析”库 {1},包根目录 {0} 分配错误
+ {StrBegins="NETSDK1020: "}
+
+
+ NETSDK1025: The target manifest {0} provided is of not the correct format
+ NETSDK1025: 提供的目标清单 {0} 的格式不正确
+ {StrBegins="NETSDK1025: "}
+
+
+ NETSDK1163: Input assembly '{0}' not found.
+ NETSDK1163: 找不到输入程序集“{0}”。
+ {StrBegins="NETSDK1163: "}
+
+
+ NETSDK1217: Invalid value in AppHostDotNetSearch: '{0}'.
+ NETSDK1217: AppHostDotNetSearch 中的值无效: "{0}"。
+ {StrBegins="NETSDK1217: "}
+
+
+ NETSDK1003: Invalid framework name: '{0}'.
+ NETSDK1003: 无效的框架名称:“{0}”。
+ {StrBegins="NETSDK1003: "}
+
+
+ NETSDK1058: Invalid value for ItemSpecToUse parameter: '{0}'. This property must be blank or set to 'Left' or 'Right'
+ NETSDK1058: 无效的 ItemSpecToUse 参数值:“{0}”。此属性必须为空或设为“左”或“右”
+ {StrBegins="NETSDK1058: "}
+The following are names of parameters or literal values and should not be translated: ItemSpecToUse, Left, Right
+
+
+ NETSDK1018: Invalid NuGet version string: '{0}'.
+ NETSDK1018: 无效的 NuGet 版本字符串:“{0}”。
+ {StrBegins="NETSDK1018: "}
+
+
+ NETSDK1075: Update handle is invalid. This instance may not be used for further updates.
+ NETSDK1075: 更新句柄无效。此实例不能用于进一步更新。
+ {StrBegins="NETSDK1075: "}
+
+
+ NETSDK1104: RollForward value '{0}' is invalid. Allowed values are {1}.
+ NETSDK1104: RollForward 值“{0}”无效。允许的值为 {1}。
+ {StrBegins="NETSDK1104: "}
+
+
+ NETSDK1140: {0} is not a valid TargetPlatformVersion for {1}. Valid versions include:
+{2}
+ NETSDK1140: {0} 不是 {1} 的有效的 TargetPlatformVersion。有效版本包括:
+{2}
+ {StrBegins="NETSDK1140: "}
+
+
+ NETSDK1173: The provided type library '{0}' is in an invalid format.
+ NETSDK1173: 提供的类型库“{0}”的格式无效。
+ {StrBegins="NETSDK1173: "}
+
+
+ NETSDK1170: The provided type library ID '{0}' for type library '{1}' is invalid. The ID must be a positive integer less than 65536.
+ NETSDK1170: 为类型库“{1}”提供的类型库 ID“{0}”无效。该 ID 必须是小于 65536 的正整数。
+ {StrBegins="NETSDK1170: "}
+
+
+ NETSDK1210: IsAotCompatible and EnableAotAnalyzer are not supported for the target framework. Consider multi-targeting to a supported framework to enable ahead-of-time compilation analysis, and set IsAotCompatible only for the supported frameworks. For example:
+<IsAotCompatible Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', '{0}'))">true</IsAotCompatible>
+ NETSDK1210: 目标框架不支持 IsAotCompatible 和 EnableAotAnalyzer。请考虑对受支持的框架进行多目标设定来启用提前编译分析,并且仅为受支持的框架设置 IsAotCompatible。例如:
+<IsAotCompatible Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', '{0}'))">true</IsAotCompatible>
+ {StrBegins="NETSDK1210: "}
+
+
+ NETSDK1212: IsTrimmable and EnableTrimAnalyzer are not supported for the target framework. Consider multi-targeting to a supported framework to enable trimming, and set IsTrimmable only for the supported frameworks. For example:
+<IsTrimmable Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', '{0}'))">true</IsTrimmable>
+ NETSDK1212: 目标框架不支持 IsTrimmable 和 EnableTrimAnalyzer。请考虑对受支持的框架进行多目标设定以启用剪裁,并且仅为受支持的框架设置 IsTrimmable。例如:
+<IsTrimmable Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', '{0}'))">true</IsTrimmable>
+ {StrBegins="NETSDK1212: "}
+
+
+ NETSDK1157: JIT library '{0}' not found.
+ NETSDK1157: 找不到 JIT 库“{0}”。
+ {StrBegins="NETSDK1157: "}
+
+
+ NETSDK1216: Package Microsoft.Net.Sdk.Compilers.Toolset is not downloaded but it is needed because your MSBuild and SDK versions are mismatched. Ensure version {0} of the package is available in your NuGet source feeds and then run NuGet package restore from Visual Studio or MSBuild.
+ NETSDK1216: 包 Microsoft.Net.Sdk.Compilers.Toolset 不可下载,但由于你的 MSBuild 和 SDK 版本不匹配,因此需要此包。确保包的版本 {0} 在你的 NuGet 源中可用,然后从 Visual Studio 或 MSBuild 运行 NuGet 包还原。
+ {StrBegins="NETSDK1216: "}{Locked="Microsoft.Net.Sdk.Compilers.Toolset"} {0} is a NuGet package version and should not be translated.
+
+
+ NETSDK1221: NuGetPackageRoot property is empty so package Microsoft.Net.Sdk.Compilers.Toolset cannot be used but it is recommended because your MSBuild and SDK versions are mismatched. Ensure you are building with '/restore /t:Build' and not '/t:Restore;Build'.
+ NETSDK1221: NuGetPackageRoot 属性为空,因此无法使用包 Microsoft.Net.Sdk.Compilers.Toolset,但建议使用它,因为你的 MSBuild 和 SDK 版本不匹配。确保使用 '/restore /t:Build' 而不是 '/t:Restore;Build' 进行生成。
+ {StrBegins="NETSDK1221: "}{Locked="NuGetPackageRoot"}{Locked="Microsoft.Net.Sdk.Compilers.Toolset"}{Locked="'/restore /t:Build'"}{Locked="'/t:Restore;Build'"}
+
+
+ NETSDK1061: The project was restored using {0} version {1}, but with current settings, version {2} would be used instead. To resolve this issue, make sure the same settings are used for restore and for subsequent operations such as build or publish. Typically this issue can occur if the RuntimeIdentifier property is set during build or publish but not during restore. For more information, see https://aka.ms/dotnet-runtime-patch-selection.
+ NETSDK1061: 项目是使用 {0} 版本 {1} 还原的, 但使用当前设置, 将改用版本 {2}。要解决此问题, 请确保将相同的设置用于还原和后续操作 (如生成或发布)。通常, 如果 RuntimeIdentifier 属性是在生成或发布过程中设置的, 而不是在还原过程中进行的, 则会发生此问题。有关详细信息, 请参阅 https://aka.ms/dotnet-runtime-patch-selection。
+ {StrBegins="NETSDK1061: "}
+{0} - Package Identifier for platform package
+{1} - Restored version of platform package
+{2} - Current version of platform package
+
+
+ NETSDK1008: Missing '{0}' metadata on '{1}' item '{2}'.
+ NETSDK1008: 在“{1}”项“{2}”上缺少“{0}”元数据。
+ {StrBegins="NETSDK1008: "}
+
+
+ NETSDK1164: Missing output PDB path in PDB generation mode (OutputPDBImage metadata).
+ NETSDK1164: PDB 生成模式下缺少输出 PDB 路径(OutputPDBImage 元数据)。
+ {StrBegins="NETSDK1164: "}
+
+
+ NETSDK1165: Missing output R2R image path (OutputR2RImage metadata).
+ NETSDK1165: 缺少输出 R2R 映像路径(OutputR2RImage 元数据)。
+ {StrBegins="NETSDK1165: "}
+
+
+ NETSDK1171: An integer ID less than 65536 must be provided for type library '{0}' because more than one type library is specified.
+ NETSDK1171: 必须为类型库“{0}”提供小于 65536 的整数 ID,因为指定了多个类型库。
+ {StrBegins="NETSDK1171: "}
+
+
+ NETSDK1021: More than one file found for {0}
+ NETSDK1021: 找到 {0} 的多个文件
+ {StrBegins="NETSDK1021: "}
+
+
+ NETSDK1069: This project uses a library that targets .NET Standard 1.5 or higher, and the project targets a version of .NET Framework that doesn't have built-in support for that version of .NET Standard. Visit https://aka.ms/net-standard-known-issues for a set of known issues. Consider retargeting to .NET Framework 4.7.2.
+ NETSDK1069: 此项目使用了一个面向 .NET Standard 1.5 或更高版本的库,且此项目面向一个没有对该版本的 .NET Standard 的内置支持的 .NET Framework 版本。请访问 https://aka.ms/net-standard-known-issues 了解一些已知问题。考虑重定向到 .NET Framework 4.7.2。
+ {StrBegins="NETSDK1069: "}
+
+
+ NETSDK1115: The current .NET SDK does not support .NET Framework without using .NET SDK Defaults. It is likely due to a mismatch between C++/CLI project CLRSupport property and TargetFramework.
+ NETSDK1115: 未使用 .NET SDK 默认设置的情况下,当前 .NET SDK 不支持 .NET Framework。很可能是因为 C++/CLI 项目的 CLRSupport 属性和 TargetFramework 之间存在不匹配情况。
+ {StrBegins="NETSDK1115: "}
+
+
+ NETSDK1225: Native compilation is not supported when invoking the Publish target directly. Try running dotnet publish.
+ NETSDK1225: Native compilation is not supported when invoking the Publish target directly. Try running dotnet publish.
+ {StrBegins="NETSDK1225: "}
+
+
+ NETSDK1223: Targeting .NET 9.0 or higher in Visual Studio 2022 17.11 is not supported.
+ NETSDK1223: 不支持在 Visual Studio 2022 17.11 中以 .NET 9.0 或更高版本为目标。
+ {StrBegins="NETSDK1223: "}
+
+
+ NETSDK1084: There is no application host available for the specified RuntimeIdentifier '{0}'.
+ NETSDK1084: 没有应用程序主机可用于指定的 RuntimeIdentifier“{0}”。
+ {StrBegins="NETSDK1084: "}
+
+
+ NETSDK1085: The 'NoBuild' property was set to true but the 'Build' target was invoked.
+ NETSDK1085: "NoBuild" 属性已设置为 true,但调用了 "Build" 目标。
+ {StrBegins="NETSDK1085: "}
+
+
+ NETSDK1002: Project '{0}' targets '{2}'. It cannot be referenced by a project that targets '{1}'.
+ NETSDK1002: 项目“{0}”以“{2}”为目标。它不可由面向“{1}”的项目引用。
+ {StrBegins="NETSDK1002: "}
+
+
+ NETSDK1082: There was no runtime pack for {0} available for the specified RuntimeIdentifier '{1}'.
+ NETSDK1082: {0} 没有运行时包可用于指定的 RuntimeIdentifier“{1}”。
+ {StrBegins="NETSDK1082: "}
+
+
+ NETSDK1132: No runtime pack information was available for {0}.
+ NETSDK1132: 没有可用于 {0} 的运行时包信息。
+ {StrBegins="NETSDK1132: "}
+
+
+ NETSDK1128: COM hosting does not support self-contained deployments.
+ NETSDK1128: COM 托管不支持自包含的部署。
+ {StrBegins="NETSDK1128: "}
+
+
+ NETSDK1119: C++/CLI projects targeting .NET Core cannot use EnableComHosting=true.
+ NETSDK1119: 面向 .NET Core 的 C++/CLI 项目不能使用 EnableComHosting=true。
+ {StrBegins="NETSDK1119: "}
+
+
+ NETSDK1116: C++/CLI projects targeting .NET Core must be dynamic libraries.
+ NETSDK1116: 面向 .NET Core 的 C++/CLI 项目必须是动态库。
+ {StrBegins="NETSDK1116: "}
+
+
+ NETSDK1118: C++/CLI projects targeting .NET Core cannot be packed.
+ NETSDK1118: 无法打包面向 .NET Core 的 C++/CLI 项目。
+ {StrBegins="NETSDK1118: "}
+
+
+ NETSDK1117: Does not support publish of C++/CLI project targeting dotnet core.
+ NETSDK1117: 不支持面向 dotnet core 的 C++/CLI 项目发布。
+ {StrBegins="NETSDK1117: "}
+
+
+ NETSDK1121: C++/CLI projects targeting .NET Core cannot use SelfContained=true.
+ NETSDK1121: 面向 .NET Core 的 C++/CLI 项目不能使用 SelfContained=true。
+ {StrBegins="NETSDK1121: "}
+
+
+ NETSDK1206: Found version-specific or distribution-specific runtime identifier(s): {0}. Affected libraries: {1}. In .NET 8.0 and higher, assets for version-specific and distribution-specific runtime identifiers will not be found by default. See https://aka.ms/dotnet/rid-usage for details.
+ NETSDK1206: 找到了特定于版本或特定于发行版的运行时标识符: {0}。受影响的库: {1}。在 .NET 8.0 及更高版本中,默认情况下找不到特定于版本和特定于发行版的运行时标识符的资产。有关详细信息,请参阅 https://aka.ms/dotnet/rid-usage。
+ {StrBegins="NETSDK1206: "}
+
+
+ NETSDK1151: The referenced project '{0}' is a self-contained executable. A self-contained executable cannot be referenced by a non self-contained executable. For more information, see https://aka.ms/netsdk1151
+ NETSDK1151: 引用的项目“{0}”是自包含的可执行文件。自包含可执行文件不能由非自包含可执行文件引用。如需获取更多信息,请访问 https://aka.ms/netsdk1151
+ {StrBegins="NETSDK1151: "}
+
+
+ NETSDK1162: PDB generation: R2R executable '{0}' not found.
+ NETSDK1162: PDB 生成: 未找到 R2R 可执行文件“{0}”。
+ {StrBegins="NETSDK1162: "}
+
+
+ NETSDK1053: Pack as tool does not support self contained.
+ NETSDK1053: 打包为工具不支持自包含。
+ {StrBegins="NETSDK1053: "}
+
+
+ NETSDK1146: PackAsTool does not support TargetPlatformIdentifier being set. For example, TargetFramework cannot be net5.0-windows, only net5.0. PackAsTool also does not support UseWPF or UseWindowsForms when targeting .NET 5 and higher.
+ NETSDK1146: PackAsTool 不支持正在设置的 TargetPlatformIdentifier。例如,TargetFramework 不能是 net5.0-windows,只能是 net5.0。面向 .NET 5 及以上版本时,PackAsTool 也不支持 UseWPF 或 UseWindowsForms。
+ {StrBegins="NETSDK1146: "}
+
+
+ NETSDK1187: Package {0} {1} has a resource with the locale '{2}'. This locale has been normalized to the standard format '{3}' to prevent casing issues in the build. Consider notifying the package author about this casing issue.
+ NETSDK1187: 包 {0} {1} 具有具有区域设置'{2}'的资源。此区域设置已规范化为标准格式'{3}'以防止生成中出现大小写问题。请考虑就此大小写问题通知包作者。
+ {StrBegins="NETSDK1187: "} 0 is a package name, 1 is a package version, 2 is the incorrect locale string, and 3 is the correct locale string.
+
+
+ NETSDK1188: Package {0} {1} has a resource with the locale '{2}'. This locale is not recognized by .NET. Consider notifying the package author that it appears to be using an invalid locale.
+ NETSDK1188: 包 {0} {1} 具有具有区域设置'{2}'的资源。.NET 无法识别此区域设置。请考虑通知包作者它似乎正在使用无效的区域设置。
+ {StrBegins="NETSDK1188: "} 0 is a package name, 1 is a package version, and 2 is the incorrect locale string
+
+
+ NETSDK1064: Package {0}, version {1} was not found. It might have been deleted since NuGet restore. Otherwise, NuGet restore might have only partially completed, which might have been due to maximum path length restrictions.
+ NETSDK1064: 未找到版本为 {1} 的包 {0}。它可能已在 NuGet 还原后删除。否则,NuGet 还原可能只是部分完成,这种情况可能是最大路径长度限制所导致。
+ {StrBegins="NETSDK1064: "}
+
+
+ NETSDK1023: A PackageReference for '{0}' was included in your project. This package is implicitly referenced by the .NET SDK and you do not typically need to reference it from your project. For more information, see {1}
+ NETSDK1023: 项目中包含了“{0}”的 PackageReference。此包由 .NET SDK 隐式引用,且通常情况下你无需从项目中对其进行引用。有关详细信息,请参阅 {1}
+ {StrBegins="NETSDK1023: "}
+
+
+ NETSDK1071: A PackageReference to '{0}' specified a Version of `{1}`. Specifying the version of this package is not recommended. For more information, see https://aka.ms/sdkimplicitrefs
+ NETSDK1071: “{0}”的 PackageReference 指定了版本“{1}”。不建议指定此包的版本。有关详细信息,请查看 https://aka.ms/sdkimplicitrefs
+ {StrBegins="NETSDK1071: "}
+
+
+ NETSDK1174: Placeholder
+ NETSDK1174: 占位符
+ {StrBegins="NETSDK1174: "} - This string is not used here, but is a placeholder for the error code, which is used by the "dotnet run" command.
+
+
+ NETSDK1189: Prefer32Bit is not supported and has no effect for netcoreapp target.
+ NETSDK1189: Prefer32Bit 不受支持,对 netcoreapp 目标无效。
+ {StrBegins="NETSDK1189: "}
+
+
+ NETSDK1222: PreferNativeArm64 applies only to .NET Framework targets. It is not supported and has no effect for when targeting .NET Core.
+ NETSDK1222: PreferNativeArm64 仅适用于 .NET Framework 目标。它不受支持,并且在以 .NET Core 为目标时不起作用。
+ {StrBegins="NETSDK1222: "}
+
+
+ NETSDK1011: Assets are consumed from project '{0}', but no corresponding MSBuild project path was found in '{1}'.
+ NETSDK1011: 从项目“{0}”消耗资产,但在“{1}”中找不到相应的 MSBuild 项目路径。
+ {StrBegins="NETSDK1011: "}
+
+
+ NETSDK1059: The tool '{0}' is now included in the .NET SDK. Information on resolving this warning is available at (https://aka.ms/dotnetclitools-in-box).
+ NETSDK1059: .NET SDK 中现已包含工具“{0}”。要了解如何处理此警告,可查看 (https://aka.ms/dotnetclitools-in-box)。
+ {StrBegins="NETSDK1059: "}
+
+
+ NETSDK1093: Project tools (DotnetCliTool) only support targeting .NET Core 2.2 and lower.
+ NETSDK1093: NETSDK1093: 项目工具(DotnetCliTool)仅支持面向 .NET Core 2.2 及更低版本。
+ {StrBegins="NETSDK1093: "}
+
+
+ NETSDK1226: Prune Package data not found {0} {1} {2}. To ignore this error, set the AllowMissingPrunePackageData to true.
+ NETSDK1226: Prune Package data not found {0} {1} {2}. To ignore this error, set the AllowMissingPrunePackageData to true.
+ {StrBegins="NETSDK1226: "}
+
+
+ NETSDK1198: A publish profile with the name '{0}' was not found in the project. Set the PublishProfile property to a valid file name.
+ NETSDK1198: 在项目中找不到名为“{0}”的发布配置文件。请将 PublishProfile 属性设置为有效的文件名。
+ {StrBegins="NETSDK1198: "}
+
+
+ NETSDK1122: ReadyToRun compilation will be skipped because it is only supported for .NET Core 3.0 or higher.
+ NETSDK1122: 将跳过 ReadyToRun 编译,因为只有 .NET Core 3.0 或更高版本才支持该编译。
+ {StrBegins="NETSDK1122: "}
+
+
+ NETSDK1193: If PublishSelfContained is set, it must be either true or false. The value given was '{0}'.
+ NETSDK1193: 如果已设置 PublishSelfContained,则它必须为 true 或 false。给定的值为“{0}”。
+ {StrBegins="NETSDK1193: "}
+
+
+ NETSDK1123: Publishing an application to a single-file requires .NET Core 3.0 or higher.
+ NETSDK1123: 将应用程序发布到单个文件需要 .NET Core 3.0 或更高版本。
+ {StrBegins="NETSDK1123: "}
+
+
+ NETSDK1124: Trimming assemblies requires .NET Core 3.0 or higher.
+ NETSDK1124: 修整程序集需要 .NET Core 3.0 或更高版本。
+ {StrBegins="NETSDK1124: "}
+
+
+ NETSDK1129: The 'Publish' target is not supported without specifying a target framework. The current project targets multiple frameworks, you must specify one of the following frameworks in order to publish: {0}
+ NETSDK1129: 如果未指定目标框架,则不支持 "Publish" 目标。当前项目面向多个框架,因此必须指定下面的一个框架来进行发布: {0}
+ {StrBegins="NETSDK1129: "}
+
+
+ NETSDK1096: Optimizing assemblies for performance failed. You can either exclude the failing assemblies from being optimized, or set the PublishReadyToRun property to false.
+ NETSDK1096: 程序集性能优化失败。可将失败的程序集排除在优化操作之外,或者将 PublishReadyToRun 属性设置为 false。
+ {StrBegins="NETSDK1096: "}
+
+
+ Some ReadyToRun compilations emitted warnings, indicating potential missing dependencies. Missing dependencies could potentially cause runtime failures. To show the warnings, set the PublishReadyToRunShowWarnings property to true.
+ 一些 ReadyToRun 编译发出警告,指出可能缺少依赖项。缺少的依赖项可能导致运行时失败。要显示警告,请将 PublishReadyToRunShowWarnings 属性设置为 true。
+
+
+
+ NETSDK1094: Unable to optimize assemblies for performance: a valid runtime package was not found. Either set the PublishReadyToRun property to false, or use a supported runtime identifier when publishing. When targeting .NET 6 or higher, make sure to restore packages with the PublishReadyToRun property set to true.
+ NETSDK1094: 无法优化程序集以改进性能: 找不到有效的运行时包。将 PublishReadyToRun 属性设置为 false,或在发布时使用支持的运行时标识符。面向 .NET 6 或更高版本时,请确保还原将 PublishReadyToRun 属性设置为 true 的包。
+ {StrBegins="NETSDK1094: "}
+
+
+ NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Please verify you are using a supported runtime identifier, or set the PublishReadyToRun property to false.
+ NETSDK1095: 所选目标平台或体系结构不支持优化程序集的性能。请验证确保你在使用受支持的运行时标识符,或者将 PublishReadyToRun 属性设置为 false。
+ {StrBegins="NETSDK1095: "}
+
+
+ NETSDK1103: RollForward setting is only supported on .NET Core 3.0 or higher.
+ NETSDK1103: RollForward 设置仅在 .NET Core 3.0 或更高版本上受支持。
+ {StrBegins="NETSDK1103: "}
+
+
+ NETSDK1083: The specified RuntimeIdentifier '{0}' is not recognized. See https://aka.ms/netsdk1083 for more information.
+ NETSDK1083: 无法识别指定的 RuntimeIdentifier“{0}”。有关详细信息,请参阅 https://aka.ms/netsdk1083。
+ {StrBegins="NETSDK1083: "}
+
+
+ NETSDK1028: Specify a RuntimeIdentifier
+ NETSDK1028: 指定一个 RuntimeIdentifier
+ {StrBegins="NETSDK1028: "}
+
+
+ NETSDK1201: For projects targeting .NET 8.0 and higher, specifying a RuntimeIdentifier will no longer produce a self contained app by default. To continue building self-contained apps, set the SelfContained property to true or use the --self-contained argument.
+ NETSDK1201: 对于面向 .NET 8.0 及更高版本的项目,默认情况下,指定 RuntimeIdentifier 将不再生成自包含应用。若要继续生成自包含应用,请将 SelfContained 属性设置为 true,或者使用 --self-contained 参数。
+ {StrBegins="NETSDK1201: "}
+
+
+ NETSDK1109: Runtime list file '{0}' was not found. Report this error to the .NET team here: https://aka.ms/dotnet-sdk-issue.
+ NETSDK1109: 找不到运行时列表文件“{0}”。请在此处将此错误报告给 .NET 团队: https://aka.ms/dotnet-sdk-issue。
+ {StrBegins="NETSDK1109: "}
+
+
+ NETSDK1112: The runtime pack for {0} was not downloaded. Try running a NuGet restore with the RuntimeIdentifier '{1}'.
+ NETSDK1112: 未下载 {0} 的运行时包。请尝试使用 RuntimeIdentifier“{1}”运行 NuGet 还原。
+ {StrBegins="NETSDK1112: "}
+
+
+ NETSDK1185: The Runtime Pack for FrameworkReference '{0}' was not available. This may be because DisableTransitiveFrameworkReferenceDownloads was set to true.
+ NETSDK1185: FrameworkReference“{0}”的运行时包不可用。这可能是因为 DisableTransitiveFrameworkReferenceDownloads 设置为 true。
+ {StrBegins="NETSDK1185: "}
+
+
+ NETSDK1150: The referenced project '{0}' is a non self-contained executable. A non self-contained executable cannot be referenced by a self-contained executable. For more information, see https://aka.ms/netsdk1150
+ NETSDK1150: 引用的项目“{0}”是非自包含的可执行文件。非自包含可执行文件不能由自包含可执行文件引用。如需获取更多信息,请访问 https://aka.ms/netsdk1150
+ {StrBegins="NETSDK1150: "}
+
+
+ NETSDK1179: One of '--self-contained' or '--no-self-contained' options are required when '--runtime' is used.
+ NETSDK1179: 使用“--runtime”时,必需选择“--self-contained”或“--no-self-contained”选项。
+ {StrBegins="NETSDK1179: "}{Locked="--self-contained"}{Locked="--no-self-contained"}{Locked="--runtime"}
+
+
+ NETSDK1048: 'AdditionalProbingPaths' were specified for GenerateRuntimeConfigurationFiles, but are being skipped because 'RuntimeConfigDevPath' is empty.
+ NETSDK1048: "AdditionalProbingPaths" 被指定给 GenerateRuntimeConfigurationFiles,但被跳过,因为 "RuntimeConfigDevPath" 为空。
+ {StrBegins="NETSDK1048: "}
+
+
+ NETSDK1197: Multiple solution project(s) contain conflicting '{0}' values; ensure the values match. Consider using a Directory.build.props file to set the property for all projects. Conflicting projects:
+{1}
+ NETSDK1197: 多个解决方案项目包含存在冲突的“{0}”值;请确保值能够匹配。请考虑使用 Directory.build.props 文件设置所有项目的属性。存在冲突的项目:
+{1}
+ {StrBegins="NETSDK1197: "}
+
+
+ NETSDK1138: The target framework '{0}' is out of support and will not receive security updates in the future. Please refer to {1} for more information about the support policy.
+ NETSDK1138: 目标框架“{0}”不受支持,将来不会收到安全更新。有关支持策略的详细信息,请参阅 {1}。
+ {StrBegins="NETSDK1138: "}
+
+
+ NETSDK1215: Targeting .NET Standard prior to 2.0 is no longer recommended. See {0} for more details.
+ NETSDK1215: 不再建议将 2.0 之前的 .NET Standard 作为目标。有关更多详细信息,请参阅 {0}。
+ {StrBegins="NETSDK1215: "}
+
+
+ NETSDK1046: The TargetFramework value '{0}' is not valid. To multi-target, use the 'TargetFrameworks' property instead.
+ NETSDK1046: TargetFramework 值“{0}”无效。若要设置多个目标,请改用 "TargetFrameworks" 属性。
+ {StrBegins="NETSDK1046: "}
+
+
+ NETSDK1145: The {0} pack is not installed and NuGet package restore is not supported. Upgrade Visual Studio, remove global.json if it specifies a certain SDK version, and uninstall the newer SDK. For more options visit https://aka.ms/targeting-apphost-pack-missing Pack Type:{0}, Pack directory: {1}, targetframework: {2}, Pack PackageId: {3}, Pack Package Version: {4}
+ NETSDK1145: {0} 包未安装,不支持 NuGet 包还原。升级 Visual Studio,删除 global.json (如果它指定特定 SDK 版本),并卸载较新的 SDK。如需了解更多选项,请访问 https://aka.ms/targeting-apphost-pack-missing 包类型:{0},包目录: {1},targetframework: {2}, 包 Id: {3},包版本: {4}
+ {StrBegins="NETSDK1145: "}
+
+
+ NETSDK1127: The targeting pack {0} is not installed. Please restore and try again.
+ NETSDK1127: 未安装目标包 {0}。请还原并重试。
+ {StrBegins="NETSDK1127: "}
+
+
+ NETSDK1184: The Targeting Pack for FrameworkReference '{0}' was not available. This may be because DisableTransitiveFrameworkReferenceDownloads was set to true.
+ NETSDK1184: FrameworkReference“{0}”的目标包不可用。这可能是因为 DisableTransitiveFrameworkReferenceDownloads 设置为 true。
+ {StrBegins="NETSDK1184: "}
+
+
+ NETSDK1175: Windows Forms is not supported or recommended with trimming enabled. Please go to https://aka.ms/dotnet-illink/windows-forms for more details.
+ NETSDK1175: 启用剪裁时,不支持或不推荐使用 Windows 窗体。请转到 https://aka.ms/dotnet-illink/windows-forms 以了解详细信息。
+ {StrBegins="NETSDK1175: "}
+
+
+ NETSDK1168: WPF is not supported or recommended with trimming enabled. Please go to https://aka.ms/dotnet-illink/wpf for more details.
+ NETSDK1168: 启用剪裁时,不支持或不推荐使用 WPF。请转到 https://aka.ms/dotnet-illink/wpf 以了解详细信息。
+ {StrBegins="NETSDK1168: "}
+
+
+ NETSDK1172: The provided type library '{0}' does not exist.
+ NETSDK1172: 提供的类型库“{0}”不存在。
+ {StrBegins="NETSDK1172: "}
+
+
+ NETSDK1016: Unable to find resolved path for '{0}'.
+ NETSDK1016: 无法找到“{0}”的已解析路径。
+ {StrBegins="NETSDK1016: "}
+
+
+ Unable to use package assets cache due to I/O error. This can occur when the same project is built more than once in parallel. Performance may be degraded, but the build result will not be impacted.
+ 由于 I/O 错误,不能使用程序包资产缓存。如果多次并行生成同样的项目,也可能出现这种情况。可能会降低性能,但是不影响生成结果。
+
+
+
+ NETSDK1012: Unexpected file type for '{0}'. Type is both '{1}' and '{2}'.
+ NETSDK1012: “{0}”的文件类型非预期。类型是“{1}”和“{2}”。
+ {StrBegins="NETSDK1012: "}
+
+
+ NETSDK1073: The FrameworkReference '{0}' was not recognized
+ NETSDK1073: 未识别 FrameworkReference“{0}”
+ {StrBegins="NETSDK1073: "}
+
+
+ NETSDK1186: This project depends on Maui Essentials through a project or NuGet package reference, but doesn't declare that dependency explicitly. To build this project, you must set the UseMauiEssentials property to true (and install the Maui workload if necessary).
+ NETSDK1186: 此项目通过项目或 NuGet 包引用依赖于 Maui Essentials,但未显式声明该依赖项。要生成此项目,必须将 UseMauiEssentials 属性设置为 true (如有必要,请安装 Maui 工作负载)。
+ {StrBegins="NETSDK1186: "}
+
+
+ NETSDK1137: It is no longer necessary to use the Microsoft.NET.Sdk.WindowsDesktop SDK. Consider changing the Sdk attribute of the root Project element to 'Microsoft.NET.Sdk'.
+ NETSDK1137: 不再需要使用 Microsoft.NET.Sdk.WindowsDesktop SDK。请考虑将根项目元素的 Sdk 属性更改为 "Microsoft.NET.Sdk"。
+ {StrBegins="NETSDK1137: "}
+
+
+ NETSDK1009: Unrecognized preprocessor token '{0}' in '{1}'.
+ NETSDK1009: “{1}”中无法识别预处理器标记“{0}”。
+ {StrBegins="NETSDK1009: "}
+
+
+ NETSDK1081: The targeting pack for {0} was not found. You may be able to resolve this by running a NuGet restore on the project.
+ NETSDK1081: 找不到 {0} 的目标包。你可以通过对项目运行 NuGet 还原来解决此问题。
+ {StrBegins="NETSDK1081: "}
+
+
+ NETSDK1019: {0} is an unsupported framework.
+ NETSDK1019: {0} 是不受支持的框架。
+ {StrBegins="NETSDK1019: "}
+
+
+ NETSDK1056: Project is targeting runtime '{0}' but did not resolve any runtime-specific packages. This runtime may not be supported by the target framework.
+ NETSDK1056: 项目的目标是运行时“{0}”,但未解析任何运行时特定的包。目标框架可能不支持此运行时。
+ {StrBegins="NETSDK1056: "}
+
+
+ NETSDK1050: The version of Microsoft.NET.Sdk used by this project is insufficient to support references to libraries targeting .NET Standard 1.5 or higher. Please install version 2.0 or higher of the .NET Core SDK.
+ NETSDK1050: 该项目使用的 Microsoft.NET.Sdk 版本过低,不支持对面向.NET Standard 1.5 或更高版本的库的引用。请安装 2.0 版本或更高版本的 .NET Core SDK。
+ {StrBegins="NETSDK1050: "}
+
+
+ NETSDK1045: The current .NET SDK does not support targeting {0} {1}. Either target {0} {2} or lower, or use a version of the .NET SDK that supports {0} {1}. Download the .NET SDK from https://aka.ms/dotnet/download
+ NETSDK1045: 当前 .NET SDK 不支持面向 {0} {1}。请面向 {0} {2} 或更低版本,或者使用支持 {0} {1} 的 .NET SDK 版本。从 https://aka.ms/dotnet/download 下载 .NET SDK
+ {StrBegins="NETSDK1045: "}
+
+
+ NETSDK1139: The target platform identifier {0} was not recognized.
+ NETSDK1139: 无法识别目标平台标识符 {0}。
+ {StrBegins="NETSDK1139: "}
+
+
+ NETSDK1200: If UseArtifactsPath is set to true and ArtifactsPath is not set, there must be a Directory.Build.props file in order to determine where the artifacts folder should be located.
+ NETSDK1200: 如果 UseArtifactsPath 设置为 true,并且未设置 ArtifactsPath,则必须具有 Directory.Build.props 文件才能确定工件文件夹的位置。
+ {StrBegins="NETSDK1200: "}
+
+
+ NETSDK1209: The current Visual Studio version does not support targeting {0} {1}. Either target {0} {2} or lower, or use Visual Studio version {3} or higher
+ NETSDK1209: 当前 Visual Studio 版本不支持面向 {0} {1}。请面向 {0} {2} 或更低版本,或者使用 Visual Studio {3} 或更高版本
+ {StrBegins="NETSDK1209: "}
+
+
+ NETSDK1208: The target platform identifier {0} was not recognized. This is because MSBuildEnableWorkloadResolver is set to false which disables .NET SDK Workloads which is required for this identifer. Unset this environment variable or MSBuild property to enable workloads.
+ NETSDK1208: 无法识别目标平台标识符 {0}。这是因为 MSBuildEnableWorkloadResolver 设置为 false,这将禁用此标识符所需的 .NET SDK 工作负载。若要启用这些工作负载,请取消设置此环境变量或 MSBuild 属性。
+ {StrBegins="NETSDK1208: "}
+
+
+ NETSDK1107: Microsoft.NET.Sdk.WindowsDesktop is required to build Windows desktop applications. 'UseWpf' and 'UseWindowsForms' are not supported by the current SDK.
+ NETSDK1107: 要构建 Windows 桌面应用程序,需使用 Microsoft.NET.Sdk.WindowsDesktop。当前 SDK 不支持 "UseWpf" 和 "UseWindowsForms"。
+ {StrBegins="NETSDK1107: "}
+
+
+ NETSDK1057: You are using a preview version of .NET. See: https://aka.ms/dotnet-support-policy
+ NETSDK1057: 你正在使用 .NET 的预览版。请参阅 https://aka.ms/dotnet-support-policy
+ {StrBegins="NETSDK1057: "}
+
+
+ NETSDK1131: Producing a managed Windows Metadata component with WinMDExp is not supported when targeting {0}.
+ NETSDK1131: 当目标为 {0} 时,不支持使用 WinMDExp 生成托管 Windows 元数据组件。
+ {StrBegins="NETSDK1131: "}
+
+
+ NETSDK1130: {1} cannot be referenced. Referencing a Windows Metadata component directly when targeting .NET 5 or higher is not supported. For more information, see https://aka.ms/netsdk1130
+ NETSDK1130: 无法引用 {1}。不支持在以 .NET 5 或更高版本为目标时直接引用 Windows 元数据组件。有关详细信息,请参阅 https://aka.ms/netsdk1130
+ {StrBegins="NETSDK1130: "}
+
+
+ NETSDK1149: {0} cannot be referenced because it uses built-in support for WinRT, which is no longer supported in .NET 5 and higher. An updated version of the component supporting .NET 5 is needed. For more information, see https://aka.ms/netsdk1149
+ NETSDK1149: 无法引用 {0},因为它使用了对 WinRT 的内置支持,而 .NET 5 和更高版本中不再支持它。需要支持 .NET 5 的更新版本组件。有关详细信息,请参阅 https://aka.ms/netsdk1149
+ {StrBegins="NETSDK1149: "}
+
+
+ NETSDK1106: Microsoft.NET.Sdk.WindowsDesktop requires 'UseWpf' or 'UseWindowsForms' to be set to 'true'
+ NETSDK1106: Microsoft.NET.Sdk.WindowsDesktop 需要将 "UseWpf" 或 "UseWindowsForms" 设置为 "true"
+ {StrBegins="NETSDK1106: "}
+
+
+ NETSDK1105: Windows desktop applications are only supported on .NET Core 3.0 or higher.
+ NETSDK1105: 仅在 .NET Core 3.0 或更高版本上支持 Windows 桌面应用程序。
+ {StrBegins="NETSDK1105: "}
+
+
+ NETSDK1100: To build a project targeting Windows on this operating system, set the EnableWindowsTargeting property to true.
+ NETSDK1100: 若要在此操作系统上生成面向 Windows 的项目,请将 EnableWindowsTargeting 属性设置为 true。
+ {StrBegins="NETSDK1100: "}
+
+
+ NETSDK1136: The target platform must be set to Windows (usually by including '-windows' in the TargetFramework property) when using Windows Forms or WPF, or referencing projects or packages that do so.
+ NETSDK1136: 如果使用 Windows 窗体或 WPF,或者引用使用 Windows 窗体或 WPF 的项目或包,则必须将目标平台设置为 Windows (通常通过在 TargetFramework 属性中添加 "-windows")。
+ {StrBegins="NETSDK1136: "}
+
+
+ NETSDK1148: A referenced assembly was compiled using a newer version of Microsoft.Windows.SDK.NET.dll. Please update to a newer .NET SDK in order to reference this assembly.
+ NETSDK1148: 使用更新版本的 Microsoft.Windows.SDK.NET.dll 编译了引用的程序集。请更新为更新的 .NET SDK 以引用此程序集。
+ {StrBegins="NETSDK1148: "}
+
+
+ NETSDK1220: UseUwp and all associated functionality require using a TFM of 'net8.0-windows' or greater.
+ NETSDK1220: UseUwp 和所有关联的功能都需要使用 "net8.0-windows" 或更高版本的 TFM。
+ {StrBegins="NETSDK1220: "}
+
+
+ NETSDK1218: This project has a transitive dependency on the full Windows SDK projections (including Windows.UI.Xaml.* types), but does not specify the UseUwp property. That must be enabled to ensure that .NET types are projected and marshalled correctly for interop scenarios with these XAML types.
+ NETSDK1218: 此项目对完整的 Windows SDK 投影(包括 Windows.UI.Xaml.* 类型)具有传递依赖项,但不指定 UseUwp 属性。必须启用此功能,以确保为具有这些 XAML 类型的互操作方案正确投影和封送 .NET 类型。
+ {StrBegins="NETSDK1218: "}
+
+
+ NETSDK1202: The workload '{0}' is out of support and will not receive security updates in the future. Please refer to {1} for more information about the support policy.
+ NETSDK1202: 工作负载“{0}”已失去支持,并且将来不会收到安全更新。有关支持政策的详细信息,请参阅 {1}。
+ {StrBegins="NETSDK1202: "}
+
+
+ NETSDK1178: The project depends on the following workload packs that do not exist in any of the workloads available in this installation: {0}
+You may need to build the project on another operating system or architecture, or update the .NET SDK.
+ NETSDK1178: 此安装文件中任何可用的工作负载中,不存在该项目依赖的以下工作负载包: {0}
+可能需要在另一个操作系统或体系结构上生成项目,或者更新 .NET SDK。
+ {StrBegins="NETSDK1178: "}
+
+
+ NETSDK1147: To build this project, the following workloads must be installed: {0}
+To install these workloads, run the following command: dotnet workload restore
+ NETSDK1147: 要构建此项目,必须安装以下工作负载: {0}
+要安装这些工作负载,请运行以下命令: dotnet workload restore
+ {StrBegins="NETSDK1147: "}{Locked="dotnet workload restore"}
+
+
+
+
\ No newline at end of file
diff --git a/src/Tasks/Common/Resources/xlf/Strings.zh-Hant.xlf b/src/Tasks/Common/Resources/xlf/Strings.zh-Hant.xlf
index 78df7fff2522..2a159e2c4a0c 100644
--- a/src/Tasks/Common/Resources/xlf/Strings.zh-Hant.xlf
+++ b/src/Tasks/Common/Resources/xlf/Strings.zh-Hant.xlf
@@ -1013,6 +1013,11 @@ The following are names of parameters or literal values and should not be transl
NETSDK1139: 無法辨識目標平台識別碼 {0}。{StrBegins="NETSDK1139: "}
+
+ NETSDK1227: Unsupported ToolCommandRunner value: {0}
+ NETSDK1227: Unsupported ToolCommandRunner value: {0}
+ {StrBegins="NETSDK1227: "}
+ NETSDK1200: If UseArtifactsPath is set to true and ArtifactsPath is not set, there must be a Directory.Build.props file in order to determine where the artifacts folder should be located.NETSDK1200: 如果 UseArtifactsPath 設定為 true 且未設定 ArtifactsPath,則必須有 Directory.Build.props 檔案,才能判斷成品資料夾的位置。
diff --git a/src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/GivenAGenerateToolsSettingsFile.cs b/src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/GivenAGenerateToolsSettingsFile.cs
index 8ae9fbf8f517..63ec4f9d2f59 100644
--- a/src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/GivenAGenerateToolsSettingsFile.cs
+++ b/src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/GivenAGenerateToolsSettingsFile.cs
@@ -4,6 +4,7 @@
#nullable disable
using FluentAssertions;
+using Microsoft.Build.Framework;
using Xunit;
namespace Microsoft.NET.Build.Tasks.UnitTests
@@ -13,7 +14,8 @@ public class GivenAGenerateToolsSettingsFile
private XDocument _generatedDocument = null;
public GivenAGenerateToolsSettingsFile()
{
- _generatedDocument = GenerateToolsSettingsFile.GenerateDocument("tool.dll", "mytool");
+ _generatedDocument = GenerateToolsSettingsFile.GenerateDocument("tool.dll", "mytool",
+ commandRunner: null, runtimeIdentifier: null, toolPackageId: "mytool", toolPackageVersion: "1.0.0", Array.Empty());
}
[Fact]
diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/AddPackageType.cs b/src/Tasks/Microsoft.NET.Build.Tasks/AddPackageType.cs
new file mode 100644
index 000000000000..3ff496b0bbb6
--- /dev/null
+++ b/src/Tasks/Microsoft.NET.Build.Tasks/AddPackageType.cs
@@ -0,0 +1,56 @@
+using Microsoft.Build.Framework;
+using Task = Microsoft.Build.Utilities.Task;
+using System;
+using System.Globalization;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Microsoft.NET.Build.Tasks
+{
+ public class AddPackageType : Task
+ {
+ public string? CurrentPackageType { get; set; }
+
+ [Required]
+ public string? PackageTypeToAdd { get; set; }
+
+ [Output]
+ public string[]? UpdatedPackageType { get; set; }
+
+ public override bool Execute()
+ {
+ string current = CurrentPackageType ?? string.Empty;
+ string toAdd = (PackageTypeToAdd ?? string.Empty).Trim();
+ if (string.IsNullOrEmpty(toAdd))
+ {
+ UpdatedPackageType = current.Split(';');
+ return true;
+ }
+
+ // Split current types, trim, and filter out empty
+ var types = current.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)
+ .Select(t => t.Trim())
+ .Where(t => !string.IsNullOrEmpty(t))
+ .ToList();
+
+ // Check if toAdd (case-insensitive, ignoring version) is already present
+ bool alreadyPresent = types.Any(t =>
+ {
+ var typeName = t.Split(',')[0].Trim();
+ return typeName.Equals(toAdd, StringComparison.InvariantCultureIgnoreCase);
+ });
+
+
+ if (alreadyPresent)
+ {
+ UpdatedPackageType = current.Split(';');
+ }
+ else
+ {
+ types.Insert(0, toAdd);
+ UpdatedPackageType = types.ToArray();
+ }
+ return true;
+ }
+ }
+}
diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/GenerateToolsSettingsFile.cs b/src/Tasks/Microsoft.NET.Build.Tasks/GenerateToolsSettingsFile.cs
index 5611ed14af98..dda71a5ddcff 100644
--- a/src/Tasks/Microsoft.NET.Build.Tasks/GenerateToolsSettingsFile.cs
+++ b/src/Tasks/Microsoft.NET.Build.Tasks/GenerateToolsSettingsFile.cs
@@ -9,34 +9,106 @@ namespace Microsoft.NET.Build.Tasks
{
public class GenerateToolsSettingsFile : TaskBase
{
- // bump whenever the format changes such that it will break old consumers
- private static readonly int _formatVersion = 1;
-
[Required]
public string EntryPointRelativePath { get; set; }
[Required]
public string CommandName { get; set; }
+ public string CommandRunner { get; set; }
+
+ public string RuntimeIdentifier { get; set; }
+
+ public string ToolPackageId { get; set; }
+
+ public string ToolPackageVersion { get; set; }
+
+ public ITaskItem[] ToolPackageRuntimeIdentifiers { get; set; }
+
[Required]
public string ToolsSettingsFilePath { get; set; }
protected override void ExecuteCore()
{
- GenerateDocument(EntryPointRelativePath, CommandName).Save(ToolsSettingsFilePath);
+ GenerateDocument(EntryPointRelativePath, CommandName, CommandRunner, RuntimeIdentifier, ToolPackageId, ToolPackageVersion, ToolPackageRuntimeIdentifiers)
+ .Save(ToolsSettingsFilePath);
}
- internal static XDocument GenerateDocument(string entryPointRelativePath, string commandName)
+ internal static XDocument GenerateDocument(string entryPointRelativePath, string commandName, string commandRunner, string runtimeIdentifier,
+ string toolPackageId, string toolPackageVersion, ITaskItem[] toolPackageRuntimeIdentifiers)
{
+ // Format version should bump whenever the format changes such that it will break old consumers
+ int formatVersion = 1;
+
+ if (string.IsNullOrEmpty(commandRunner))
+ {
+ commandRunner = "dotnet";
+ }
+
+ if (commandRunner != "dotnet")
+ {
+ if (commandRunner == "executable")
+ {
+ formatVersion = 2;
+ }
+ else
+ {
+ throw new BuildErrorException(
+ string.Format(
+ Strings.UnsupportedToolCommandRunner,
+ commandRunner));
+ }
+ }
+
+ XElement runtimeIdentifierPackagesNode = null;
+ XElement commandNode = new XElement("Command",
+ new XAttribute("Name", commandName));
+
+ // Only generate RuntimeIdentifierPackages node for the primary package, when RuntimeIdentifier isn't set
+ if (string.IsNullOrEmpty(runtimeIdentifier) && (toolPackageRuntimeIdentifiers?.Any() ?? false))
+ {
+ formatVersion = 2;
+ runtimeIdentifierPackagesNode = new XElement("RuntimeIdentifierPackages");
+ foreach (var runtimeIdentifierPackage in toolPackageRuntimeIdentifiers)
+ {
+ string toolPackageRuntimeIdentifier = runtimeIdentifierPackage.ItemSpec;
+
+ var packageNode = new XElement("RuntimeIdentifierPackage");
+ packageNode.Add(new XAttribute("RuntimeIdentifier", toolPackageRuntimeIdentifier));
+
+ string ridPackageId = toolPackageId + "." + toolPackageRuntimeIdentifier;
+ packageNode.Add(new XAttribute("Id", ridPackageId));
+
+ string ridPackageVersion = runtimeIdentifierPackage.GetMetadata("Version");
+ if (string.IsNullOrEmpty(ridPackageVersion))
+ {
+ ridPackageVersion = toolPackageVersion;
+ }
+ packageNode.Add(new XAttribute("Version", ridPackageVersion));
+
+ runtimeIdentifierPackagesNode.Add(packageNode);
+ }
+ }
+ else
+ {
+ // EntryPoint and Runner are only set in packages with tool implementation, not in primary packages
+ // when there are RID-specific tool packages
+ commandNode.Add(new XAttribute("EntryPoint", entryPointRelativePath),
+ new XAttribute("Runner", commandRunner));
+ }
+
+ var dotnetCliToolNode = new XElement("DotNetCliTool",
+ new XAttribute("Version", formatVersion),
+ new XElement("Commands", commandNode));
+
+ if (runtimeIdentifierPackagesNode != null)
+ {
+ dotnetCliToolNode.Add(runtimeIdentifierPackagesNode);
+ }
+
return new XDocument(
new XDeclaration(version: null, encoding: null, standalone: null),
- new XElement("DotNetCliTool",
- new XAttribute("Version", _formatVersion),
- new XElement("Commands",
- new XElement("Command",
- new XAttribute("Name", commandName),
- new XAttribute("EntryPoint", entryPointRelativePath),
- new XAttribute("Runner", "dotnet")))));
+ dotnetCliToolNode);
}
}
}
diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/Microsoft.NET.Build.Tasks.csproj b/src/Tasks/Microsoft.NET.Build.Tasks/Microsoft.NET.Build.Tasks.csproj
index 1eb9602b1b25..9dd44663b715 100644
--- a/src/Tasks/Microsoft.NET.Build.Tasks/Microsoft.NET.Build.Tasks.csproj
+++ b/src/Tasks/Microsoft.NET.Build.Tasks/Microsoft.NET.Build.Tasks.csproj
@@ -101,6 +101,7 @@
+
diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/RemoveTargetFromList.cs b/src/Tasks/Microsoft.NET.Build.Tasks/RemoveTargetFromList.cs
new file mode 100644
index 000000000000..6ef2c4c9bd86
--- /dev/null
+++ b/src/Tasks/Microsoft.NET.Build.Tasks/RemoveTargetFromList.cs
@@ -0,0 +1,36 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#nullable disable
+
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+using System;
+using System.Linq;
+
+namespace Microsoft.NET.Build.Tasks
+{
+ ///
+ /// Removes a target from a semicolon-delimited list of targets.
+ ///
+ public class RemoveTargetFromList : TaskBase
+ {
+ [Required]
+ public string TargetList { get; set; }
+
+ [Required]
+ public string TargetToRemove { get; set; }
+
+ // Output needs to be an array so MSBuild won't escape semicolonns
+ [Output]
+ public string[] UpdatedTargetList { get; private set; }
+
+ protected override void ExecuteCore()
+ {
+ UpdatedTargetList = (TargetList ?? string.Empty)
+ .Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)
+ .Where(t => !string.Equals(t.Trim(), TargetToRemove, StringComparison.OrdinalIgnoreCase))
+ .ToArray();
+ }
+ }
+}
diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/ResolveToolPackagePaths.cs b/src/Tasks/Microsoft.NET.Build.Tasks/ResolveToolPackagePaths.cs
index cb89a467731a..049d65894770 100644
--- a/src/Tasks/Microsoft.NET.Build.Tasks/ResolveToolPackagePaths.cs
+++ b/src/Tasks/Microsoft.NET.Build.Tasks/ResolveToolPackagePaths.cs
@@ -24,9 +24,7 @@ public sealed class ResolveToolPackagePaths : TaskBase
public string PublishDir { get; set; }
[Required]
- public string TargetFrameworkMoniker { get; set; }
-
- public string TargetPlatformMoniker { get; set; }
+ public string ToolPackShortTargetFrameworkName { get; set; }
[Output]
public ITaskItem[] ResolvedFileToPublishWithPackagePath { get; private set; }
@@ -51,9 +49,7 @@ protected override void ExecuteCore()
relativePath));
var i = new TaskItem(fullpath);
- var shortFrameworkName = NuGetFramework
- .ParseComponents(TargetFrameworkMoniker, TargetPlatformMoniker)
- .GetShortFolderName();
+ var shortFrameworkName = ToolPackShortTargetFrameworkName;
i.SetMetadata("PackagePath", $"tools/{shortFrameworkName}/any/{GetDirectoryPathInRelativePath(relativePath)}");
result.Add(i);
diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.PackTool.targets b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.PackTool.targets
index dbc4c9ee1bf0..2c5c19dcd3ec 100644
--- a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.PackTool.targets
+++ b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.PackTool.targets
@@ -21,7 +21,18 @@ Copyright (c) .NET Foundation. All rights reserved.
AssemblyFile="$(MicrosoftNETBuildTasksAssembly)" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ToolPackageShouldIncludeImplementation Condition=" '$(PackAsTool)' == 'true' And
+ ('@(ToolPackageRuntimeIdentifier)' == '' Or '$(RuntimeIdentifier)' != '')">true
+ <_ToolPackageShouldIncludeImplementation Condition="'$(_ToolPackageShouldIncludeImplementation)' == ''">false
+
+
+
+ <_PackToolPublishDependency Condition=" ('$(GeneratePackageOnBuild)' != 'true' and '$(NoBuild)' != 'true') and $(IsPublishable) == 'true' ">_PublishBuildAlternative
+ <_PackToolPublishDependency Condition=" ('$(GeneratePackageOnBuild)' == 'true' or '$(NoBuild)' == 'true') and $(IsPublishable) == 'true' ">$(_PublishNoBuildAlternativeDependsOn)
+
+
+
+
+ $(TargetFileName)
+
+ $([System.IO.Path]::GetFileName($(NativeBinary)))
+
+
+
+ $(PackageId).$(RuntimeIdentifier)
+
+
+
+
+
+
<_GeneratedFiles Include="$(PublishDepsFilePath)" Condition="'$(GenerateDependencyFile)' != 'true' or '$(_UseBuildDependencyFile)' == 'true'" />
<_GeneratedFiles Include="$(PublishRuntimeConfigFilePath)"/>
+
+
+
+
+
+
+
+
+
<_GeneratedFiles Include="$(_ToolsSettingsFilePath)"/>
@@ -44,15 +124,13 @@ Copyright (c) .NET Foundation. All rights reserved.
AppHostIntermediatePath="$(AppHostIntermediatePath)"
ResolvedFileToPublish="@(ResolvedFileToPublish)"
PublishDir="$(PublishDir)"
- TargetFrameworkMoniker="$(TargetFrameworkMoniker)"
- TargetPlatformMoniker="$(TargetPlatformMoniker)">
-
+ ToolPackShortTargetFrameworkName="$(_ToolPackShortTargetFrameworkName)">
- tools/$(_NuGetShortFolderName)/any/%(_GeneratedFiles.RecursiveDir)%(_GeneratedFiles.Filename)%(_GeneratedFiles.Extension)
+ tools/$(_ToolPackShortTargetFrameworkName)/any/%(_GeneratedFiles.RecursiveDir)%(_GeneratedFiles.Filename)%(_GeneratedFiles.Extension)
@@ -63,15 +141,25 @@ Copyright (c) .NET Foundation. All rights reserved.
$(TargetName)
- $(TargetFileName)
+ $(RuntimeIdentifier)
<_GenerateToolsSettingsFileCacheFile Condition="'$(_GenerateToolsSettingsFileCacheFile)' == ''">$(IntermediateOutputPath)$(MSBuildProjectName).toolssettingsinput.cache
<_GenerateToolsSettingsFileCacheFile>$([MSBuild]::NormalizePath($(MSBuildProjectDirectory), $(_GenerateToolsSettingsFileCacheFile)))
+
+ dotnet
+ executable
+
+
<_GenerateToolsSettingsFileInputCacheToHash Include="$(ToolEntryPoint)" />
<_GenerateToolsSettingsFileInputCacheToHash Include="$(ToolCommandName)" />
+ <_GenerateToolsSettingsFileInputCacheToHash Include="$(ToolCommandRunner)" />
+ <_GenerateToolsSettingsFileInputCacheToHash Include="$(ToolRuntimeIdentifier)" />
+ <_GenerateToolsSettingsFileInputCacheToHash Include="$(PackageId)" />
+ <_GenerateToolsSettingsFileInputCacheToHash Include="$(Version)" />
+ <_GenerateToolsSettingsFileInputCacheToHash Include="@(ToolPackageRuntimeIdentifier->'%(Identity)%(Version)')" />
@@ -98,6 +186,11 @@ Copyright (c) .NET Foundation. All rights reserved.
@@ -107,12 +200,13 @@ Copyright (c) .NET Foundation. All rights reserved.
TargetFrameworkMoniker="$(TargetFrameworkMoniker)"
TargetPlatformMoniker="$(TargetPlatformMoniker)">
-
+
-
+
+ <_ToolPackShortTargetFrameworkName Condition="'$(SelfContained)' == 'true'">any
+
@@ -151,7 +245,7 @@ Copyright (c) .NET Foundation. All rights reserved.
ApphostsForShimRuntimeIdentifiers="@(_ApphostsForShimRuntimeIdentifiers)"
IntermediateAssembly="@(IntermediateAssembly->'%(FullPath)')"
OutputType="$(OutputType)"
- PackagedShimOutputDirectory="$(PackagedShimOutputRootDirectory)/shims/$(_NuGetShortFolderName)"
+ PackagedShimOutputDirectory="$(PackagedShimOutputRootDirectory)/shims/$(_ToolPackShortTargetFrameworkName)"
PackageId="$(PackageId)"
PackageVersion="$(PackageVersion)"
ShimRuntimeIdentifiers="@(_PackAsToolShimRuntimeIdentifiers)"
@@ -180,7 +274,7 @@ Copyright (c) .NET Foundation. All rights reserved.
diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.RuntimeIdentifierInference.targets b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.RuntimeIdentifierInference.targets
index abcd7ba3dbcd..ac32434a4eaf 100644
--- a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.RuntimeIdentifierInference.targets
+++ b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.RuntimeIdentifierInference.targets
@@ -77,6 +77,10 @@ Copyright (c) .NET Foundation. All rights reserved.
true
+
+
+ <_IsPublishing>true
+
@@ -91,12 +95,17 @@ Copyright (c) .NET Foundation. All rights reserved.
The other publish properties are specifically labelled Publish* and don't 'NEED' their RID unless we are doing a publish, so the RID inference
... for these properties is limited to publishing only scenarios.
- Finally, library projects and non-executable projects have awkward interactions here so they are excluded.-->
+ .NET Tools that build RID-specific packages will also need a primary package without a RuntimeIdentifier, so we disable RID inference for them
+ in order to build the primary package
+
+ Finally, library projects and non-executable projects have awkward interactions here so they are excluded.
+ -->
false
+ $(RuntimeIdentifiers);$(PackAsToolShimRuntimeIdentifiers)
+
+
+
+
+
+
+
+ <_ToolPackageType Condition="'$(RuntimeIdentifier)' != '' And '@(ToolPackageRuntimeIdentifier)' != ''">DotnetToolRidPackage
+ <_ToolPackageType Condition="'$(_ToolPackageType)' == ''">DotnetTool
+
+
+
- <_PaddedPackageType>;$(PackageType.Replace(' ', '').Trim().ToLowerInvariant());
- DotnetTool;$(PackageType)
- DotnetTool
- $(RuntimeIdentifiers);$(PackAsToolShimRuntimeIdentifiers)
-
+
+
+
+
+
+ Preview
diff --git a/test/Microsoft.DotNet.PackageInstall.Tests/DotnetToolSettingsMajorHigherVersion.xml b/test/Microsoft.DotNet.PackageInstall.Tests/DotnetToolSettingsMajorHigherVersion.xml
index f74b863d84cb..25d78a271db4 100644
--- a/test/Microsoft.DotNet.PackageInstall.Tests/DotnetToolSettingsMajorHigherVersion.xml
+++ b/test/Microsoft.DotNet.PackageInstall.Tests/DotnetToolSettingsMajorHigherVersion.xml
@@ -1,5 +1,5 @@
-
+
diff --git a/test/Microsoft.DotNet.PackageInstall.Tests/EndToEndToolTests.cs b/test/Microsoft.DotNet.PackageInstall.Tests/EndToEndToolTests.cs
new file mode 100644
index 000000000000..04430642f3aa
--- /dev/null
+++ b/test/Microsoft.DotNet.PackageInstall.Tests/EndToEndToolTests.cs
@@ -0,0 +1,150 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Microsoft.Extensions.EnvironmentAbstractions;
+
+namespace Microsoft.DotNet.PackageInstall.Tests
+{
+ [Collection(nameof(TestToolBuilderCollection))]
+ public class EndToEndToolTests : SdkTest
+ {
+ private readonly TestToolBuilder ToolBuilder;
+
+ public EndToEndToolTests(ITestOutputHelper log, TestToolBuilder toolBuilder) : base(log)
+ {
+ ToolBuilder = toolBuilder;
+ }
+
+ [Fact]
+ public void InstallAndRunToolGlobal()
+ {
+ var toolSettings = new TestToolBuilder.TestToolSettings();
+ string toolPackagesPath = ToolBuilder.CreateTestTool(Log, toolSettings);
+
+ var testDirectory = _testAssetsManager.CreateTestDirectory();
+ var homeFolder = Path.Combine(testDirectory.Path, "home");
+
+ new DotnetToolCommand(Log, "install", "-g", toolSettings.ToolPackageId, "--add-source", toolPackagesPath)
+ .WithEnvironmentVariables(homeFolder)
+ .WithWorkingDirectory(testDirectory.Path)
+ .Execute()
+ .Should().Pass();
+
+ var toolsFolder = Path.Combine(homeFolder, ".dotnet", "tools");
+
+ var shimPath = Path.Combine(toolsFolder, toolSettings.ToolCommandName + EnvironmentInfo.ExecutableExtension);
+ new FileInfo(shimPath).Should().Exist();
+
+ new RunExeCommand(Log, shimPath)
+ .WithWorkingDirectory(testDirectory.Path)
+ .Execute()
+ .Should().Pass()
+ .And.HaveStdOutContaining("Hello Tool!");
+ }
+
+ [Fact]
+ public void InstallAndRunNativeAotGlobalTool()
+ {
+ var toolSettings = new TestToolBuilder.TestToolSettings()
+ {
+ NativeAOT = true
+ };
+ string toolPackagesPath = ToolBuilder.CreateTestTool(Log, toolSettings);
+
+ var testDirectory = _testAssetsManager.CreateTestDirectory();
+
+ var homeFolder = Path.Combine(testDirectory.Path, "home");
+
+ new DotnetToolCommand(Log, "install", "-g", toolSettings.ToolPackageId, "--add-source", toolPackagesPath)
+ .WithEnvironmentVariables(homeFolder)
+ .WithWorkingDirectory(testDirectory.Path)
+ .Execute()
+ .Should().Pass();
+
+ var toolsFolder = Path.Combine(homeFolder, ".dotnet", "tools");
+
+ var shimPath = Path.Combine(toolsFolder, toolSettings.ToolCommandName + (OperatingSystem.IsWindows() ? ".cmd" : ""));
+ new FileInfo(shimPath).Should().Exist();
+
+ new RunExeCommand(Log, shimPath)
+ .WithWorkingDirectory(testDirectory.Path)
+ .Execute()
+ .Should().Pass()
+ .And.HaveStdOutContaining("Hello Tool!");
+ }
+
+ [Fact]
+ public void InstallAndRunToolLocal()
+ {
+ var toolSettings = new TestToolBuilder.TestToolSettings();
+ string toolPackagesPath = ToolBuilder.CreateTestTool(Log, toolSettings);
+
+ var testDirectory = _testAssetsManager.CreateTestDirectory();
+ var homeFolder = Path.Combine(testDirectory.Path, "home");
+
+ new DotnetCommand(Log, "new", "tool-manifest")
+ .WithEnvironmentVariables(homeFolder)
+ .WithWorkingDirectory(testDirectory.Path)
+ .Execute()
+ .Should().Pass();
+
+ new DotnetToolCommand(Log, "install", toolSettings.ToolPackageId, "--add-source", toolPackagesPath)
+ .WithEnvironmentVariables(homeFolder)
+ .WithWorkingDirectory(testDirectory.Path)
+ .Execute()
+ .Should().Pass();
+
+ new DotnetCommand(Log, toolSettings.ToolCommandName)
+ .WithEnvironmentVariables(homeFolder)
+ .WithWorkingDirectory(testDirectory.Path)
+ .Execute()
+ .Should().Pass()
+ .And.HaveStdOutContaining("Hello Tool!");
+ }
+
+ [Fact]
+ public void InstallAndRunNativeAotLocalTool()
+ {
+ var toolSettings = new TestToolBuilder.TestToolSettings()
+ {
+ NativeAOT = true
+ };
+ string toolPackagesPath = ToolBuilder.CreateTestTool(Log, toolSettings);
+
+ var testDirectory = _testAssetsManager.CreateTestDirectory();
+ var homeFolder = Path.Combine(testDirectory.Path, "home");
+
+ new DotnetCommand(Log, "new", "tool-manifest")
+ .WithEnvironmentVariables(homeFolder)
+ .WithWorkingDirectory(testDirectory.Path)
+ .Execute()
+ .Should().Pass();
+
+ new DotnetToolCommand(Log, "install", toolSettings.ToolPackageId, "--add-source", toolPackagesPath)
+ .WithEnvironmentVariables(homeFolder)
+ .WithWorkingDirectory(testDirectory.Path)
+ .Execute()
+ .Should().Pass();
+
+ new DotnetCommand(Log, toolSettings.ToolCommandName)
+ .WithEnvironmentVariables(homeFolder)
+ .WithWorkingDirectory(testDirectory.Path)
+ .Execute()
+ .Should().Pass()
+ .And.HaveStdOutContaining("Hello Tool!");
+ }
+ }
+
+ static class EndToEndToolTestExtensions
+ {
+ public static TestCommand WithEnvironmentVariables(this TestCommand command, string homeFolder)
+ {
+ return command.WithEnvironmentVariable("DOTNET_CLI_HOME", homeFolder)
+ .WithEnvironmentVariable("DOTNET_NOLOGO", "1")
+ .WithEnvironmentVariable("DOTNET_ADD_GLOBAL_TOOLS_TO_PATH", "0");
+ }
+ }
+}
diff --git a/test/Microsoft.DotNet.PackageInstall.Tests/LocalToolsResolverCacheTests.cs b/test/Microsoft.DotNet.PackageInstall.Tests/LocalToolsResolverCacheTests.cs
index 3a4d090a4aa2..6871b67d5a3f 100644
--- a/test/Microsoft.DotNet.PackageInstall.Tests/LocalToolsResolverCacheTests.cs
+++ b/test/Microsoft.DotNet.PackageInstall.Tests/LocalToolsResolverCacheTests.cs
@@ -42,10 +42,10 @@ public void GivenExecutableIdentifierItCanSaveAndCannotLoadWithMismatches()
string runtimeIdentifier = Constants.AnyRid;
PackageId packageId = new("my.toolBundle");
NuGetVersion nuGetVersion = NuGetVersion.Parse("1.0.2");
- IReadOnlyList restoredCommands = new[]
+ IReadOnlyList restoredCommands = new[]
{
- new RestoredCommand(new ToolCommandName("tool1"), "dotnet", nuGetGlobalPackagesFolder.WithFile("tool1.dll")),
- new RestoredCommand(new ToolCommandName("tool2"), "dotnet", nuGetGlobalPackagesFolder.WithFile("tool2.dll"))
+ new ToolCommand(new ToolCommandName("tool1"), "dotnet", nuGetGlobalPackagesFolder.WithFile("tool1.dll")),
+ new ToolCommand(new ToolCommandName("tool2"), "dotnet", nuGetGlobalPackagesFolder.WithFile("tool2.dll"))
};
localToolsResolverCache.Save(
@@ -82,10 +82,10 @@ public void GivenExecutableIdentifierItCanSaveAndLoad()
string runtimeIdentifier = Constants.AnyRid;
PackageId packageId = new("my.toolBundle");
NuGetVersion nuGetVersion = NuGetVersion.Parse("1.0.2");
- IReadOnlyList restoredCommands = new[]
+ IReadOnlyList restoredCommands = new[]
{
- new RestoredCommand(new ToolCommandName("tool1"), "dotnet", nuGetGlobalPackagesFolder.WithFile("tool1.dll")),
- new RestoredCommand(new ToolCommandName("tool2"), "dotnet", nuGetGlobalPackagesFolder.WithFile("tool2.dll"))
+ new ToolCommand(new ToolCommandName("tool1"), "dotnet", nuGetGlobalPackagesFolder.WithFile("tool1.dll")),
+ new ToolCommand(new ToolCommandName("tool2"), "dotnet", nuGetGlobalPackagesFolder.WithFile("tool2.dll"))
};
localToolsResolverCache.Save(
@@ -96,12 +96,12 @@ public void GivenExecutableIdentifierItCanSaveAndLoad()
localToolsResolverCache.TryLoad(
new RestoredCommandIdentifier(packageId, nuGetVersion, targetFramework, runtimeIdentifier,
restoredCommands[0].Name),
- out RestoredCommand tool1).Should().BeTrue();
+ out ToolCommand tool1).Should().BeTrue();
localToolsResolverCache.TryLoad(
new RestoredCommandIdentifier(packageId, nuGetVersion, targetFramework, runtimeIdentifier,
restoredCommands[1].Name),
- out RestoredCommand tool2).Should().BeTrue();
+ out ToolCommand tool2).Should().BeTrue();
tool1.Should().BeEquivalentTo(restoredCommands[0]);
tool2.Should().BeEquivalentTo(restoredCommands[1]);
@@ -116,10 +116,10 @@ public void GivenExecutableIdentifierItCanSaveMultipleSameAndLoadContainsOnlyOne
string runtimeIdentifier = Constants.AnyRid;
PackageId packageId = new("my.toolBundle");
NuGetVersion nuGetVersion = NuGetVersion.Parse("1.0.2");
- IReadOnlyList restoredCommands = new[]
+ IReadOnlyList restoredCommands = new[]
{
- new RestoredCommand(new ToolCommandName("tool1"), "dotnet", nuGetGlobalPackagesFolder.WithFile("tool1.dll")),
- new RestoredCommand(new ToolCommandName("tool2"), "dotnet", nuGetGlobalPackagesFolder.WithFile("tool2.dll"))
+ new ToolCommand(new ToolCommandName("tool1"), "dotnet", nuGetGlobalPackagesFolder.WithFile("tool1.dll")),
+ new ToolCommand(new ToolCommandName("tool2"), "dotnet", nuGetGlobalPackagesFolder.WithFile("tool2.dll"))
};
localToolsResolverCache.Save(
@@ -135,89 +135,18 @@ public void GivenExecutableIdentifierItCanSaveMultipleSameAndLoadContainsOnlyOne
localToolsResolverCache.TryLoad(
new RestoredCommandIdentifier(packageId, nuGetVersion, targetFramework, runtimeIdentifier,
restoredCommands[0].Name),
- out RestoredCommand tool1);
+ out ToolCommand tool1);
localToolsResolverCache.TryLoad(
new RestoredCommandIdentifier(packageId, nuGetVersion, targetFramework, runtimeIdentifier,
restoredCommands[1].Name),
- out RestoredCommand tool2);
+ out ToolCommand tool2);
tool1.Should().BeEquivalentTo(restoredCommands[0]);
tool2.Should().BeEquivalentTo(restoredCommands[1]);
}
- [Fact]
- public void ItCanSaveMultipleSameAndLoadTheHighestFromVersionRange()
- {
- (DirectoryPath nuGetGlobalPackagesFolder, LocalToolsResolverCache localToolsResolverCache) = Setup();
-
- NuGetFramework targetFramework = NuGetFramework.Parse(ToolsetInfo.CurrentTargetFramework);
- string runtimeIdentifier = Constants.AnyRid;
- PackageId packageId = new("my.toolBundle");
-
- NuGetVersion previewNuGetVersion = NuGetVersion.Parse("0.0.2");
- IReadOnlyList restoredCommandsV0 = new[]
- {
- new RestoredCommand(new ToolCommandName("tool1"), "dotnet", nuGetGlobalPackagesFolder.WithFile("tool1preview.dll")),
- };
-
- NuGetVersion nuGetVersion = NuGetVersion.Parse("1.0.2");
- IReadOnlyList restoredCommandsV1 = new[]
- {
- new RestoredCommand(new ToolCommandName("tool1"), "dotnet", nuGetGlobalPackagesFolder.WithFile("tool1.dll")),
- };
-
- NuGetVersion newerNuGetVersion = NuGetVersion.Parse("2.0.2");
- IReadOnlyList restoredCommandsV2 = new[]
- {
- new RestoredCommand(new ToolCommandName("tool1"), "dotnet", nuGetGlobalPackagesFolder.WithFile("tool1new.dll")),
- };
-
- localToolsResolverCache.Save(
- restoredCommandsV0.ToDictionary(
- c => new RestoredCommandIdentifier(packageId, previewNuGetVersion, targetFramework, runtimeIdentifier,
- c.Name)));
-
- localToolsResolverCache.Save(
- restoredCommandsV1.ToDictionary(
- c => new RestoredCommandIdentifier(packageId, nuGetVersion, targetFramework, runtimeIdentifier,
- c.Name)));
-
- localToolsResolverCache.Save(
- restoredCommandsV2.ToDictionary(
- c => new RestoredCommandIdentifier(packageId, newerNuGetVersion, targetFramework, runtimeIdentifier,
- c.Name)));
-
- bool loadSuccess =
- localToolsResolverCache.TryLoadHighestVersion(
- new RestoredCommandIdentifierVersionRange(
- packageId,
- VersionRange.Parse("(0.0.0, 2.0.0)"),
- targetFramework, runtimeIdentifier, new ToolCommandName("tool1")),
- out RestoredCommand loadedResolverCache);
-
- loadSuccess.Should().BeTrue();
-
- loadedResolverCache.Should().BeEquivalentTo(restoredCommandsV1[0]);
- }
-
- [Fact]
- public void ItReturnsFalseWhenFailedToLoadVersionRange()
- {
- (DirectoryPath nuGetGlobalPackagesFolder, LocalToolsResolverCache localToolsResolverCache) = Setup();
-
- bool loadSuccess =
- localToolsResolverCache.TryLoadHighestVersion(
- new RestoredCommandIdentifierVersionRange(
- new PackageId("my.toolBundle"),
- VersionRange.Parse("(0.0.0, 2.0.0)"),
- NuGetFramework.Parse(ToolsetInfo.CurrentTargetFramework), Constants.AnyRid, new ToolCommandName("tool1")),
- out _);
-
- loadSuccess.Should().BeFalse();
- }
-
[Fact]
public void GivenExecutableIdentifierItCanSaveMultipleVersionAndLoad()
{
@@ -227,16 +156,16 @@ public void GivenExecutableIdentifierItCanSaveMultipleVersionAndLoad()
string runtimeIdentifier = Constants.AnyRid;
PackageId packageId = new("my.toolBundle");
NuGetVersion nuGetVersion = NuGetVersion.Parse("1.0.2");
- IReadOnlyList restoredCommands = new[]
+ IReadOnlyList restoredCommands = new[]
{
- new RestoredCommand(new ToolCommandName("tool1"), "dotnet", nuGetGlobalPackagesFolder.WithFile("tool1.dll")),
+ new ToolCommand(new ToolCommandName("tool1"), "dotnet", nuGetGlobalPackagesFolder.WithFile("tool1.dll")),
};
NuGetVersion newerNuGetVersion = NuGetVersion.Parse("2.0.2");
- IReadOnlyList restoredCommandsNewer = new[]
+ IReadOnlyList restoredCommandsNewer = new[]
{
- new RestoredCommand(new ToolCommandName("tool1"), "dotnet", nuGetGlobalPackagesFolder.WithFile("tool1new.dll")),
- new RestoredCommand(new ToolCommandName("tool2"), "dotnet", nuGetGlobalPackagesFolder.WithFile("tool2new.dll")),
+ new ToolCommand(new ToolCommandName("tool1"), "dotnet", nuGetGlobalPackagesFolder.WithFile("tool1new.dll")),
+ new ToolCommand(new ToolCommandName("tool2"), "dotnet", nuGetGlobalPackagesFolder.WithFile("tool2new.dll")),
};
localToolsResolverCache.Save(
@@ -252,16 +181,16 @@ public void GivenExecutableIdentifierItCanSaveMultipleVersionAndLoad()
localToolsResolverCache.TryLoad(
new RestoredCommandIdentifier(packageId, nuGetVersion, targetFramework, runtimeIdentifier,
restoredCommands[0].Name),
- out RestoredCommand tool1);
+ out ToolCommand tool1);
localToolsResolverCache.TryLoad(
new RestoredCommandIdentifier(packageId, newerNuGetVersion, targetFramework, runtimeIdentifier,
restoredCommandsNewer[0].Name),
- out RestoredCommand tool1Newer);
+ out ToolCommand tool1Newer);
localToolsResolverCache.TryLoad(
new RestoredCommandIdentifier(packageId, newerNuGetVersion, targetFramework, runtimeIdentifier,
restoredCommandsNewer[1].Name),
- out RestoredCommand tool2Newer);
+ out ToolCommand tool2Newer);
tool1.Should().BeEquivalentTo(restoredCommands[0]);
tool1Newer.Should().BeEquivalentTo(restoredCommandsNewer[0]);
@@ -309,9 +238,9 @@ public void WhenTheCacheIsCorruptedItShouldNotAffectNextSaveAndLoad()
string runtimeIdentifier = Constants.AnyRid;
PackageId packageId = new("my.toolBundle");
NuGetVersion nuGetVersion = NuGetVersion.Parse("1.0.2");
- IReadOnlyList restoredCommands = new[]
+ IReadOnlyList restoredCommands = new[]
{
- new RestoredCommand(new ToolCommandName("tool1"), "dotnet", nuGetGlobalPackagesFolder.WithFile("tool1.dll")),
+ new ToolCommand(new ToolCommandName("tool1"), "dotnet", nuGetGlobalPackagesFolder.WithFile("tool1.dll")),
};
localToolsResolverCache.Save(
@@ -338,7 +267,7 @@ public void WhenTheCacheIsCorruptedItShouldNotAffectNextSaveAndLoad()
localToolsResolverCache.TryLoad(
new RestoredCommandIdentifier(packageId, nuGetVersion, targetFramework, runtimeIdentifier,
restoredCommands[0].Name),
- out RestoredCommand restoredCommand);
+ out ToolCommand restoredCommand);
restoredCommand.Should().BeEquivalentTo(restoredCommands[0]);
}
@@ -366,9 +295,9 @@ private static void WhenTheCacheIsCorruptedItShouldLoadAsEmpty(
string runtimeIdentifier = Constants.AnyRid;
PackageId packageId = new("my.toolBundle");
NuGetVersion nuGetVersion = NuGetVersion.Parse("1.0.2");
- IReadOnlyList restoredCommands = new[]
+ IReadOnlyList restoredCommands = new[]
{
- new RestoredCommand(new ToolCommandName("tool1"), "dotnet", nuGetGlobalPackagesFolder.WithFile("tool1.dll")),
+ new ToolCommand(new ToolCommandName("tool1"), "dotnet", nuGetGlobalPackagesFolder.WithFile("tool1.dll")),
};
localToolsResolverCache.Save(
diff --git a/test/Microsoft.DotNet.PackageInstall.Tests/Microsoft.DotNet.PackageInstall.Tests.csproj b/test/Microsoft.DotNet.PackageInstall.Tests/Microsoft.DotNet.PackageInstall.Tests.csproj
index dccaeb7c55a9..9f50ecb38a1c 100644
--- a/test/Microsoft.DotNet.PackageInstall.Tests/Microsoft.DotNet.PackageInstall.Tests.csproj
+++ b/test/Microsoft.DotNet.PackageInstall.Tests/Microsoft.DotNet.PackageInstall.Tests.csproj
@@ -71,8 +71,6 @@
$(BaseOutputPath)/TestAsset/SampleGlobalTool
-
-
@@ -96,8 +94,6 @@
$(BaseOutputPath)/TestAsset/SampleGlobalToolWithPreview
-
-
@@ -121,8 +117,6 @@
$(BaseOutputPath)/TestAsset/SampleGlobalToolWithDifferentCasing
-
-
diff --git a/test/Microsoft.DotNet.PackageInstall.Tests/NuGetPackageInstallerTests.cs b/test/Microsoft.DotNet.PackageInstall.Tests/NuGetPackageInstallerTests.cs
index e66351fa38e2..8e0693efdad9 100644
--- a/test/Microsoft.DotNet.PackageInstall.Tests/NuGetPackageInstallerTests.cs
+++ b/test/Microsoft.DotNet.PackageInstall.Tests/NuGetPackageInstallerTests.cs
@@ -157,9 +157,12 @@ public async Task GivenNoPackageVersionItCanInstallLatestVersionOfPackage()
[Fact]
public async Task GivenARelativeSourcePathInstallSucceeds()
{
+ new RunExeCommand(Log, "dotnet", "nuget", "locals", "all", "--list")
+ .Execute().Should().Pass();
+
string getTestLocalFeedPath = GetTestLocalFeedPath();
string relativePath = Path.GetRelativePath(Environment.CurrentDirectory, getTestLocalFeedPath);
- Log.WriteLine(relativePath);
+ Log.WriteLine("Relative path: " + relativePath);
string packagePath = await _installer.DownloadPackageAsync(
TestPackageId,
new NuGetVersion(TestPackageVersion),
diff --git a/test/Microsoft.DotNet.PackageInstall.Tests/SampleGlobalTool/DotnetToolSettings.xml b/test/Microsoft.DotNet.PackageInstall.Tests/SampleGlobalTool/DotnetToolSettings.xml
deleted file mode 100644
index 92142c78de77..000000000000
--- a/test/Microsoft.DotNet.PackageInstall.Tests/SampleGlobalTool/DotnetToolSettings.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
diff --git a/test/Microsoft.DotNet.PackageInstall.Tests/SampleGlobalTool/consoledemo.csproj b/test/Microsoft.DotNet.PackageInstall.Tests/SampleGlobalTool/consoledemo.csproj
index 2423b618afd8..65d852a42fcb 100644
--- a/test/Microsoft.DotNet.PackageInstall.Tests/SampleGlobalTool/consoledemo.csproj
+++ b/test/Microsoft.DotNet.PackageInstall.Tests/SampleGlobalTool/consoledemo.csproj
@@ -1,7 +1,7 @@
-
+Exe
- netcoreapp2.1
+ net6.0consoledemo
$(RestoreSources);
@@ -11,5 +11,9 @@
falsefalsefalse
+ true
+ global.tool.console.demo
+ 1.0.4
+ demo
-
\ No newline at end of file
+
diff --git a/test/Microsoft.DotNet.PackageInstall.Tests/SampleGlobalTool/includepublish.nuspec b/test/Microsoft.DotNet.PackageInstall.Tests/SampleGlobalTool/includepublish.nuspec
deleted file mode 100644
index 57b0be8ec1ed..000000000000
--- a/test/Microsoft.DotNet.PackageInstall.Tests/SampleGlobalTool/includepublish.nuspec
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
- global.tool.console.demo
- 1.0.4
- test app
- testauthor
-
-
-
-
-
-
-
-
-
diff --git a/test/Microsoft.DotNet.PackageInstall.Tests/SampleGlobalToolWithDifferentCasing/ConsoleDemoWithCasing.csproj b/test/Microsoft.DotNet.PackageInstall.Tests/SampleGlobalToolWithDifferentCasing/ConsoleDemoWithCasing.csproj
index b8971531dd4f..5fe98faa5825 100644
--- a/test/Microsoft.DotNet.PackageInstall.Tests/SampleGlobalToolWithDifferentCasing/ConsoleDemoWithCasing.csproj
+++ b/test/Microsoft.DotNet.PackageInstall.Tests/SampleGlobalToolWithDifferentCasing/ConsoleDemoWithCasing.csproj
@@ -1,7 +1,7 @@
Exe
- netcoreapp2.1
+ net6.0ConsoleDemoWithCasing
$(RestoreSources);
@@ -11,5 +11,9 @@
falsefalsefalse
+ true
+ Global.Tool.Console.Demo.With.Casing
+ 2.0.4
+ DemoWithCasing
diff --git a/test/Microsoft.DotNet.PackageInstall.Tests/SampleGlobalToolWithDifferentCasing/DotnetToolSettings.xml b/test/Microsoft.DotNet.PackageInstall.Tests/SampleGlobalToolWithDifferentCasing/DotnetToolSettings.xml
deleted file mode 100644
index 98734a9d562d..000000000000
--- a/test/Microsoft.DotNet.PackageInstall.Tests/SampleGlobalToolWithDifferentCasing/DotnetToolSettings.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
diff --git a/test/Microsoft.DotNet.PackageInstall.Tests/SampleGlobalToolWithDifferentCasing/includepublish.nuspec b/test/Microsoft.DotNet.PackageInstall.Tests/SampleGlobalToolWithDifferentCasing/includepublish.nuspec
deleted file mode 100644
index db3b0787c05a..000000000000
--- a/test/Microsoft.DotNet.PackageInstall.Tests/SampleGlobalToolWithDifferentCasing/includepublish.nuspec
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
- Global.Tool.Console.Demo.With.Casing
- 2.0.4
- test app
- testauthor
-
-
-
-
-
-
-
-
-
diff --git a/test/Microsoft.DotNet.PackageInstall.Tests/SampleGlobalToolWithPreview/DotnetToolSettings.xml b/test/Microsoft.DotNet.PackageInstall.Tests/SampleGlobalToolWithPreview/DotnetToolSettings.xml
deleted file mode 100644
index 92142c78de77..000000000000
--- a/test/Microsoft.DotNet.PackageInstall.Tests/SampleGlobalToolWithPreview/DotnetToolSettings.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
diff --git a/test/Microsoft.DotNet.PackageInstall.Tests/SampleGlobalToolWithPreview/consoledemo.csproj b/test/Microsoft.DotNet.PackageInstall.Tests/SampleGlobalToolWithPreview/consoledemo.csproj
index 2423b618afd8..e7ae47a820ce 100644
--- a/test/Microsoft.DotNet.PackageInstall.Tests/SampleGlobalToolWithPreview/consoledemo.csproj
+++ b/test/Microsoft.DotNet.PackageInstall.Tests/SampleGlobalToolWithPreview/consoledemo.csproj
@@ -1,7 +1,7 @@
Exe
- netcoreapp2.1
+ net6.0consoledemo
$(RestoreSources);
@@ -11,5 +11,9 @@
falsefalsefalse
+ true
+ global.tool.console.demo
+ 2.0.1-preview1
+ demo
\ No newline at end of file
diff --git a/test/Microsoft.DotNet.PackageInstall.Tests/SampleGlobalToolWithPreview/includepublish.nuspec b/test/Microsoft.DotNet.PackageInstall.Tests/SampleGlobalToolWithPreview/includepublish.nuspec
deleted file mode 100644
index aa6a0f7476db..000000000000
--- a/test/Microsoft.DotNet.PackageInstall.Tests/SampleGlobalToolWithPreview/includepublish.nuspec
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
- global.tool.console.demo
- 2.0.1-preview1
- test app
- testauthor
-
-
-
-
-
-
-
-
-
diff --git a/test/Microsoft.DotNet.PackageInstall.Tests/SampleGlobalToolWithShim/consoledemo.csproj b/test/Microsoft.DotNet.PackageInstall.Tests/SampleGlobalToolWithShim/consoledemo.csproj
index 2423b618afd8..c42859afe28f 100644
--- a/test/Microsoft.DotNet.PackageInstall.Tests/SampleGlobalToolWithShim/consoledemo.csproj
+++ b/test/Microsoft.DotNet.PackageInstall.Tests/SampleGlobalToolWithShim/consoledemo.csproj
@@ -1,7 +1,7 @@
Exe
- netcoreapp2.1
+ net6.0consoledemo
$(RestoreSources);
diff --git a/test/Microsoft.DotNet.PackageInstall.Tests/SampleGlobalToolWithShim/includepublish.nuspec b/test/Microsoft.DotNet.PackageInstall.Tests/SampleGlobalToolWithShim/includepublish.nuspec
index b2ed9d349cc7..828a4f7d7b53 100644
--- a/test/Microsoft.DotNet.PackageInstall.Tests/SampleGlobalToolWithShim/includepublish.nuspec
+++ b/test/Microsoft.DotNet.PackageInstall.Tests/SampleGlobalToolWithShim/includepublish.nuspec
@@ -10,11 +10,11 @@
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/test/Microsoft.DotNet.PackageInstall.Tests/Stage2ProjectRestorer.cs b/test/Microsoft.DotNet.PackageInstall.Tests/Stage2ProjectRestorer.cs
deleted file mode 100644
index bf3fed61f6a3..000000000000
--- a/test/Microsoft.DotNet.PackageInstall.Tests/Stage2ProjectRestorer.cs
+++ /dev/null
@@ -1,81 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-#nullable disable
-
-using Microsoft.DotNet.Cli.Commands;
-using Microsoft.DotNet.Cli.Commands.Tool.Install;
-using Microsoft.DotNet.Cli.ToolPackage;
-using Microsoft.DotNet.Cli.Utils;
-using Microsoft.Extensions.EnvironmentAbstractions;
-
-namespace Microsoft.DotNet.Tools.Tool.Install
-{
- ///
- /// Use stage 2 (the build result) to run restore instead of stage 0 (the last version of SDK)
- /// to have more coverage
- ///
- /// ProjectRestorer will stage0, so cannot be covered in tests. Try to hit the same code path of ProjectRestorer as possible.
- ///
- internal class Stage2ProjectRestorer : IProjectRestorer
- {
- private readonly IReporter _reporter;
- private readonly IReporter _errorReporter;
- private readonly IEnumerable _additionalRestoreArguments;
- private readonly ITestOutputHelper _log;
-
- public Stage2ProjectRestorer(ITestOutputHelper log, IReporter reporter = null,
- IEnumerable additionalRestoreArguments = null)
- {
- _log = log;
- _additionalRestoreArguments = additionalRestoreArguments;
- _reporter = reporter ?? Reporter.Output;
- _errorReporter = reporter ?? Reporter.Error;
- }
-
- public void Restore(FilePath project,
- PackageLocation packageLocation,
- string verbosity = null)
- {
- var argsToPassToRestore = new List();
-
- argsToPassToRestore.Add(project.Value);
- if (packageLocation.NugetConfig != null)
- {
- argsToPassToRestore.Add("--configfile");
- argsToPassToRestore.Add(packageLocation.NugetConfig.Value.Value);
- }
-
- argsToPassToRestore.AddRange(new List
- {
- "--runtime",
- Constants.AnyRid,
- "-v:quiet"
- });
-
- if (_additionalRestoreArguments != null)
- {
- argsToPassToRestore.AddRange(_additionalRestoreArguments);
- }
-
- var command =
- new DotnetRestoreCommand(_log).
- Execute(argsToPassToRestore);
-
- if (!string.IsNullOrWhiteSpace(command.StdOut) && (_reporter != null))
- {
- ProjectRestorer.WriteLine(_reporter, command.StdOut, project);
- }
-
- if (!string.IsNullOrWhiteSpace(command.StdErr) && (_reporter != null))
- {
- ProjectRestorer.WriteLine(_errorReporter, command.StdErr, project);
- }
-
- if (command.ExitCode != 0)
- {
- throw new ToolPackageException(CliCommandStrings.ToolInstallationRestoreFailed);
- }
- }
- }
-}
diff --git a/test/Microsoft.DotNet.PackageInstall.Tests/TestToolBuilder.cs b/test/Microsoft.DotNet.PackageInstall.Tests/TestToolBuilder.cs
new file mode 100644
index 000000000000..c306552c8ab9
--- /dev/null
+++ b/test/Microsoft.DotNet.PackageInstall.Tests/TestToolBuilder.cs
@@ -0,0 +1,173 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Microsoft.DotNet.PackageInstall.Tests
+{
+ [CollectionDefinition(nameof(TestToolBuilderCollection))]
+ public class TestToolBuilderCollection : ICollectionFixture
+ {
+ // This class is intentionally left empty.
+ }
+
+
+ // This class is responsible for creating test dotnet tool packages. We don't want every test to have to create it's own tool package, as that could slow things down quite a bit.
+ // So this class handles creating each tool package once. To use it, add it as a constructor parameter to your test class. You will also need to add [Collection(nameof(TestToolBuilderCollection))]
+ // to your test class to ensure that only one test at a time uses this class. xUnit will give you an error if you forget to add the collection attribute but do add the constructor parameter.
+ //
+ // The TestToolBuilder class uses a common folder to store all the tool package projects and their built nupkgs. When CreateTestTool is called, it will compare the contents of the project
+ // in the common folder to the contents of the project that is being requested. If there are any differences, it will re-create the project and build it again. It will also delete the package from the
+ // global packages folder to ensure that the newly built package is used the next time a test tries to install it.
+ //
+ // The main thing this class can't handle is if the way the .NET SDK builds packages changes. In CI runs, we should use a clean test execution folder each time (I think!), so this shouldn't be an issue.
+ // For local testing, you may need to delete the artifacts\tmp\Debug\TestTools folder if the SDK changes in a way that affects the built package.
+ public class TestToolBuilder
+ {
+ public class TestToolSettings
+ {
+ public string ToolPackageId { get; set; } = "TestTool";
+ public string ToolPackageVersion { get; set; } = "1.0.0";
+ public string ToolCommandName { get; set; } = "TestTool";
+
+ public bool NativeAOT { get; set; } = false;
+
+ public string GetIdentifier() => $"{ToolPackageId}-{ToolPackageVersion}-{ToolCommandName}-{(NativeAOT ? "nativeaot" : "managed")}";
+ }
+
+
+ public string CreateTestTool(ITestOutputHelper log, TestToolSettings toolSettings)
+ {
+ var targetDirectory = Path.Combine(TestContext.Current.TestExecutionDirectory, "TestTools", toolSettings.GetIdentifier());
+
+
+ var testProject = new TestProject(toolSettings.ToolPackageId)
+ {
+ TargetFrameworks = ToolsetInfo.CurrentTargetFramework,
+ IsExe = true,
+ };
+ testProject.AdditionalProperties["PackAsTool"] = "true";
+ testProject.AdditionalProperties["ToolCommandName"] = toolSettings.ToolCommandName;
+ testProject.AdditionalProperties["ImplicitUsings"] = "enable";
+ testProject.AdditionalProperties["Version"] = toolSettings.ToolPackageVersion;
+
+ if (toolSettings.NativeAOT)
+ {
+ testProject.AdditionalProperties["PublishAot"] = "true";
+ testProject.AddItem("ToolPackageRuntimeIdentifier", "Include", RuntimeInformation.RuntimeIdentifier);
+ }
+
+ testProject.SourceFiles.Add("Program.cs", "Console.WriteLine(\"Hello Tool!\");");
+
+ var testAssetManager = new TestAssetsManager(log);
+ var testAsset = testAssetManager.CreateTestProject(testProject, identifier: toolSettings.GetIdentifier());
+
+ var testAssetProjectDirectory = Path.Combine(testAsset.Path, testProject.Name!);
+
+ // Avoid rebuilding the package unless the project has changed. If there is a difference in contents between the files from the TestProject and the target directory,
+ // then we delete and recopy everything over.
+ if (!AreDirectoriesEqual(testAssetProjectDirectory, targetDirectory))
+ {
+ if (Directory.Exists(targetDirectory))
+ {
+ Directory.Delete(targetDirectory, true);
+ }
+
+ Directory.CreateDirectory(Path.GetDirectoryName(targetDirectory)!);
+
+ Directory.Move(testAssetProjectDirectory, targetDirectory);
+ }
+
+ // If the .nupkg hasn't been created yet, then build it. This may be because this is the first time we need the package, or because we've updated the tests and
+ // the contents of the files have changed
+ string packageOutputPath = Path.Combine(targetDirectory, "bin", "Release");
+ if (!Directory.Exists(packageOutputPath) || Directory.GetFiles(packageOutputPath, "*.nupkg").Length == 0)
+ {
+ new DotnetPackCommand(log)
+ .WithWorkingDirectory(targetDirectory)
+ .Execute()
+ .Should().Pass();
+
+ if (toolSettings.NativeAOT)
+ {
+ // For Native AOT tools, we need to repack the tool to include the runtime-specific files that were generated during publish
+ new DotnetPackCommand(log, "-r", RuntimeInformation.RuntimeIdentifier)
+ .WithWorkingDirectory(targetDirectory)
+ .Execute()
+ .Should().Pass();
+ }
+
+ // If we have built a new package, delete any old versions of it from the global packages folder
+ RemovePackageFromGlobalPackages(log, toolSettings.ToolPackageId, toolSettings.ToolPackageVersion);
+ }
+
+ return packageOutputPath;
+ }
+
+ public void RemovePackageFromGlobalPackages(ITestOutputHelper log, string packageId, string version)
+ {
+ var result = new DotnetCommand(log, "nuget", "locals", "global-packages", "--list")
+ .Execute();
+
+ result.Should().Pass();
+
+ string? globalPackagesPath;
+
+ var outputDict = result.StdOut!.Split(Environment.NewLine)
+ .Select(l => l.Trim())
+ .Where(l => !string.IsNullOrEmpty(l))
+ .ToDictionary(l => l.Split(':')[0].Trim(), l => l.Split(':', count: 2)[1].Trim());
+
+ if (!outputDict.TryGetValue("global-packages", out globalPackagesPath))
+ {
+ throw new InvalidOperationException("Could not determine global packages location.");
+ }
+
+ var packagePathInGlobalPackages = Path.Combine(globalPackagesPath, packageId.ToLowerInvariant(), version);
+
+ if (Directory.Exists(packagePathInGlobalPackages))
+ {
+ Directory.Delete(packagePathInGlobalPackages, true);
+ }
+ }
+
+ ///
+ /// Compares the files in two directories (non-recursively) and returns true if they have the same files with identical text contents.
+ ///
+ /// First directory path
+ /// Second directory path
+ /// True if the directories have the same files with the same text contents, false otherwise.
+ public static bool AreDirectoriesEqual(string dir1, string dir2)
+ {
+ if (!Directory.Exists(dir1) || !Directory.Exists(dir2))
+ return false;
+
+ var files1 = Directory.GetFiles(dir1);
+ var files2 = Directory.GetFiles(dir2);
+
+ if (files1.Length != files2.Length)
+ return false;
+
+ var fileNames1 = new HashSet(Array.ConvertAll(files1, f => Path.GetFileName(f) ?? string.Empty), StringComparer.OrdinalIgnoreCase);
+ var fileNames2 = new HashSet(Array.ConvertAll(files2, f => Path.GetFileName(f) ?? string.Empty), StringComparer.OrdinalIgnoreCase);
+
+ if (!fileNames1.SetEquals(fileNames2))
+ return false;
+
+ foreach (var fileName in fileNames1)
+ {
+ var filePath1 = Path.Combine(dir1, fileName);
+ var filePath2 = Path.Combine(dir2, fileName);
+ if (!File.Exists(filePath1) || !File.Exists(filePath2))
+ return false;
+ var text1 = File.ReadAllText(filePath1);
+ var text2 = File.ReadAllText(filePath2);
+ if (!string.Equals(text1, text2, StringComparison.Ordinal))
+ return false;
+ }
+ return true;
+ }
+ }
+}
diff --git a/test/Microsoft.DotNet.PackageInstall.Tests/ToolConfigurationDeserializerTests.cs b/test/Microsoft.DotNet.PackageInstall.Tests/ToolConfigurationDeserializerTests.cs
index a484f838081e..acff382cd166 100644
--- a/test/Microsoft.DotNet.PackageInstall.Tests/ToolConfigurationDeserializerTests.cs
+++ b/test/Microsoft.DotNet.PackageInstall.Tests/ToolConfigurationDeserializerTests.cs
@@ -63,7 +63,7 @@ public void GivenMinorHigherVersionItHasNoWarning()
public void GivenInvalidCharAsFileNameItThrows()
{
var invalidCommandName = "na\0me";
- Action a = () => new ToolConfiguration(invalidCommandName, "my.dll");
+ Action a = () => new ToolConfiguration(invalidCommandName, "my.dll", "dotnet");
a.Should().Throw()
.And.Message.Should()
.Contain(
@@ -77,7 +77,7 @@ public void GivenInvalidCharAsFileNameItThrows()
public void GivenALeadingDotAsFileNameItThrows()
{
var invalidCommandName = ".mytool";
- Action a = () => new ToolConfiguration(invalidCommandName, "my.dll");
+ Action a = () => new ToolConfiguration(invalidCommandName, "my.dll", "dotnet");
a.Should().Throw()
.And.Message.Should()
.Contain(string.Format(
diff --git a/test/Microsoft.DotNet.PackageInstall.Tests/ToolPackageDownloaderTests.cs b/test/Microsoft.DotNet.PackageInstall.Tests/ToolPackageDownloaderTests.cs
index 10c6e4b6314a..299593c6e202 100644
--- a/test/Microsoft.DotNet.PackageInstall.Tests/ToolPackageDownloaderTests.cs
+++ b/test/Microsoft.DotNet.PackageInstall.Tests/ToolPackageDownloaderTests.cs
@@ -34,6 +34,7 @@ public DotnetEnvironmentTestFixture()
public void Dispose() => Environment.SetEnvironmentVariable(_PATH_VAR_NAME, _originalPath);
}
+ [Collection(nameof(TestToolBuilderCollection))]
public class ToolPackageDownloaderTests : SdkTest, IClassFixture
{
[Theory]
@@ -41,14 +42,12 @@ public class ToolPackageDownloaderTests : SdkTest, IClassFixture
- {
- new MockFeed
- {
- Type = MockFeedType.FeedFromLookUpNugetConfig,
- Uri = nugetConfigPath.Value,
- Packages = new List
- {
- new MockFeedPackage
- {
- PackageId = TestPackageId.ToString(),
- Version = TestPackageVersion,
- ToolCommandName = "SimulatorCommand"
- }
- }
- }
- };
-
- var (store, storeQuery, downloader, uninstaller, reporter, fileSystem) = Setup(
+ var (store, storeQuery, downloader, uninstaller, reporter, fileSystem, testDir) = Setup(
useMock: testMockBehaviorIsInSync,
- writeLocalFeedToNugetConfig: nugetConfigPath,
- feeds: onlyNugetConfigInParentDirHasPackagesFeed);
+ includeLocalFeedInNugetConfig: true);
- fileSystem.Directory.CreateDirectory(subDirUnderNugetConfigPath.Value);
+ var subDirectory = testDir.WithSubDirectories("sub");
+ fileSystem.Directory.CreateDirectory(subDirectory.Value);
var package = downloader.InstallPackage(
- new PackageLocation(rootConfigDirectory: subDirUnderNugetConfigPath),
+ new PackageLocation(rootConfigDirectory: subDirectory),
packageId: TestPackageId,
verbosity: TestVerbosity,
versionRange: VersionRange.Parse(TestPackageVersion),
@@ -186,14 +160,12 @@ public void GivenAConfigFileRootDirectoryPackageInstallSucceedsViaFindingNugetCo
[InlineData(true)]
public void GivenAllButNoPackageVersionItReturnLatestStableVersion(bool testMockBehaviorIsInSync)
{
- var nugetConfigPath = GenerateRandomNugetConfigFilePath();
-
- var (store, storeQuery, downloader, uninstaller, reporter, fileSystem) = Setup(
+ var (store, storeQuery, downloader, uninstaller, reporter, fileSystem, testDir) = Setup(
useMock: testMockBehaviorIsInSync,
- writeLocalFeedToNugetConfig: nugetConfigPath);
+ includeLocalFeedInNugetConfig: true);
var package = downloader.GetNuGetVersion(
- new PackageLocation(nugetConfig: nugetConfigPath),
+ new PackageLocation(nugetConfig: testDir.WithFile("NuGet.config")),
packageId: TestPackageId,
verbosity: TestVerbosity,
isGlobalTool: true);
@@ -210,15 +182,15 @@ public void GivenAllButNoPackageVersionItReturnLatestStableVersion(bool testMock
[InlineData(true, TestPackageVersion, TestPackageVersion)]
public void GivenASpecificVersionGetCorrectVersion(bool testMockBehaviorIsInSync, string requestedVersion, string expectedVersion)
{
- var nugetConfigPath = GenerateRandomNugetConfigFilePath();
+
var emptySource = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
Directory.CreateDirectory(emptySource);
- var (store, storeQuery, downloader, uninstaller, reporter, fileSystem) = Setup(
+ var (store, storeQuery, downloader, uninstaller, reporter, fileSystem, testDir) = Setup(
useMock: testMockBehaviorIsInSync,
- writeLocalFeedToNugetConfig: nugetConfigPath);
+ includeLocalFeedInNugetConfig: true);
- var package = downloader.GetNuGetVersion(new PackageLocation(nugetConfig: nugetConfigPath,
+ var package = downloader.GetNuGetVersion(new PackageLocation(nugetConfig: testDir.WithFile("NuGet.config"),
additionalFeeds: new[] { emptySource }),
packageId: TestPackageId,
verbosity: TestVerbosity,
@@ -233,14 +205,12 @@ public void GivenASpecificVersionGetCorrectVersion(bool testMockBehaviorIsInSync
[InlineData(true)]
public void GivenAllButNoPackageVersionItCanInstallThePackage(bool testMockBehaviorIsInSync)
{
- var nugetConfigPath = GenerateRandomNugetConfigFilePath();
-
- var (store, storeQuery, downloader, uninstaller, reporter, fileSystem) = Setup(
+ var (store, storeQuery, downloader, uninstaller, reporter, fileSystem, testDir) = Setup(
useMock: testMockBehaviorIsInSync,
- writeLocalFeedToNugetConfig: nugetConfigPath);
+ includeLocalFeedInNugetConfig: true);
var package = downloader.InstallPackage(
- new PackageLocation(nugetConfig: nugetConfigPath),
+ new PackageLocation(nugetConfig: testDir.WithFile("NuGet.config")),
packageId: TestPackageId,
verbosity: TestVerbosity,
targetFramework: _testTargetframework,
@@ -257,13 +227,11 @@ public void GivenAllButNoPackageVersionItCanInstallThePackage(bool testMockBehav
[InlineData(true)]
public void GivenAllButNoTargetFrameworkItCanDownloadThePackage(bool testMockBehaviorIsInSync)
{
- var nugetConfigPath = GenerateRandomNugetConfigFilePath();
-
- var (store, storeQuery, downloader, uninstaller, reporter, fileSystem) = Setup(
+ var (store, storeQuery, downloader, uninstaller, reporter, fileSystem, testDir) = Setup(
useMock: testMockBehaviorIsInSync,
- writeLocalFeedToNugetConfig: nugetConfigPath);
+ includeLocalFeedInNugetConfig: true);
- var package = downloader.InstallPackage(new PackageLocation(nugetConfig: nugetConfigPath),
+ var package = downloader.InstallPackage(new PackageLocation(nugetConfig: testDir.WithFile("NuGet.config")),
packageId: TestPackageId,
verbosity: TestVerbosity,
versionRange: VersionRange.Parse(TestPackageVersion),
@@ -282,9 +250,9 @@ public void GivenASourceInstallSucceeds(bool testMockBehaviorIsInSync)
{
var source = GetTestLocalFeedPath();
- var (store, storeQuery, downloader, uninstaller, reporter, fileSystem) = Setup(
+ var (store, storeQuery, downloader, uninstaller, reporter, fileSystem, testDir) = Setup(
useMock: testMockBehaviorIsInSync,
- feeds: GetMockFeedsForSource(source));
+ includeLocalFeedInNugetConfig: false);
var package = downloader.InstallPackage(new PackageLocation(additionalFeeds: new[] { source }),
packageId: TestPackageId,
@@ -304,15 +272,24 @@ public void GivenASourceInstallSucceeds(bool testMockBehaviorIsInSync)
[InlineData(true)]
public void GivenARelativeSourcePathInstallSucceeds(bool testMockBehaviorIsInSync)
{
+ // CI seems to be getting an old version of the global.tool.console.demo package which targets .NET Core 2.1. This may fix that
+ ToolBuilder.RemovePackageFromGlobalPackages(Log, TestPackageId.ToString(), TestPackageVersion);
+
var source = GetTestLocalFeedPath();
- var (store, storeQuery, downloader, uninstaller, reporter, fileSystem) = Setup(
+ var (store, storeQuery, downloader, uninstaller, reporter, fileSystem, testDir) = Setup(
useMock: testMockBehaviorIsInSync,
- feeds: GetMockFeedsForSource(source));
+ includeLocalFeedInNugetConfig: false);
+
+ var relativePath = Path.GetRelativePath(testDir.Value, source);
+
+ Log.WriteLine("Root path: " + testDir.Value);
+ Log.WriteLine("Relative path: " + relativePath);
+ Log.WriteLine("Current Directory: " + Directory.GetCurrentDirectory());
var package = downloader.InstallPackage(
- new PackageLocation(additionalFeeds: new[]
- {Path.GetRelativePath(Directory.GetCurrentDirectory(), source)}), packageId: TestPackageId,
+ new PackageLocation(additionalFeeds: new[] {relativePath}),
+ packageId: TestPackageId,
verbosity: TestVerbosity,
versionRange: VersionRange.Parse(TestPackageVersion),
targetFramework: _testTargetframework,
@@ -329,11 +306,14 @@ public void GivenARelativeSourcePathInstallSucceeds(bool testMockBehaviorIsInSyn
[InlineData(true)]
public void GivenAUriSourceInstallSucceeds(bool testMockBehaviorIsInSync)
{
+ // CI seems to be getting an old version of the global.tool.console.demo package which targets .NET Core 2.1. This may fix that
+ ToolBuilder.RemovePackageFromGlobalPackages(Log, TestPackageId.ToString(), TestPackageVersion);
+
var source = GetTestLocalFeedPath();
- var (store, storeQuery, downloader, uninstaller, reporter, fileSystem) = Setup(
+ var (store, storeQuery, downloader, uninstaller, reporter, fileSystem, testDir) = Setup(
useMock: testMockBehaviorIsInSync,
- feeds: GetMockFeedsForSource(source));
+ includeLocalFeedInNugetConfig: false);
var package = downloader.InstallPackage(
new PackageLocation(additionalFeeds: new[] { new Uri(source).AbsoluteUri }), packageId: TestPackageId,
@@ -353,15 +333,14 @@ public void GivenAUriSourceInstallSucceeds(bool testMockBehaviorIsInSync)
[InlineData(true)]
public void GivenAEmptySourceAndNugetConfigInstallSucceeds(bool testMockBehaviorIsInSync)
{
- var nugetConfigPath = GenerateRandomNugetConfigFilePath();
var emptySource = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
Directory.CreateDirectory(emptySource);
- var (store, storeQuery, downloader, uninstaller, reporter, fileSystem) = Setup(
+ var (store, storeQuery, downloader, uninstaller, reporter, fileSystem, testDir) = Setup(
useMock: testMockBehaviorIsInSync,
- writeLocalFeedToNugetConfig: nugetConfigPath);
+ includeLocalFeedInNugetConfig: true);
- var package = downloader.InstallPackage(new PackageLocation(nugetConfig: nugetConfigPath,
+ var package = downloader.InstallPackage(new PackageLocation(nugetConfig: testDir.WithFile("NuGet.config"),
additionalFeeds: new[] { emptySource }),
packageId: TestPackageId,
verbosity: TestVerbosity,
@@ -382,9 +361,9 @@ public void GivenFailureAfterRestoreInstallWillRollback(bool testMockBehaviorIsI
{
var source = GetTestLocalFeedPath();
- var (store, storeQuery, downloader, uninstaller, reporter, fileSystem) = Setup(
+ var (store, storeQuery, downloader, uninstaller, reporter, fileSystem, testDir) = Setup(
useMock: testMockBehaviorIsInSync,
- feeds: GetMockFeedsForSource(source));
+ includeLocalFeedInNugetConfig: false);
static void FailedStepAfterSuccessRestore() => throw new GracefulException("simulated error");
@@ -419,9 +398,9 @@ public void GivenSecondInstallInATransactionTheFirstInstallShouldRollback(bool t
{
var source = GetTestLocalFeedPath();
- var (store, storeQuery, downloader, uninstaller, reporter, fileSystem) = Setup(
+ var (store, storeQuery, downloader, uninstaller, reporter, fileSystem, testDir) = Setup(
useMock: testMockBehaviorIsInSync,
- feeds: GetMockFeedsForSource(source));
+ includeLocalFeedInNugetConfig: false);
Action a = () =>
{
@@ -468,13 +447,19 @@ public void GivenFailureWhenInstallLocalToolsItWillRollbackPackageVersion(bool t
{
var source = GetTestLocalFeedPath();
- var (store, storeQuery, downloader, uninstaller, reporter, fileSystem) = Setup(
+ var (store, storeQuery, downloader, uninstaller, reporter, fileSystem, testDir) = Setup(
useMock: testMockBehaviorIsInSync,
- feeds: GetMockFeedsForSource(source));
+ includeLocalFeedInNugetConfig: false);
static void FailedStepAfterSuccessDownload() => throw new GracefulException("simulated error");
ISettings settings = Settings.LoadDefaultSettings(Directory.GetCurrentDirectory());
var localToolDownloadDir = Path.Combine(new DirectoryPath(SettingsUtility.GetGlobalPackagesFolder(settings)).ToString().Trim('"'), TestPackageId.ToString());
+ var localToolVersionDir = Path.Combine(localToolDownloadDir, TestPackageVersion.ToString());
+
+ if (fileSystem.Directory.Exists(localToolVersionDir))
+ {
+ fileSystem.Directory.Delete(localToolVersionDir, true);
+ }
Action a = () =>
{
@@ -489,12 +474,16 @@ public void GivenFailureWhenInstallLocalToolsItWillRollbackPackageVersion(bool t
targetFramework: _testTargetframework,
verifySignatures: false);
- fileSystem
- .Directory
+ fileSystem.Directory
.Exists(localToolDownloadDir)
.Should()
.BeTrue();
+ fileSystem.Directory
+ .Exists(localToolVersionDir)
+ .Should()
+ .BeTrue();
+
FailedStepAfterSuccessDownload();
t.Complete();
}
@@ -508,7 +497,7 @@ public void GivenFailureWhenInstallLocalToolsItWillRollbackPackageVersion(bool t
.Should()
.BeTrue();
- var localToolVersionDir = Path.Combine(localToolDownloadDir, TestPackageVersion.ToString());
+
fileSystem
.Directory
.Exists(localToolVersionDir)
@@ -523,9 +512,9 @@ public void GivenSecondInstallOfLocalToolItShouldNotThrowException(bool testMock
{
var source = GetTestLocalFeedPath();
- var (store, storeQuery, downloader, uninstaller, reporter, fileSystem) = Setup(
+ var (store, storeQuery, downloader, uninstaller, reporter, fileSystem, testDir) = Setup(
useMock: testMockBehaviorIsInSync,
- feeds: GetMockFeedsForSource(source));
+ includeLocalFeedInNugetConfig: false);
Action a = () =>
{
@@ -551,6 +540,8 @@ public void GivenSecondInstallOfLocalToolItShouldNotThrowException(bool testMock
t.Complete();
}
};
+
+ a();
}
[Theory]
@@ -558,11 +549,14 @@ public void GivenSecondInstallOfLocalToolItShouldNotThrowException(bool testMock
[InlineData(true)]
public void GivenSecondInstallWithoutATransactionTheFirstShouldNotRollback(bool testMockBehaviorIsInSync)
{
+ new RunExeCommand(Log, "dotnet", "nuget", "locals", "all", "--list")
+ .Execute().Should().Pass();
+
var source = GetTestLocalFeedPath();
- var (store, storeQuery, downloader, uninstaller, reporter, fileSystem) = Setup(
+ var (store, storeQuery, downloader, uninstaller, reporter, fileSystem, testDir) = Setup(
useMock: testMockBehaviorIsInSync,
- feeds: GetMockFeedsForSource(source));
+ includeLocalFeedInNugetConfig: false);
var package = downloader.InstallPackage(new PackageLocation(additionalFeeds: new[] { source }),
packageId: TestPackageId,
@@ -613,9 +607,9 @@ public void GivenAnInstalledPackageUninstallRemovesThePackage(bool testMockBehav
{
var source = GetTestLocalFeedPath();
- var (store, storeQuery, downloader, uninstaller, reporter, fileSystem) = Setup(
+ var (store, storeQuery, downloader, uninstaller, reporter, fileSystem, testDir) = Setup(
useMock: testMockBehaviorIsInSync,
- feeds: GetMockFeedsForSource(source),
+ includeLocalFeedInNugetConfig: false,
identiifer: testMockBehaviorIsInSync.ToString());
var package = downloader.InstallPackage(new PackageLocation(additionalFeeds: new[] { source }),
@@ -640,9 +634,9 @@ public void GivenAnInstalledPackageUninstallRollsbackWhenTransactionFails(bool t
{
var source = GetTestLocalFeedPath();
- var (store, storeQuery, downloader, uninstaller, reporter, fileSystem) = Setup(
+ var (store, storeQuery, downloader, uninstaller, reporter, fileSystem, testDir) = Setup(
useMock: testMockBehaviorIsInSync,
- feeds: GetMockFeedsForSource(source));
+ includeLocalFeedInNugetConfig: false);
var package = downloader.InstallPackage(
new PackageLocation(additionalFeeds: new[] { source }),
@@ -677,9 +671,9 @@ public void GivenAnInstalledPackageUninstallRemovesThePackageWhenTransactionComm
{
var source = GetTestLocalFeedPath();
- var (store, storeQuery, downloader, uninstaller, reporter, fileSystem) = Setup(
+ var (store, storeQuery, downloader, uninstaller, reporter, fileSystem, testDir) = Setup(
useMock: testMockBehaviorIsInSync,
- feeds: GetMockFeedsForSource(source));
+ includeLocalFeedInNugetConfig: false);
var package = downloader.InstallPackage(new PackageLocation(additionalFeeds: new[] { source }),
packageId: TestPackageId,
@@ -707,13 +701,11 @@ public void GivenAnInstalledPackageUninstallRemovesThePackageWhenTransactionComm
[InlineData(true)]
public void GivenAPackageNameWithDifferentCaseItCanInstallThePackage(bool testMockBehaviorIsInSync)
{
- var nugetConfigPath = GenerateRandomNugetConfigFilePath();
-
- var (store, storeQuery, downloader, uninstaller, reporter, fileSystem) = Setup(
+ var (store, storeQuery, downloader, uninstaller, reporter, fileSystem, testDir) = Setup(
useMock: testMockBehaviorIsInSync,
- writeLocalFeedToNugetConfig: nugetConfigPath);
+ includeLocalFeedInNugetConfig: true);
- var package = downloader.InstallPackage(new PackageLocation(nugetConfig: nugetConfigPath),
+ var package = downloader.InstallPackage(new PackageLocation(nugetConfig: testDir.WithFile("NuGet.config")),
packageId: new PackageId("GlObAl.TooL.coNsoLe.DemO"),
verbosity: TestVerbosity,
targetFramework: _testTargetframework,
@@ -728,8 +720,6 @@ public void GivenAPackageNameWithDifferentCaseItCanInstallThePackage(bool testMo
[Fact]
public void GivenARootWithNonAsciiCharacterInstallSucceeds()
{
- var nugetConfigPath = GenerateRandomNugetConfigFilePath();
-
var surrogate = char.ConvertFromUtf32(int.Parse("2A601", NumberStyles.HexNumber));
string nonAscii = "ab Ṱ̺̺̕o 田中さん åä," + surrogate;
@@ -737,7 +727,11 @@ public void GivenARootWithNonAsciiCharacterInstallSucceeds()
var reporter = new BufferedReporter();
var fileSystem = new FileSystemWrapper();
var store = new ToolPackageStoreAndQuery(new DirectoryPath(root.Path));
- WriteNugetConfigFileToPointToTheFeed(fileSystem, nugetConfigPath);
+
+ var nugetConfigPath = new FilePath(Path.Combine(root.Path, "NuGet.config"));
+
+ WriteNugetConfigFile(fileSystem, nugetConfigPath, true);
+
var testRuntimeJsonPath = Path.Combine(TestContext.Current.ToolsetUnderTest.SdkFolderUnderTest, "RuntimeIdentifierGraph.json");
var downloader = new ToolPackageDownloader(
@@ -765,15 +759,14 @@ public void GivenARootWithNonAsciiCharacterInstallSucceeds()
// repro https://github.com/dotnet/cli/issues/9409
public void GivenAComplexVersionRangeInstallSucceeds(bool testMockBehaviorIsInSync)
{
- var nugetConfigPath = GenerateRandomNugetConfigFilePath();
var emptySource = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
Directory.CreateDirectory(emptySource);
- var (store, storeQuery, downloader, uninstaller, reporter, fileSystem) = Setup(
+ var (store, storeQuery, downloader, uninstaller, reporter, fileSystem, testDir) = Setup(
useMock: testMockBehaviorIsInSync,
- writeLocalFeedToNugetConfig: nugetConfigPath);
+ includeLocalFeedInNugetConfig: true);
- var package = downloader.InstallPackage(new PackageLocation(nugetConfig: nugetConfigPath,
+ var package = downloader.InstallPackage(new PackageLocation(nugetConfig: testDir.WithFile("NuGet.config"),
additionalFeeds: new[] { emptySource }),
packageId: TestPackageId,
verbosity: TestVerbosity,
@@ -793,31 +786,16 @@ public void GivenAComplexVersionRangeInstallSucceeds(bool testMockBehaviorIsInSy
// repro https://github.com/dotnet/cli/issues/10101
public void GivenAPackageWithCasingAndenUSPOSIXInstallSucceeds(bool testMockBehaviorIsInSync)
{
- var nugetConfigPath = GenerateRandomNugetConfigFilePath();
+
var emptySource = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
Directory.CreateDirectory(emptySource);
var packageId = new PackageId("Global.Tool.Console.Demo.With.Casing");
var packageVersion = "2.0.4";
- var feed = new MockFeed
- {
- Type = MockFeedType.ImplicitAdditionalFeed,
- Uri = nugetConfigPath.Value,
- Packages = new List
- {
- new MockFeedPackage
- {
- PackageId = packageId.ToString(),
- Version = packageVersion,
- ToolCommandName = "DemoWithCasing",
- }
- }
- };
- var (store, storeQuery, downloader, uninstaller, reporter, fileSystem) = Setup(
+ var (store, storeQuery, downloader, uninstaller, reporter, fileSystem, testDir) = Setup(
useMock: testMockBehaviorIsInSync,
- feeds: new List { feed },
- writeLocalFeedToNugetConfig: nugetConfigPath);
+ includeLocalFeedInNugetConfig: true);
CultureInfo currentCultureBefore = CultureInfo.CurrentCulture;
try
@@ -826,7 +804,7 @@ public void GivenAPackageWithCasingAndenUSPOSIXInstallSucceeds(bool testMockBeha
IToolPackage package = null;
Action action = () => package = downloader.InstallPackage(
new PackageLocation(
- nugetConfig: nugetConfigPath,
+ nugetConfig: testDir.WithFile("NuGet.config"),
additionalFeeds: new[] { emptySource }),
packageId: packageId,
verbosity: TestVerbosity,
@@ -891,90 +869,10 @@ private static void AssertInstallRollBack(IFileSystem fileSystem, IToolPackageSt
.BeEmpty();
}
- private static FilePath GetUniqueTempProjectPathEachTest()
- {
- var tempProjectDirectory =
- new DirectoryPath(Path.GetTempPath()).WithSubDirectories(Path.GetRandomFileName());
- var tempProjectPath =
- tempProjectDirectory.WithFile(Path.GetRandomFileName() + ".csproj");
- return tempProjectPath;
- }
-
- private static List GetMockFeedsForConfigFile(FilePath? nugetConfig)
- {
- if (nugetConfig.HasValue)
- {
- return new List
- {
- new MockFeed
- {
- Type = MockFeedType.ExplicitNugetConfig,
- Uri = nugetConfig.Value.Value,
- Packages = new List
- {
- new MockFeedPackage
- {
- PackageId = TestPackageId.ToString(),
- Version = TestPackageVersion,
- ToolCommandName = "SimulatorCommand"
- }
- }
- }
- };
- }
- else
- {
- return new List();
- }
- }
-
- private static List GetMockFeedsForSource(string source)
- {
- return new List
- {
- new MockFeed
- {
- Type = MockFeedType.ImplicitAdditionalFeed,
- Uri = source,
- Packages = new List
- {
- new MockFeedPackage
- {
- PackageId = TestPackageId.ToString(),
- Version = TestPackageVersion,
- ToolCommandName = "SimulatorCommand"
- }
- }
- }
- };
- }
-
- private static List GetOfflineMockFeed()
- {
- return new List
- {
- new MockFeed
- {
- Type = MockFeedType.ImplicitAdditionalFeed,
- Uri = GetTestLocalFeedPath(),
- Packages = new List
- {
- new MockFeedPackage
- {
- PackageId = TestPackageId.ToString(),
- Version = TestPackageVersion,
- ToolCommandName = "SimulatorCommand"
- }
- }
- }
- };
- }
-
- private (IToolPackageStore, IToolPackageStoreQuery, IToolPackageDownloader, IToolPackageUninstaller, BufferedReporter, IFileSystem
+ private (IToolPackageStore, IToolPackageStoreQuery, IToolPackageDownloader, IToolPackageUninstaller, BufferedReporter, IFileSystem, DirectoryPath testDir
) Setup(
bool useMock,
- List feeds = null,
- FilePath? writeLocalFeedToNugetConfig = null,
+ bool includeLocalFeedInNugetConfig,
[CallerMemberName] string callingMethod = "",
string identiifer = null)
{
@@ -986,77 +884,72 @@ private static List GetOfflineMockFeed()
IToolPackageStoreQuery storeQuery;
IToolPackageDownloader downloader;
IToolPackageUninstaller uninstaller;
+
+ var nugetConfigPath = new FilePath(Path.Combine(root.Value, "NuGet.config"));
+
+ var toolsRoot = root.WithSubDirectories("tools");
+
+
if (useMock)
{
fileSystem = new FileSystemMockBuilder().Build();
var frameworksMap = new Dictionary>()
{ {TestPackageId, TestFrameworks } };
- WriteNugetConfigFileToPointToTheFeed(fileSystem, writeLocalFeedToNugetConfig);
- var toolPackageStoreMock = new ToolPackageStoreMock(root, fileSystem, frameworksMap);
- store = toolPackageStoreMock;
- storeQuery = toolPackageStoreMock;
- downloader = new ToolPackageDownloaderMock(
- store: toolPackageStoreMock,
- fileSystem: fileSystem,
- reporter: reporter,
- feeds: feeds == null
- ? GetMockFeedsForConfigFile(writeLocalFeedToNugetConfig)
- : feeds.Concat(GetMockFeedsForConfigFile(writeLocalFeedToNugetConfig)).ToList(),
- frameworksMap: frameworksMap);
- uninstaller = new ToolPackageUninstallerMock(fileSystem, toolPackageStoreMock);
+
+ WriteNugetConfigFile(fileSystem, nugetConfigPath, includeLocalFeedInNugetConfig);
+ var storeAndQuery = new ToolPackageStoreAndQuery(toolsRoot, fileSystem);
+ store = storeAndQuery;
+ storeQuery = storeAndQuery;
+ downloader = new ToolPackageDownloaderMock2(storeAndQuery,
+ runtimeJsonPathForTests: TestContext.GetRuntimeGraphFilePath(),
+ currentWorkingDirectory: root.Value,
+ fileSystem);
+
+ uninstaller = new ToolPackageUninstallerMock(fileSystem, storeAndQuery);
}
else
{
fileSystem = new FileSystemWrapper();
- WriteNugetConfigFileToPointToTheFeed(fileSystem, writeLocalFeedToNugetConfig);
- var toolPackageStore = new ToolPackageStoreAndQuery(root);
+ WriteNugetConfigFile(fileSystem, nugetConfigPath, includeLocalFeedInNugetConfig);
+ var toolPackageStore = new ToolPackageStoreAndQuery(toolsRoot);
store = toolPackageStore;
storeQuery = toolPackageStore;
var testRuntimeJsonPath = Path.Combine(TestContext.Current.ToolsetUnderTest.SdkFolderUnderTest, "RuntimeIdentifierGraph.json");
- downloader = new ToolPackageDownloader(store, testRuntimeJsonPath);
+ downloader = new ToolPackageDownloader(store, testRuntimeJsonPath, root.Value);
uninstaller = new ToolPackageUninstaller(store);
}
- store.Root.Value.Should().Be(Path.GetFullPath(root.Value));
+ store.Root.Value.Should().Be(Path.GetFullPath(toolsRoot.Value));
- return (store, storeQuery, downloader, uninstaller, reporter, fileSystem);
+ return (store, storeQuery, downloader, uninstaller, reporter, fileSystem, root);
}
- private static void WriteNugetConfigFileToPointToTheFeed(IFileSystem fileSystem, FilePath? filePath)
+ private static void WriteNugetConfigFile(IFileSystem fileSystem, FilePath? filePath, bool includeLocalFeedPath)
{
if (!filePath.HasValue) return;
fileSystem.Directory.CreateDirectory(filePath.Value.GetDirectoryPath().Value);
fileSystem.File.WriteAllText(filePath.Value.Value, FormatNuGetConfig(
- localFeedPath: GetTestLocalFeedPath()));
+ localFeedPath: includeLocalFeedPath ? GetTestLocalFeedPath() : null));
}
public static string FormatNuGetConfig(string localFeedPath)
{
- const string template = @"
+ string localFeed = string.IsNullOrEmpty(localFeedPath)
+ ? string.Empty
+ : $"";
+
+ return $@"
-
+{localFeed}
";
- return string.Format(template, localFeedPath);
- }
-
- private static FilePath GenerateRandomNugetConfigFilePath()
- {
- const string nugetConfigName = "nuget.config";
- var tempPathForNugetConfigWithWhiteSpace =
- Path.Combine(Path.GetTempPath(),
- Path.GetRandomFileName() + " " + Path.GetRandomFileName());
-
- FilePath nugetConfigFullPath =
- new(Path.GetFullPath(Path.Combine(tempPathForNugetConfigWithWhiteSpace, nugetConfigName)));
- return nugetConfigFullPath;
}
private static string GetTestLocalFeedPath() =>
@@ -1065,10 +958,14 @@ private static string GetTestLocalFeedPath() =>
private readonly string _testTargetframework = BundledTargetFramework.GetTargetFrameworkMoniker();
private const string TestPackageVersion = "1.0.4";
private static readonly PackageId TestPackageId = new("global.tool.console.demo");
- private static readonly IEnumerable TestFrameworks = new NuGetFramework[] { NuGetFramework.Parse("netcoreapp2.1") };
+ private static readonly IEnumerable TestFrameworks = new NuGetFramework[] { NuGetFramework.Parse(ToolPackageDownloaderMock2.DefaultTargetFramework) };
private static readonly VerbosityOptions TestVerbosity = new VerbosityOptions();
- public ToolPackageDownloaderTests(ITestOutputHelper log) : base(log)
+
+ private readonly TestToolBuilder ToolBuilder;
+
+ public ToolPackageDownloaderTests(ITestOutputHelper log, TestToolBuilder toolBuilder) : base(log)
{
+ ToolBuilder = toolBuilder;
}
}
}
diff --git a/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/MockFeedPackage.cs b/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/MockFeedPackage.cs
index ebc3599ff1e5..8f450c552cbd 100644
--- a/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/MockFeedPackage.cs
+++ b/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/MockFeedPackage.cs
@@ -10,5 +10,11 @@ public class MockFeedPackage
public string PackageId;
public string Version;
public string ToolCommandName;
+ public string ToolFormatVersion = "1";
+
+ ///
+ /// Key: Path inside package. Value: Contents of file
+ ///
+ public Dictionary AdditionalFiles { get; } = new();
}
}
diff --git a/test/dotnet.Tests/CommandTests/Workload/Install/MockNuGetPackageInstaller.cs b/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/MockNuGetPackageDownloader.cs
similarity index 67%
rename from test/dotnet.Tests/CommandTests/Workload/Install/MockNuGetPackageInstaller.cs
rename to test/Microsoft.DotNet.Tools.Tests.ComponentMocks/MockNuGetPackageDownloader.cs
index 47b10d934b80..ff1a37dc9e69 100644
--- a/test/dotnet.Tests/CommandTests/Workload/Install/MockNuGetPackageInstaller.cs
+++ b/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/MockNuGetPackageDownloader.cs
@@ -12,6 +12,8 @@ namespace Microsoft.DotNet.Cli.NuGetPackageDownloader
{
internal class MockNuGetPackageDownloader : INuGetPackageDownloader
{
+ public static readonly string MOCK_FEEDS_TEXT = "{MockFeeds}";
+
private readonly string _downloadPath;
private readonly bool _manifestDownload;
private NuGetVersion _lastPackageVersion = new("1.0.0");
@@ -25,6 +27,8 @@ internal class MockNuGetPackageDownloader : INuGetPackageDownloader
public HashSet PackageIdsToNotFind { get; set; } = new HashSet(StringComparer.OrdinalIgnoreCase);
+ public string MockFeedWithNoPackages { get; set; }
+
public MockNuGetPackageDownloader(string dotnetRoot = null, bool manifestDownload = false, IEnumerable packageVersions = null)
{
_manifestDownload = manifestDownload;
@@ -34,9 +38,22 @@ public MockNuGetPackageDownloader(string dotnetRoot = null, bool manifestDownloa
Directory.CreateDirectory(_downloadPath);
}
- _packageVersions = packageVersions;
+ _packageVersions = packageVersions ?? [new NuGetVersion("1.0.42")];
+
+ PackageIdsToNotFind.Add("does.not.exist");
+ }
+
+ bool ShouldFindPackage(PackageId packageId, PackageSourceLocation packageSourceLocation)
+ {
+ if (PackageIdsToNotFind.Contains(packageId.ToString()) ||
+ (!string.IsNullOrEmpty(MockFeedWithNoPackages) && packageSourceLocation.SourceFeedOverrides.Length == 1 && packageSourceLocation.SourceFeedOverrides[0] == MockFeedWithNoPackages))
+ {
+ return false;
+ }
+ return true;
}
+
public Task DownloadPackageAsync(PackageId packageId,
NuGetVersion packageVersion = null,
PackageSourceLocation packageSourceLocation = null,
@@ -47,9 +64,9 @@ public Task DownloadPackageAsync(PackageId packageId,
{
DownloadCallParams.Add((packageId, packageVersion, downloadFolder, packageSourceLocation));
- if (PackageIdsToNotFind.Contains(packageId.ToString()))
+ if (!ShouldFindPackage(packageId, packageSourceLocation))
{
- return Task.FromException(new NuGetPackageNotFoundException("Package not found: " + packageId.ToString()));
+ return Task.FromException(new NuGetPackageNotFoundException(string.Format(CliStrings.IsNotFoundInNuGetFeeds, packageId, MOCK_FEEDS_TEXT)));
}
var path = Path.Combine(_downloadPath, "mock.nupkg");
@@ -65,7 +82,7 @@ public Task DownloadPackageAsync(PackageId packageId,
// Do not write this file twice in parallel
}
}
- _lastPackageVersion = packageVersion ?? new NuGetVersion("1.0.42");
+ _lastPackageVersion = packageVersion ?? _packageVersions.Max();
return Task.FromResult(path);
}
@@ -91,16 +108,40 @@ public Task> ExtractPackageAsync(string packagePath, Directo
return Task.FromResult(new List() as IEnumerable);
}
- public Task> GetLatestPackageVersions(PackageId packageId, int numberOfResults, PackageSourceLocation packageSourceLocation = null, bool includePreview = false) => Task.FromResult(_packageVersions ?? Enumerable.Empty());
+ public Task> GetLatestPackageVersions(PackageId packageId, int numberOfResults, PackageSourceLocation packageSourceLocation = null, bool includePreview = false)
+ {
+
+ if (!ShouldFindPackage(packageId, packageSourceLocation))
+ {
+ return Task.FromResult(Enumerable.Empty());
+ }
+
+ return Task.FromResult(_packageVersions ?? Enumerable.Empty());
+ }
public Task GetLatestPackageVersion(PackageId packageId, PackageSourceLocation packageSourceLocation = null, bool includePreview = false)
{
- return Task.FromResult(new NuGetVersion("10.0.0"));
+ if (!ShouldFindPackage(packageId, packageSourceLocation))
+ {
+ return Task.FromException(new NuGetPackageNotFoundException(string.Format(CliStrings.IsNotFoundInNuGetFeeds, packageId, MOCK_FEEDS_TEXT)));
+ }
+
+ return Task.FromResult(_packageVersions.Max());
}
public Task GetBestPackageVersionAsync(PackageId packageId, VersionRange versionRange, PackageSourceLocation packageSourceLocation = null)
{
- return Task.FromResult(new NuGetVersion("10.0.0"));
+ if (!ShouldFindPackage(packageId, packageSourceLocation))
+ {
+ return Task.FromException(new NuGetPackageNotFoundException(string.Format(CliStrings.IsNotFoundInNuGetFeeds, packageId, MOCK_FEEDS_TEXT)));
+ }
+
+ var bestVersion = versionRange.FindBestMatch(_packageVersions);
+ if (bestVersion == null)
+ {
+ bestVersion = versionRange.MinVersion;
+ }
+ return Task.FromResult(bestVersion);
}
diff --git a/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/ProjectRestorerMock.cs b/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/ProjectRestorerMock.cs
index ca27d789562e..0d7126f17304 100644
--- a/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/ProjectRestorerMock.cs
+++ b/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/ProjectRestorerMock.cs
@@ -12,189 +12,12 @@
namespace Microsoft.DotNet.Tools.Tests.ComponentMocks
{
- internal class ProjectRestorerMock : IProjectRestorer
+ internal class ProjectRestorerMock
{
public const string FakeEntrypointName = "SimulatorEntryPoint.dll";
public const string DefaultToolCommandName = "SimulatorCommand";
public const string DefaultPackageName = "global.tool.console.demo";
public const string DefaultPackageVersion = "1.0.4";
public const string FakeCommandSettingsFileName = "FakeDotnetToolSettings.json";
-
- private readonly IFileSystem _fileSystem;
- private readonly IReporter _reporter;
- private readonly List _feeds;
-
- public ProjectRestorerMock(
- IFileSystem fileSystem,
- IReporter reporter = null,
- List feeds = null)
- {
- _fileSystem = fileSystem ?? throw new ArgumentNullException(nameof(fileSystem));
- _reporter = reporter;
-
- if (feeds == null)
- {
- _feeds = new List();
- _feeds.Add(new MockFeed
- {
- Type = MockFeedType.FeedFromGlobalNugetConfig,
- Packages = new List
- {
- new MockFeedPackage
- {
- PackageId = DefaultPackageName,
- Version = DefaultPackageVersion,
- ToolCommandName = DefaultToolCommandName,
- }
- }
- });
- }
- else
- {
- _feeds = feeds;
- }
- }
-
- public void Restore(FilePath project,
- PackageLocation packageLocation,
- string verbosity = null)
- {
- string packageId;
- VersionRange versionRange;
- string targetFramework;
- DirectoryPath assetJsonOutput;
- try
- {
- // The mock installer wrote a mock project file containing id;version;framework;stageDirectory
- var contents = _fileSystem.File.ReadAllText(project.Value);
- var tokens = contents.Split(';');
- if (tokens.Length != 4)
- {
- throw new ToolPackageException(CliCommandStrings.ToolInstallationRestoreFailed);
- }
-
- packageId = tokens[0];
- versionRange = VersionRange.Parse(tokens[1]);
- targetFramework = tokens[2];
- assetJsonOutput = new DirectoryPath(tokens[3]);
- }
- catch (IOException)
- {
- throw new ToolPackageException(CliCommandStrings.ToolInstallationRestoreFailed);
- }
-
- if (string.IsNullOrEmpty(packageId))
- {
- throw new ToolPackageException(CliCommandStrings.ToolInstallationRestoreFailed);
- }
-
- var feedPackage = GetPackage(
- packageId,
- versionRange,
- packageLocation.NugetConfig,
- packageLocation.RootConfigDirectory);
-
- var packageVersion = feedPackage.Version;
- targetFramework = string.IsNullOrEmpty(targetFramework) ? "targetFramework" : targetFramework;
-
- var fakeExecutableSubDirectory = Path.Combine(
- packageId.ToLowerInvariant(),
- packageVersion.ToLowerInvariant(),
- "tools",
- targetFramework,
- Constants.AnyRid);
- var fakeExecutablePath = Path.Combine(fakeExecutableSubDirectory, FakeEntrypointName);
-
- _fileSystem.Directory.CreateDirectory(Path.Combine(assetJsonOutput.Value, fakeExecutableSubDirectory));
- _fileSystem.File.CreateEmptyFile(Path.Combine(assetJsonOutput.Value, fakeExecutablePath));
- _fileSystem.File.WriteAllText(
- assetJsonOutput.WithFile("project.assets.json").Value,
- fakeExecutablePath);
- _fileSystem.File.WriteAllText(
- assetJsonOutput.WithFile(FakeCommandSettingsFileName).Value,
- JsonSerializer.Serialize(new { Name = feedPackage.ToolCommandName }));
- }
-
- public MockFeedPackage GetPackage(
- string packageId,
- VersionRange versionRange,
- FilePath? nugetConfig = null,
- DirectoryPath? rootConfigDirectory = null)
- {
- var allPackages = _feeds
- .Where(feed =>
- {
- if (nugetConfig == null)
- {
- return SimulateNugetSearchNugetConfigAndMatch(
- rootConfigDirectory,
- feed);
- }
- else
- {
- return ExcludeOtherFeeds(nugetConfig.Value, feed);
- }
- })
- .SelectMany(f => f.Packages)
- .Where(f => f.PackageId == packageId)
- .ToList();
-
- var bestVersion = versionRange.FindBestMatch(allPackages.Select(p => NuGetVersion.Parse(p.Version)));
-
- var package = allPackages.FirstOrDefault(p => NuGetVersion.Parse(p.Version).Equals(bestVersion));
-
- if (package == null)
- {
- _reporter?.WriteLine($"Error: failed to restore package {packageId}.");
- throw new ToolPackageException(CliCommandStrings.ToolInstallationRestoreFailed);
- }
-
- return package;
- }
-
- ///
- /// Simulate NuGet search nuget config from parent directories.
- /// Assume all nuget.config has Clear
- /// And then filter against mock feed
- ///
- private bool SimulateNugetSearchNugetConfigAndMatch(
- DirectoryPath? rootConfigDirectory,
- MockFeed feed)
- {
- if (rootConfigDirectory != null)
- {
- var probedNugetConfig = EnumerateDefaultAllPossibleNuGetConfig(rootConfigDirectory.Value)
- .FirstOrDefault(possibleNugetConfig =>
- _fileSystem.File.Exists(possibleNugetConfig.Value));
-
- if (!Equals(probedNugetConfig, default(FilePath)))
- {
- return (feed.Type == MockFeedType.FeedFromLookUpNugetConfig) ||
- (feed.Type == MockFeedType.ImplicitAdditionalFeed) ||
- (feed.Type == MockFeedType.FeedFromLookUpNugetConfig
- && feed.Uri == probedNugetConfig.Value);
- }
- }
-
- return feed.Type != MockFeedType.ExplicitNugetConfig
- && feed.Type != MockFeedType.FeedFromLookUpNugetConfig;
- }
-
- private static IEnumerable EnumerateDefaultAllPossibleNuGetConfig(DirectoryPath probStart)
- {
- DirectoryPath? currentSearchDirectory = probStart;
- while (currentSearchDirectory.HasValue)
- {
- var tryNugetConfig = currentSearchDirectory.Value.WithFile("nuget.config");
- yield return tryNugetConfig;
- currentSearchDirectory = currentSearchDirectory.Value.GetParentPathNullable();
- }
- }
-
- private static bool ExcludeOtherFeeds(FilePath nugetConfig, MockFeed f)
- {
- return f.Type == MockFeedType.ImplicitAdditionalFeed
- || (f.Type == MockFeedType.ExplicitNugetConfig && f.Uri == nugetConfig.Value);
- }
}
}
diff --git a/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/ToolPackageDownloaderMock.cs b/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/ToolPackageDownloaderMock.cs
index 4aa8504a6d32..e6f0d0e1265c 100644
--- a/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/ToolPackageDownloaderMock.cs
+++ b/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/ToolPackageDownloaderMock.cs
@@ -15,6 +15,11 @@
namespace Microsoft.DotNet.Tools.Tests.ComponentMocks
{
+ // This class should be superceded by ToolPackageDownloaderMock2. The Mock2 version derives from ToolPackageDownloaderBase, so a lot less
+ // business logic needs to be duplicated.
+ // The class here on the other hand has a lot of code/behavior copied from the product and they could get out of sync.
+ // So ideally we should migrate existing tests that use this class to the Mock2 version, then delete this version and rename the Mock2 version
+ // to ToolPackageDownlnoaderMock.
internal class ToolPackageDownloaderMock : IToolPackageDownloader
{
private readonly IToolPackageStore _toolPackageStore;
@@ -174,7 +179,7 @@ public IToolPackage InstallPackage(PackageLocation packageLocation, PackageId pa
{
Id = packageId,
Version = NuGetVersion.Parse(feedPackage.Version),
- Command = new RestoredCommand(new ToolCommandName(feedPackage.ToolCommandName), "runner", executable),
+ Command = new ToolCommand(new ToolCommandName(feedPackage.ToolCommandName), "runner", executable),
Warnings = Array.Empty(),
PackagedShims = Array.Empty()
};
@@ -336,13 +341,17 @@ private class TestToolPackage : IToolPackage
public NuGetVersion Version { get; set; }
public DirectoryPath PackageDirectory { get; set; }
- public RestoredCommand Command { get; set; }
+ public ToolCommand Command { get; set; }
public IEnumerable Warnings { get; set; }
public IReadOnlyList PackagedShims { get; set; }
public IEnumerable Frameworks => throw new NotImplementedException();
+
+ public PackageId ResolvedPackageId { get; set; }
+
+ public NuGetVersion ResolvedPackageVersion { get; set; }
}
}
}
diff --git a/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/ToolPackageDownloaderMock2.cs b/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/ToolPackageDownloaderMock2.cs
new file mode 100644
index 000000000000..02a9acbe608b
--- /dev/null
+++ b/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/ToolPackageDownloaderMock2.cs
@@ -0,0 +1,192 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Microsoft.DotNet.Cli;
+using Microsoft.DotNet.Cli.NuGetPackageDownloader;
+using Microsoft.DotNet.Cli.ToolPackage;
+using Microsoft.Extensions.EnvironmentAbstractions;
+using NuGet.Commands.Restore;
+using NuGet.Packaging;
+using NuGet.Versioning;
+
+namespace Microsoft.DotNet.Tools.Tests.ComponentMocks
+{
+ internal class ToolPackageDownloaderMock2 : ToolPackageDownloaderBase
+ {
+ public const string DefaultToolCommandName = "SimulatorCommand";
+ public const string FakeEntrypointName = "SimulatorEntryPoint.dll";
+ public const string DefaultPackageVersion = "1.0.4";
+ public const string DefaultTargetFramework = "net6.0";
+
+ public Action? DownloadCallback { get; set; }
+
+ public string? MockFeedWithNoPackages { get; set; }
+
+ List? _packages = null;
+
+ public ToolPackageDownloaderMock2(IToolPackageStore store, string runtimeJsonPathForTests, string currentWorkingDirectory, IFileSystem fileSystem) : base(store, runtimeJsonPathForTests, currentWorkingDirectory, fileSystem)
+ {
+ }
+
+ public void AddMockPackage(MockFeedPackage package)
+ {
+ if (_packages == null)
+ {
+ _packages = new List();
+ };
+ _packages.Add(package);
+ }
+
+ MockFeedPackage? GetPackage(PackageId packageId, NuGetVersion version)
+ {
+ if (_packages == null)
+ {
+ return new MockFeedPackage()
+ {
+ PackageId = packageId.ToString(),
+ Version = version.ToString(),
+ ToolCommandName = DefaultToolCommandName
+ };
+ }
+
+ var matchingPackages = _packages.Where(p => p.PackageId == packageId.ToString() && new NuGetVersion(p.Version) >= version);
+ if (!matchingPackages.Any())
+ {
+ return null;
+ }
+ return matchingPackages.MaxBy(p => new NuGetVersion(p.Version));
+ }
+
+ protected override void CreateAssetFile(PackageId packageId, NuGetVersion version, DirectoryPath packagesRootPath, string assetFilePath, string runtimeJsonGraph, string? targetFramework = null)
+ {
+ var mockPackage = GetPackage(packageId, version);
+ if (mockPackage == null)
+ {
+ throw new InvalidOperationException("Mock feed package not found");
+ }
+
+ var entryPointSimple = Path.GetFileNameWithoutExtension(FakeEntrypointName);
+
+ var extraFiles = string.Join(Environment.NewLine, mockPackage.AdditionalFiles.Select(f => $"\"{f.Key}\":{{}},"));
+
+ var assetFileContents = $$"""
+ {
+ "version": 3,
+ "targets": {
+ "{{DefaultTargetFramework}}/{{RuntimeInformation.RuntimeIdentifier}}": {
+ "{{packageId}}/{{version}}": {
+ "type": "package",
+ "tools": {
+ {{extraFiles}}
+ "tools/{{DefaultTargetFramework}}/any/DotnetToolSettings.xml": {},
+ "tools/{{DefaultTargetFramework}}/any/{{entryPointSimple}}.deps.json": {},
+ "tools/{{DefaultTargetFramework}}/any/{{entryPointSimple}}.dll": {},
+ "tools/{{DefaultTargetFramework}}/any/{{entryPointSimple}}.pdb": {},
+ "tools/{{DefaultTargetFramework}}/any/{{entryPointSimple}}.runtimeconfig.json": {}
+ }
+ }
+ }
+ },
+ "libraries": {},
+ "projectFileDependencyGroups": {}
+ }
+ """;
+
+ _fileSystem.File.WriteAllText(assetFilePath, assetFileContents);
+ }
+ protected override INuGetPackageDownloader CreateNuGetPackageDownloader(bool verifySignatures, VerbosityOptions verbosity, RestoreActionConfig? restoreActionConfig)
+ {
+ List packageVersions;
+ if (_packages == null)
+ {
+ packageVersions = [new NuGetVersion(DefaultPackageVersion)];
+ }
+ else
+ {
+ packageVersions = _packages.Select(p => new NuGetVersion(p.Version)).ToList();
+ }
+
+ return new MockNuGetPackageDownloader(packageVersions: packageVersions)
+ {
+ MockFeedWithNoPackages = MockFeedWithNoPackages
+ };
+ }
+
+ protected override NuGetVersion DownloadAndExtractPackage(PackageId packageId, INuGetPackageDownloader nugetPackageDownloader, string packagesRootPath,
+ NuGetVersion packageVersion, PackageSourceLocation packageSourceLocation, bool includeUnlisted = false)
+ {
+
+ var package = GetPackage(packageId, packageVersion);
+ if (package == null)
+ {
+ throw new NuGetPackageNotFoundException(string.Format(CliStrings.IsNotFoundInNuGetFeeds, $"Version {packageVersion} of {packageId}", MockNuGetPackageDownloader.MOCK_FEEDS_TEXT));
+ }
+
+ NuGetVersion resolvedVersion = new NuGetVersion(packageVersion);
+
+ var versionFolderPathResolver = new VersionFolderPathResolver(packagesRootPath);
+ var nupkgDir = versionFolderPathResolver.GetInstallPath(packageId.ToString(), resolvedVersion);
+
+ var fakeExecutableSubDirectory = Path.Combine(
+ nupkgDir,
+ "tools",
+ DefaultTargetFramework,
+ "any");
+
+ var fakeExecutablePath = Path.Combine(fakeExecutableSubDirectory, FakeEntrypointName);
+
+ TransactionalAction.Run(() =>
+ {
+ _fileSystem.Directory.CreateDirectory(fakeExecutableSubDirectory);
+ _fileSystem.File.CreateEmptyFile(fakeExecutablePath);
+ _fileSystem.File.WriteAllText(Path.Combine(fakeExecutableSubDirectory, "DotnetToolSettings.xml"),
+ $"""
+
+
+
+
+
+ """);
+
+ foreach (var additionalFile in package.AdditionalFiles)
+ {
+ var resolvedPath = Path.Combine(nupkgDir, additionalFile.Key);
+ if (!_fileSystem.Directory.Exists(Path.GetDirectoryName(resolvedPath)!))
+ {
+ _fileSystem.Directory.CreateDirectory(Path.GetDirectoryName(resolvedPath)!);
+ }
+ _fileSystem.File.WriteAllText(resolvedPath, additionalFile.Value);
+ }
+
+ if (DownloadCallback != null)
+ {
+ DownloadCallback();
+ }
+
+ }, rollback: () =>
+ {
+ if (_fileSystem.Directory.Exists(nupkgDir))
+ {
+ _fileSystem.Directory.Delete(nupkgDir, true);
+ }
+ });
+
+ return resolvedVersion;
+ }
+ protected override ToolConfiguration GetToolConfiguration(PackageId id, DirectoryPath packageDirectory, DirectoryPath assetsJsonParentDirectory)
+ {
+ return new ToolConfiguration(DefaultToolCommandName, FakeEntrypointName, "dotnet");
+
+ }
+ protected override bool IsPackageInstalled(PackageId packageId, NuGetVersion packageVersion, string packagesRootPath)
+ {
+ var versionFolderPathResolver = new VersionFolderPathResolver(packagesRootPath);
+ var nupkgDir = versionFolderPathResolver.GetInstallPath(packageId.ToString(), packageVersion);
+
+ return _fileSystem.Directory.Exists(nupkgDir);
+ }
+ }
+}
diff --git a/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/ToolPackageMock.cs b/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/ToolPackageMock.cs
index 78c9c25900f1..12cbe1319ef5 100644
--- a/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/ToolPackageMock.cs
+++ b/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/ToolPackageMock.cs
@@ -16,7 +16,7 @@ namespace Microsoft.DotNet.Tools.Tests.ComponentMocks
internal class ToolPackageMock : IToolPackage
{
private IFileSystem _fileSystem;
- private Lazy _command;
+ private Lazy _command;
private IEnumerable _warnings;
private readonly IReadOnlyList _packagedShims;
@@ -33,7 +33,7 @@ public ToolPackageMock(
Id = id;
Version = version ?? throw new ArgumentNullException(nameof(version));
PackageDirectory = packageDirectory;
- _command = new Lazy(GetCommand);
+ _command = new Lazy(GetCommand);
_warnings = warnings ?? new List();
_packagedShims = packagedShims ?? new List();
Frameworks = frameworks ?? new List();
@@ -44,7 +44,7 @@ public ToolPackageMock(
public NuGetVersion Version { get; private set; }
public DirectoryPath PackageDirectory { get; private set; }
- public RestoredCommand Command
+ public ToolCommand Command
{
get
{
@@ -64,7 +64,11 @@ public IReadOnlyList PackagedShims
public IEnumerable Frameworks { get; private set; }
- private RestoredCommand GetCommand()
+ public PackageId ResolvedPackageId { get; private set; }
+
+ public NuGetVersion ResolvedPackageVersion { get; private set; }
+
+ private ToolCommand GetCommand()
{
try
{
@@ -72,17 +76,12 @@ private RestoredCommand GetCommand()
// Currently only "dotnet" commands are supported
var executablePath = _fileSystem.File.ReadAllText(Path.Combine(PackageDirectory.Value, "project.assets.json"));
- var fakeSettingFile = _fileSystem.File.ReadAllText(Path.Combine(PackageDirectory.Value, ProjectRestorerMock.FakeCommandSettingsFileName));
+ var settingsFilePath = Path.Combine(PackageDirectory.Value, @$"{Id}\{Version}\tools\net6.0\any", "DotnetToolSettings.xml");
- string name;
- using (JsonDocument doc = JsonDocument.Parse(fakeSettingFile))
- {
- JsonElement root = doc.RootElement;
- name = root.GetProperty("Name").GetString();
- }
+ var configuration = ToolConfigurationDeserializer.Deserialize(settingsFilePath, _fileSystem);
- return new RestoredCommand(
- new ToolCommandName(name),
+ return new ToolCommand(
+ new ToolCommandName(configuration.CommandName),
"dotnet",
PackageDirectory.WithFile(executablePath));
}
diff --git a/test/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildADesktopExe.cs b/test/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildADesktopExe.cs
index 992b02d8c289..715573502ac3 100644
--- a/test/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildADesktopExe.cs
+++ b/test/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildADesktopExe.cs
@@ -844,9 +844,10 @@ public void It_generates_supportedRuntime_when_there_is_appconfig_with_supported
Path.Combine(testAsset.TestRoot, "App.Config"));
XElement root = BuildTestAssetGetAppConfig(testAsset);
+
root.Elements("startup").Single()
.Elements("supportedRuntime").Single()
- .Should().HaveAttribute("version", "v999", "It should keep existing supportedRuntime");
+ .Should().HaveAttributeWithValue("version", "v999", "It should keep existing supportedRuntime");
}
[WindowsOnlyFact]
diff --git a/test/Microsoft.NET.Sdk.Razor.Tests/ReferenceResolverTest.cs b/test/Microsoft.NET.Sdk.Razor.Tests/ReferenceResolverTest.cs
index 732a3b175a4f..20d4f6095707 100644
--- a/test/Microsoft.NET.Sdk.Razor.Tests/ReferenceResolverTest.cs
+++ b/test/Microsoft.NET.Sdk.Razor.Tests/ReferenceResolverTest.cs
@@ -188,7 +188,7 @@ public void Resolve_Works_WhenAssemblyReferencesAreRecursive_ButAlsoReferencesMv
var assemblies = resolver.ResolveAssemblies();
// Assert
- assemblies.Should().Contain("MyCMS", "MyCMS.Core", "MyCoolLibrary", "PresentationFramework", "ReachFramework");
+ assemblies.Should().Contain(["MyCMS", "MyCMS.Core", "MyCoolLibrary", "PresentationFramework", "ReachFramework"]);
}
public AssemblyItem CreateAssemblyItem(string name, bool isFrameworkReference = false)
diff --git a/test/Microsoft.NET.Sdk.Razor.Tool.Tests/Microsoft.NET.Sdk.Razor.Tool.Tests.csproj b/test/Microsoft.NET.Sdk.Razor.Tool.Tests/Microsoft.NET.Sdk.Razor.Tool.Tests.csproj
index 7d2e76bf9dd6..0cabc4330a7c 100644
--- a/test/Microsoft.NET.Sdk.Razor.Tool.Tests/Microsoft.NET.Sdk.Razor.Tool.Tests.csproj
+++ b/test/Microsoft.NET.Sdk.Razor.Tool.Tests/Microsoft.NET.Sdk.Razor.Tool.Tests.csproj
@@ -8,6 +8,11 @@
MicrosoftAspNetCore
+
+
+ $(NoWarn);CA2025
+
+
diff --git a/test/Microsoft.NET.TestFramework/Commands/TestCommand.cs b/test/Microsoft.NET.TestFramework/Commands/TestCommand.cs
index a31b826d40d8..952bf87e76a8 100644
--- a/test/Microsoft.NET.TestFramework/Commands/TestCommand.cs
+++ b/test/Microsoft.NET.TestFramework/Commands/TestCommand.cs
@@ -153,8 +153,11 @@ public virtual CommandResult Execute(IEnumerable args)
{
Log.WriteLine($"❌{line}");
});
-
- var display = $"dotnet {string.Join(" ", spec.Arguments)}";
+
+ string fileToShow = Path.GetFileNameWithoutExtension(spec.FileName!).Equals("dotnet", StringComparison.OrdinalIgnoreCase) ?
+ "dotnet" :
+ spec.FileName!;
+ var display = $"{fileToShow} {string.Join(" ", spec.Arguments)}";
Log.WriteLine($"Executing '{display}':");
var result = ((Command)command).Execute(ProcessStartedHandler);
diff --git a/test/Microsoft.NET.TestFramework/Mock/FileSystemMockBuilder.cs b/test/Microsoft.NET.TestFramework/Mock/FileSystemMockBuilder.cs
index 4e6b19125c68..6f103306c263 100644
--- a/test/Microsoft.NET.TestFramework/Mock/FileSystemMockBuilder.cs
+++ b/test/Microsoft.NET.TestFramework/Mock/FileSystemMockBuilder.cs
@@ -97,7 +97,11 @@ public MockFileSystemModel(string? temporaryFolder,
public bool TryGetNodeParent(string path, out DirectoryNode current)
{
PathModel pathModel = CreateFullPathModel(path);
- current = Files.Volume[pathModel.Volume];
+ if (!Files.Volume.TryGetValue(pathModel.Volume, out current!))
+ {
+ current = new DirectoryNode();
+ current = Files.Volume.GetOrAdd(pathModel.Volume, current);
+ }
if (!Files.Volume.ContainsKey(pathModel.Volume))
{
diff --git a/test/Microsoft.NET.ToolPack.Tests/GivenThatWeWantToPackAToolProject.cs b/test/Microsoft.NET.ToolPack.Tests/GivenThatWeWantToPackAToolProject.cs
index b178cb8dfdfa..dc14779c933d 100644
--- a/test/Microsoft.NET.ToolPack.Tests/GivenThatWeWantToPackAToolProject.cs
+++ b/test/Microsoft.NET.ToolPack.Tests/GivenThatWeWantToPackAToolProject.cs
@@ -22,7 +22,7 @@ private string SetupNuGetPackage(bool multiTarget, string packageType = null, [C
{
TestAsset helloWorldAsset = _testAssetsManager
- .CopyTestAsset("PortableTool", callingMethod + multiTarget)
+ .CopyTestAsset("PortableTool", callingMethod + multiTarget + (packageType ?? ""))
.WithSource()
.WithProjectChanges(project =>
{
diff --git a/test/Microsoft.NET.ToolPack.Tests/GivenThatWeWantToPackAToolSelfContainedProject.cs b/test/Microsoft.NET.ToolPack.Tests/GivenThatWeWantToPackAToolSelfContainedProject.cs
index 3171b8ad174c..317d6f56b260 100644
--- a/test/Microsoft.NET.ToolPack.Tests/GivenThatWeWantToPackAToolSelfContainedProject.cs
+++ b/test/Microsoft.NET.ToolPack.Tests/GivenThatWeWantToPackAToolSelfContainedProject.cs
@@ -17,17 +17,19 @@ public GivenThatWeWantToPackAToolSelfContainedProject(ITestOutputHelper log) : b
}
- [Fact]
- public void It_should_fail_with_error_message()
- {
- TestAsset helloWorldAsset = CreateAsset();
+ // TODO: Add tests for Self-contained / AOT tools, which are now supported
- var packCommand = new PackCommand(Log, helloWorldAsset.TestRoot);
+ //[Fact]
+ //public void It_should_fail_with_error_message()
+ //{
+ // TestAsset helloWorldAsset = CreateAsset();
- CommandResult result = packCommand.Execute("--property:SelfContained=true");
- result.ExitCode.Should().NotBe(0);
- result.StdOut.Should().Contain(Strings.PackAsToolCannotSupportSelfContained);
- }
+ // var packCommand = new PackCommand(Log, helloWorldAsset.TestRoot);
+
+ // CommandResult result = packCommand.Execute("--property:SelfContained=true");
+ // result.ExitCode.Should().NotBe(0);
+ // result.StdOut.Should().Contain(Strings.PackAsToolCannotSupportSelfContained);
+ //}
// Reproduce of https://github.com/dotnet/cli/issues/10607
[Fact]
diff --git a/test/dotnet.Tests/CommandFactoryTests/GivenALocalToolsCommandResolver.cs b/test/dotnet.Tests/CommandFactoryTests/GivenALocalToolsCommandResolver.cs
index b98bd10c551a..b0ff2d4f0bd4 100644
--- a/test/dotnet.Tests/CommandFactoryTests/GivenALocalToolsCommandResolver.cs
+++ b/test/dotnet.Tests/CommandFactoryTests/GivenALocalToolsCommandResolver.cs
@@ -93,7 +93,7 @@ public void WhenResolveWithNoArgumentsItReturnsNull()
_fileSystem.Directory.CreateDirectory(_nugetGlobalPackagesFolder.Value);
_fileSystem.File.CreateEmptyFile(fakeExecutable.Value);
_localToolsResolverCache.Save(
- new Dictionary
+ new Dictionary
{
[new RestoredCommandIdentifier(
new PackageId("local.tool.console.a"),
@@ -101,7 +101,7 @@ [new RestoredCommandIdentifier(
NuGetFramework.Parse(BundledTargetFramework.GetTargetFrameworkMoniker()),
Constants.AnyRid,
toolCommandNameA)]
- = new RestoredCommand(toolCommandNameA, "dotnet", fakeExecutable)
+ = new ToolCommand(toolCommandNameA, "dotnet", fakeExecutable)
});
var localToolsCommandResolver = new LocalToolsCommandResolver(
@@ -126,7 +126,7 @@ public void WhenNuGetGlobalPackageLocationIsCleanedAfterRestoreItShowError()
_fileSystem.Directory.CreateDirectory(_nugetGlobalPackagesFolder.Value);
_fileSystem.File.CreateEmptyFile(fakeExecutable.Value);
_localToolsResolverCache.Save(
- new Dictionary
+ new Dictionary
{
[new RestoredCommandIdentifier(
new PackageId("local.tool.console.a"),
@@ -134,7 +134,7 @@ [new RestoredCommandIdentifier(
NuGetFramework.Parse(BundledTargetFramework.GetTargetFrameworkMoniker()),
Constants.AnyRid,
toolCommandNameA)]
- = new RestoredCommand(toolCommandNameA, "dotnet", fakeExecutable)
+ = new ToolCommand(toolCommandNameA, "dotnet", fakeExecutable)
});
var localToolsCommandResolver = new LocalToolsCommandResolver(
@@ -191,7 +191,7 @@ public void ItCanResolveAmbiguityCausedByPrefixDotnetDash()
_fileSystem.File.CreateEmptyFile(fakeExecutableA.Value);
_fileSystem.File.CreateEmptyFile(fakeExecutableDotnetA.Value);
_localToolsResolverCache.Save(
- new Dictionary
+ new Dictionary
{
[new RestoredCommandIdentifier(
new PackageId("local.tool.console.a"),
@@ -199,14 +199,14 @@ [new RestoredCommandIdentifier(
NuGetFramework.Parse(BundledTargetFramework.GetTargetFrameworkMoniker()),
Constants.AnyRid,
new ToolCommandName("a"))]
- = new RestoredCommand(new ToolCommandName("a"), "dotnet", fakeExecutableA),
+ = new ToolCommand(new ToolCommandName("a"), "dotnet", fakeExecutableA),
[new RestoredCommandIdentifier(
new PackageId("local.tool.console.dotnet.a"),
NuGetVersion.Parse("1.0.4"),
NuGetFramework.Parse(BundledTargetFramework.GetTargetFrameworkMoniker()),
Constants.AnyRid,
new ToolCommandName("dotnet-a"))]
- = new RestoredCommand(new ToolCommandName("dotnet-a"), "dotnet", fakeExecutableDotnetA)
+ = new ToolCommand(new ToolCommandName("dotnet-a"), "dotnet", fakeExecutableDotnetA)
});
var localToolsCommandResolver = new LocalToolsCommandResolver(
diff --git a/test/dotnet.Tests/CommandTests/Tool/Install/ToolInstallGlobalOrToolPathCommandTests.cs b/test/dotnet.Tests/CommandTests/Tool/Install/ToolInstallGlobalOrToolPathCommandTests.cs
index 8b30715d3342..43184db6b930 100644
--- a/test/dotnet.Tests/CommandTests/Tool/Install/ToolInstallGlobalOrToolPathCommandTests.cs
+++ b/test/dotnet.Tests/CommandTests/Tool/Install/ToolInstallGlobalOrToolPathCommandTests.cs
@@ -32,6 +32,7 @@ public class ToolInstallGlobalOrToolPathCommandTests: SdkTest
private readonly ToolPackageUninstallerMock _toolPackageUninstallerMock;
private readonly CreateShellShimRepository _createShellShimRepository;
private readonly CreateToolPackageStoresAndDownloaderAndUninstaller _createToolPackageStoreDownloaderUninstaller;
+ private readonly ToolPackageDownloaderMock2 _toolPackageDownloader;
private readonly string _toolsDirectory;
private readonly EnvironmentPathInstructionMock _environmentPathInstructionMock;
private readonly ParseResult _parseResult;
@@ -56,7 +57,7 @@ public ToolInstallGlobalOrToolPathCommandTests(ITestOutputHelper log): base(log)
_pathToPlaceShim = Path.Combine(_temporaryDirectory, "pathToPlace");
_fileSystem.Directory.CreateDirectory(_pathToPlaceShim);
_pathToPlacePackages = _pathToPlaceShim + "Packages";
- var toolPackageStoreMock = new ToolPackageStoreMock(new DirectoryPath(_pathToPlacePackages), _fileSystem);
+ var toolPackageStoreMock = new ToolPackageStoreAndQuery(new DirectoryPath(_pathToPlacePackages), _fileSystem);
_toolPackageStore = toolPackageStoreMock;
_toolPackageStoreQuery = toolPackageStoreMock;
_createShellShimRepository =
@@ -72,7 +73,12 @@ public ToolInstallGlobalOrToolPathCommandTests(ITestOutputHelper log): base(log)
new DirectoryPath(_toolsDirectory),
_fileSystem);
_toolPackageUninstallerMock = new ToolPackageUninstallerMock(_fileSystem, store);
- _createToolPackageStoreDownloaderUninstaller = (location, forwardArguments, workingDirectory) => (_toolPackageStore, _toolPackageStoreQuery, CreateToolPackageDownloader(), _toolPackageUninstallerMock);
+ _toolPackageDownloader = new ToolPackageDownloaderMock2(_toolPackageStore,
+ runtimeJsonPathForTests: TestContext.GetRuntimeGraphFilePath(),
+ currentWorkingDirectory: null,
+ fileSystem: _fileSystem);
+
+ _createToolPackageStoreDownloaderUninstaller = (location, forwardArguments, workingDirectory) => (_toolPackageStore, _toolPackageStoreQuery, _toolPackageDownloader, _toolPackageUninstallerMock);
_parseResult = Parser.Instance.Parse($"dotnet tool install -g {PackageId}");
@@ -171,38 +177,20 @@ public void WhenRunFromToolInstallRedirectCommandWithPackageIdItShouldCreateVali
public void WhenRunWithSourceItShouldFindOnlyTheProvidedSource()
{
const string sourcePath1 = "https://sourceOne.com";
- const string sourcePath2 = "https://sourceTwo.com";
ParseResult result = Parser.Instance.Parse($"dotnet tool install -g {PackageId} --source {sourcePath1}");
- var toolPackageDownloader = CreateToolPackageDownloader(
- feeds: new List
- {
- new MockFeed
- {
- Type = MockFeedType.ImplicitAdditionalFeed,
- Uri = sourcePath2,
- Packages = new List
- {
- new MockFeedPackage
- {
- PackageId = PackageId,
- Version = PackageVersion,
- ToolCommandName = ToolCommandName,
- }
- }
- }
- });
+ _toolPackageDownloader.MockFeedWithNoPackages = sourcePath1;
var toolInstallGlobalOrToolPathCommand = new ToolInstallGlobalOrToolPathCommand(
result,
_packageId,
- (location, forwardArguments, currentWorkingDirectory) => (_toolPackageStore, _toolPackageStoreQuery, toolPackageDownloader, _toolPackageUninstallerMock),
+ _createToolPackageStoreDownloaderUninstaller,
_createShellShimRepository,
_environmentPathInstructionMock,
_reporter);
// Should not find the package because it is in the wrong feed
- var ex = Assert.Throws(() => toolInstallGlobalOrToolPathCommand.Execute());
+ var ex = Assert.Throws(() => toolInstallGlobalOrToolPathCommand.Execute());
ex.Message.Should().Contain(PackageId);
}
@@ -212,28 +200,10 @@ public void WhenRunWithPackageIdWithSourceItShouldCreateValidShim()
const string sourcePath = "http://mysource.com";
ParseResult result = Parser.Instance.Parse($"dotnet tool install -g {PackageId} --add-source {sourcePath}");
- var toolToolPackageDownloader = CreateToolPackageDownloader(
- feeds: new List {
- new MockFeed
- {
- Type = MockFeedType.ImplicitAdditionalFeed,
- Uri = sourcePath,
- Packages = new List
- {
- new MockFeedPackage
- {
- PackageId = PackageId,
- Version = PackageVersion,
- ToolCommandName = ToolCommandName,
- }
- }
- }
- });
-
var toolInstallGlobalOrToolPathCommand = new ToolInstallGlobalOrToolPathCommand(
result,
_packageId,
- (location, forwardArguments, currentWorkingDirectory) => (_toolPackageStore, _toolPackageStoreQuery, toolToolPackageDownloader, _toolPackageUninstallerMock),
+ _createToolPackageStoreDownloaderUninstaller,
_createShellShimRepository,
_environmentPathInstructionMock,
_reporter);
@@ -268,28 +238,25 @@ public void WhenRunWithPackageIdItShouldShowPathInstruction()
[Fact]
public void WhenRunWithPackageIdPackageFormatIsNotFullySupportedItShouldShowPathInstruction()
{
- const string Warning = "WARNING";
- var injectedWarnings = new Dictionary>()
+ _toolPackageDownloader.AddMockPackage(new MockFeedPackage()
{
- [new PackageId(PackageId)] = new List() { Warning }
- };
-
- var toolPackageDownloader = new ToolPackageDownloaderMock(
- fileSystem: _fileSystem,
- store: _toolPackageStore,
- warningsMap: injectedWarnings);
+ PackageId = PackageId,
+ Version = PackageVersion,
+ ToolCommandName = ToolCommandName,
+ ToolFormatVersion = "42",
+ });
var toolInstallGlobalOrToolPathCommand = new ToolInstallGlobalOrToolPathCommand(
_parseResult,
_packageId,
- (location, forwardArguments, currentWorkingDirectory) => (_toolPackageStore, _toolPackageStoreQuery, toolPackageDownloader, _toolPackageUninstallerMock),
+ _createToolPackageStoreDownloaderUninstaller,
_createShellShimRepository,
_environmentPathInstructionMock,
_reporter);
toolInstallGlobalOrToolPathCommand.Execute().Should().Be(0);
- _reporter.Lines.First().Should().Be(Warning.Yellow());
+ _reporter.Lines.First().Should().Be(CliStrings.FormatVersionIsHigher.Yellow());
_reporter.Lines.Skip(1).First().Should().Be(EnvironmentPathInstructionMock.MockInstructionText);
}
@@ -298,14 +265,12 @@ public void GivenFailedPackageInstallWhenRunWithPackageIdItShouldFail()
{
const string ErrorMessage = "Simulated error";
- var toolPackageDownloader =
- CreateToolPackageDownloader(
- downloadCallback: () => throw new ToolPackageException(ErrorMessage));
+ _toolPackageDownloader.DownloadCallback = () => throw new ToolPackageException(ErrorMessage);
var toolInstallGlobalOrToolPathCommand = new ToolInstallGlobalOrToolPathCommand(
_parseResult,
_packageId,
- (location, forwardArguments, currentWorkingDirectory) => (_toolPackageStore, _toolPackageStoreQuery, toolPackageDownloader, _toolPackageUninstallerMock),
+ _createToolPackageStoreDownloaderUninstaller,
_createShellShimRepository,
_environmentPathInstructionMock,
_reporter);
@@ -313,10 +278,7 @@ public void GivenFailedPackageInstallWhenRunWithPackageIdItShouldFail()
Action a = () => toolInstallGlobalOrToolPathCommand.Execute();
a.Should().Throw().And.Message
- .Should().Contain(
- ErrorMessage +
- Environment.NewLine +
- string.Format(CliCommandStrings.ToolInstallationFailedWithRestoreGuidance, PackageId));
+ .Should().Contain(ErrorMessage);
_fileSystem.Directory.Exists(Path.Combine(_pathToPlacePackages, PackageId)).Should().BeFalse();
}
@@ -347,14 +309,13 @@ public void GivenCreateShimItShouldHaveNoBrokenFolderOnDisk()
[Fact]
public void GivenInCorrectToolConfigurationWhenRunWithPackageIdItShouldFail()
{
- var toolPackageDownloader =
- CreateToolPackageDownloader(
- downloadCallback: () => throw new ToolConfigurationException("Simulated error"));
+
+ _toolPackageDownloader.DownloadCallback = () => throw new ToolConfigurationException("Simulated error");
var toolInstallGlobalOrToolPathCommand = new ToolInstallGlobalOrToolPathCommand(
_parseResult,
_packageId,
- (location, forwardArguments, currentWorkingDirectory) => (_toolPackageStore, _toolPackageStoreQuery, toolPackageDownloader, _toolPackageUninstallerMock),
+ _createToolPackageStoreDownloaderUninstaller,
_createShellShimRepository,
_environmentPathInstructionMock,
_reporter);
@@ -498,13 +459,14 @@ public void WhenInstallTheSpecificSameVersionTwiceItShouldNoop()
[Fact]
public void WhenInstallWithHigherVersionItShouldUpdate()
{
- IToolPackageDownloader toolToolPackageDownloader = GetToolPackageDownloaderWithHigherVersionInFeed();
+ AddHigherToolPackageVersionToFeed();
+
ParseResult result = Parser.Instance.Parse($"dotnet tool install -g {PackageId} --version {PackageVersion}");
var toolInstallGlobalOrToolPathCommand = new ToolInstallGlobalOrToolPathCommand(
result,
_packageId,
- (location, forwardArguments, currentWorkingDirectory) => (_toolPackageStore, _toolPackageStoreQuery, toolToolPackageDownloader, _toolPackageUninstallerMock),
+ _createToolPackageStoreDownloaderUninstaller,
_createShellShimRepository,
new EnvironmentPathInstructionMock(_reporter, _pathToPlaceShim, true),
_reporter);
@@ -526,7 +488,7 @@ public void WhenInstallWithHigherVersionItShouldUpdate()
var toolInstallGlobalOrToolPathCommand2 = new ToolInstallGlobalOrToolPathCommand(
result2,
_packageId,
- (location, forwardArguments, currentWorkingDirectory) => (_toolPackageStore, _toolPackageStoreQuery, toolToolPackageDownloader, _toolPackageUninstallerMock),
+ _createToolPackageStoreDownloaderUninstaller,
_createShellShimRepository,
new EnvironmentPathInstructionMock(_reporter, _pathToPlaceShim, true),
_reporter);
@@ -546,13 +508,14 @@ public void WhenInstallWithHigherVersionItShouldUpdate()
[Fact]
public void WhenInstallWithLowerVersionWithAllowDowngradeOptionItShouldDowngrade()
{
- IToolPackageDownloader toolToolPackageDownloader = GetToolPackageDownloaderWithLowerVersionInFeed();
+ AddLowerToolPackageVersionToFeed();
+
ParseResult result = Parser.Instance.Parse($"dotnet tool install -g {PackageId} --version {PackageVersion}");
var toolInstallGlobalOrToolPathCommand = new ToolInstallGlobalOrToolPathCommand(
result,
_packageId,
- (location, forwardArguments, currentWorkingDirectory) => (_toolPackageStore, _toolPackageStoreQuery, toolToolPackageDownloader, _toolPackageUninstallerMock),
+ _createToolPackageStoreDownloaderUninstaller,
_createShellShimRepository,
new EnvironmentPathInstructionMock(_reporter, _pathToPlaceShim, true),
_reporter);
@@ -574,7 +537,7 @@ public void WhenInstallWithLowerVersionWithAllowDowngradeOptionItShouldDowngrade
var toolInstallGlobalOrToolPathCommand2 = new ToolInstallGlobalOrToolPathCommand(
result2,
_packageId,
- (location, forwardArguments, currentWorkingDirectory) => (_toolPackageStore, _toolPackageStoreQuery, toolToolPackageDownloader, _toolPackageUninstallerMock),
+ _createToolPackageStoreDownloaderUninstaller,
_createShellShimRepository,
new EnvironmentPathInstructionMock(_reporter, _pathToPlaceShim, true),
_reporter);
@@ -594,13 +557,14 @@ public void WhenInstallWithLowerVersionWithAllowDowngradeOptionItShouldDowngrade
[Fact]
public void WhenInstallWithLowerVersionItShouldFail()
{
- IToolPackageDownloader toolToolPackageDownloader = GetToolPackageDownloaderWithLowerVersionInFeed();
+ AddLowerToolPackageVersionToFeed();
+
ParseResult result = Parser.Instance.Parse($"dotnet tool install -g {PackageId} --version {PackageVersion}");
var toolInstallGlobalOrToolPathCommand = new ToolInstallGlobalOrToolPathCommand(
result,
_packageId,
- (location, forwardArguments, currentWorkingDirectory) => (_toolPackageStore, _toolPackageStoreQuery, toolToolPackageDownloader, _toolPackageUninstallerMock),
+ _createToolPackageStoreDownloaderUninstaller,
_createShellShimRepository,
new EnvironmentPathInstructionMock(_reporter, _pathToPlaceShim, true),
_reporter);
@@ -622,7 +586,7 @@ public void WhenInstallWithLowerVersionItShouldFail()
var toolInstallGlobalOrToolPathCommand2 = new ToolInstallGlobalOrToolPathCommand(
result2,
_packageId,
- (location, forwardArguments, currentWorkingDirectory) => (_toolPackageStore, _toolPackageStoreQuery, toolToolPackageDownloader, _toolPackageUninstallerMock),
+ _createToolPackageStoreDownloaderUninstaller,
_createShellShimRepository,
new EnvironmentPathInstructionMock(_reporter, _pathToPlaceShim, true),
_reporter);
@@ -711,14 +675,14 @@ public void WhenRunWithoutValidVersionUnlistedToolItShouldThrow()
[Fact]
public void WhenRunWithPrereleaseItShouldSucceed()
{
- IToolPackageDownloader toolToolPackageDownloader = GetToolToolPackageDownloaderWithPreviewInFeed();
+ AddPreviewToolPackageVersionToFeed();
ParseResult result = Parser.Instance.Parse($"dotnet tool install -g {PackageId} --prerelease");
var toolInstallGlobalOrToolPathCommand = new ToolInstallGlobalOrToolPathCommand(
result,
_packageId,
- (location, forwardArguments, currentWorkingDirectory) => (_toolPackageStore, _toolPackageStoreQuery, toolToolPackageDownloader, _toolPackageUninstallerMock),
+ _createToolPackageStoreDownloaderUninstaller,
_createShellShimRepository,
_environmentPathInstructionMock,
_reporter);
@@ -738,14 +702,14 @@ public void WhenRunWithPrereleaseItShouldSucceed()
[Fact]
public void WhenRunWithPrereleaseAndPackageVersionItShouldThrow()
{
- IToolPackageDownloader toolToolPackageDownloader = GetToolToolPackageDownloaderWithPreviewInFeed();
+ AddPreviewToolPackageVersionToFeed();
ParseResult result = Parser.Instance.Parse($"dotnet tool install -g {PackageId} --version 2.0 --prerelease");
var toolInstallGlobalOrToolPathCommand = new ToolInstallGlobalOrToolPathCommand(
result,
_packageId,
- (location, forwardArguments, currentWorkingDirectory) => (_toolPackageStore, _toolPackageStoreQuery, toolToolPackageDownloader, _toolPackageUninstallerMock),
+ _createToolPackageStoreDownloaderUninstaller,
_createShellShimRepository,
_environmentPathInstructionMock,
_reporter);
@@ -754,88 +718,57 @@ public void WhenRunWithPrereleaseAndPackageVersionItShouldThrow()
a.Should().Throw();
}
- private IToolPackageDownloader GetToolToolPackageDownloaderWithPreviewInFeed()
+ private void AddPreviewToolPackageVersionToFeed()
{
- var toolToolPackageDownloader = CreateToolPackageDownloader(
- feeds: new List
- {
- new MockFeed
- {
- Type = MockFeedType.ImplicitAdditionalFeed,
- Packages = new List
- {
- new MockFeedPackage
- {
- PackageId = PackageId,
- Version = "1.0.4",
- ToolCommandName = "SimulatorCommand"
- },
- new MockFeedPackage
- {
- PackageId = PackageId,
- Version = "2.0.1-preview1",
- ToolCommandName = "SimulatorCommand"
- }
- }
- }
- });
- return toolToolPackageDownloader;
+ _toolPackageDownloader.AddMockPackage(new MockFeedPackage
+ {
+ PackageId = PackageId,
+ Version = "1.0.4",
+ ToolCommandName = "SimulatorCommand"
+ });
+
+ _toolPackageDownloader.AddMockPackage(new MockFeedPackage
+ {
+ PackageId = PackageId,
+ Version = "2.0.1-preview1",
+ ToolCommandName = "SimulatorCommand"
+ });
}
- private IToolPackageDownloader GetToolPackageDownloaderWithLowerVersionInFeed()
+
+ private void AddLowerToolPackageVersionToFeed()
{
- var toolToolPackageDownloader = CreateToolPackageDownloader(
- feeds: new List
- {
- new MockFeed
- {
- Type = MockFeedType.ImplicitAdditionalFeed,
- Packages = new List
- {
- new MockFeedPackage
- {
- PackageId = PackageId,
- Version = "1.0.4",
- ToolCommandName = "SimulatorCommand"
- },
- new MockFeedPackage
- {
- PackageId = PackageId,
- Version = "1.0.0",
- ToolCommandName = "SimulatorCommand"
- }
- }
- }
- });
- return toolToolPackageDownloader;
+ _toolPackageDownloader.AddMockPackage(new MockFeedPackage
+ {
+ PackageId = PackageId,
+ Version = "1.0.4",
+ ToolCommandName = "SimulatorCommand"
+ });
+
+ _toolPackageDownloader.AddMockPackage(new MockFeedPackage
+ {
+ PackageId = PackageId,
+ Version = "1.0.0",
+ ToolCommandName = "SimulatorCommand"
+ });
}
- private IToolPackageDownloader GetToolPackageDownloaderWithHigherVersionInFeed()
+
+ private void AddHigherToolPackageVersionToFeed()
{
- var toolToolPackageDownloader = CreateToolPackageDownloader(
- feeds: new List
- {
- new MockFeed
- {
- Type = MockFeedType.ImplicitAdditionalFeed,
- Packages = new List
- {
- new MockFeedPackage
- {
- PackageId = PackageId,
- Version = "1.0.4",
- ToolCommandName = "SimulatorCommand"
- },
- new MockFeedPackage
- {
- PackageId = PackageId,
- Version = "2.0.0",
- ToolCommandName = "SimulatorCommand"
- }
- }
- }
- });
- return toolToolPackageDownloader;
+ _toolPackageDownloader.AddMockPackage(new MockFeedPackage
+ {
+ PackageId = PackageId,
+ Version = "1.0.4",
+ ToolCommandName = "SimulatorCommand"
+ });
+
+ _toolPackageDownloader.AddMockPackage(new MockFeedPackage
+ {
+ PackageId = PackageId,
+ Version = "2.0.0",
+ ToolCommandName = "SimulatorCommand"
+ });
}
[Fact]
@@ -843,6 +776,13 @@ public void WhenRunWithoutAMatchingRangeItShouldFail()
{
ParseResult result = Parser.Instance.Parse($"dotnet tool install -g {PackageId} --version [5.0,10.0]");
+ _toolPackageDownloader.AddMockPackage(new MockFeedPackage()
+ {
+ PackageId = PackageId,
+ Version = PackageVersion,
+ ToolCommandName = ToolCommandName,
+ });
+
var toolInstallGlobalOrToolPathCommand = new ToolInstallGlobalOrToolPathCommand(
result,
_packageId,
@@ -854,9 +794,7 @@ public void WhenRunWithoutAMatchingRangeItShouldFail()
Action a = () => toolInstallGlobalOrToolPathCommand.Execute();
a.Should().Throw().And.Message
- .Should().Contain(
- CliCommandStrings.ToolInstallationRestoreFailed +
- Environment.NewLine + string.Format(CliCommandStrings.ToolInstallationFailedWithRestoreGuidance, PackageId));
+ .Should().Contain(string.Format(CliStrings.IsNotFoundInNuGetFeeds, $"Version 5.0 of {PackageId}", "{MockFeeds}"));
_fileSystem.Directory.Exists(Path.Combine(_pathToPlacePackages, PackageId)).Should().BeFalse();
}
@@ -921,26 +859,29 @@ public void WhenInstallItDoesNotSkipNuGetPackageVerfication()
[Fact]
public void AndPackagedShimIsProvidedWhenRunWithPackageIdItCreateShimUsingPackagedShim()
{
- var extension = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".exe" : string.Empty;
- var prepackagedShimPath = Path.Combine(_temporaryDirectory, ToolCommandName + extension);
- var tokenToIdentifyPackagedShim = "packagedShim";
- _fileSystem.File.WriteAllText(prepackagedShimPath, tokenToIdentifyPackagedShim);
+
+ string toolTargetRuntimeIdentifier = OperatingSystem.IsWindows() ? "win-x64" : RuntimeInformation.RuntimeIdentifier;
+
+ var tokenToIdentifyPackagedShim = $"{toolTargetRuntimeIdentifier}-tool";
var result = Parser.Instance.Parse($"dotnet tool install --tool-path /tmp/folder {PackageId}");
- var packagedShimsMap = new Dictionary>
+
+ var mockPackage = new MockFeedPackage()
{
- [new PackageId(PackageId)] = new[] { new FilePath(prepackagedShimPath) }
+ PackageId = PackageId,
+ Version = PackageVersion,
+ ToolCommandName = ToolCommandName
};
+ mockPackage.AdditionalFiles[$"tools/{ToolPackageDownloaderMock2.DefaultTargetFramework}/any/shims/{toolTargetRuntimeIdentifier}/{ToolCommandName}{EnvironmentInfo.ExecutableExtension}"] = tokenToIdentifyPackagedShim;
+
+ _toolPackageDownloader.AddMockPackage(mockPackage);
+
var installCommand = new ToolInstallGlobalOrToolPathCommand(
result,
_packageId,
- (location, forwardArguments, currentWorkingDirectory) => (_toolPackageStore, _toolPackageStoreQuery, new ToolPackageDownloaderMock(
- fileSystem: _fileSystem,
- store: _toolPackageStore,
- packagedShimsMap: packagedShimsMap,
- reporter: _reporter), _toolPackageUninstallerMock),
+ _createToolPackageStoreDownloaderUninstaller,
_createShellShimRepository,
new EnvironmentPathInstructionMock(_reporter, _pathToPlaceShim),
_reporter);
@@ -987,17 +928,6 @@ public void WhenRunWithArchOptionItDownloadsAppHostTemplate()
nugetPackageDownloader.DownloadCallParams.First().Item1.Should().Be(new PackageId("microsoft.netcore.app.host.win-arm64"));
}
- private IToolPackageDownloader CreateToolPackageDownloader(
- List feeds = null,
- Action downloadCallback = null)
- {
- return new ToolPackageDownloaderMock(fileSystem: _fileSystem,
- store: _toolPackageStore,
- reporter: _reporter,
- feeds: feeds,
- downloadCallback: downloadCallback);
- }
-
private string ExpectedCommandPath()
{
var extension = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".exe" : string.Empty;
diff --git a/test/dotnet.Tests/CommandTests/Tool/Install/ToolInstallLocalCommandTests.cs b/test/dotnet.Tests/CommandTests/Tool/Install/ToolInstallLocalCommandTests.cs
index e1871f2ca072..5a213c91acab 100644
--- a/test/dotnet.Tests/CommandTests/Tool/Install/ToolInstallLocalCommandTests.cs
+++ b/test/dotnet.Tests/CommandTests/Tool/Install/ToolInstallLocalCommandTests.cs
@@ -297,7 +297,7 @@ public void GivenManifestFileConflictItShouldNotAddToCache()
NuGetFramework.Parse(BundledTargetFramework.GetTargetFrameworkMoniker()),
Constants.AnyRid,
_toolCommandNameA),
- out RestoredCommand restoredCommand
+ out ToolCommand restoredCommand
).Should().BeFalse("it should not add to cache if add to manifest failed. " +
"But restore do not need to 'revert' since it just set in nuget global directory");
}
@@ -377,7 +377,7 @@ public void WhenRunWithPrereleaseAndPackageVersionItShouldSucceed()
NuGetFramework.Parse(BundledTargetFramework.GetTargetFrameworkMoniker()),
Constants.AnyRid,
addedPackage.CommandNames.Single()),
- out RestoredCommand restoredCommand
+ out ToolCommand restoredCommand
).Should().BeTrue();
_fileSystem.File.Exists(restoredCommand.Executable.Value);
@@ -500,7 +500,7 @@ private void AssertDefaultInstallSuccess()
NuGetFramework.Parse(BundledTargetFramework.GetTargetFrameworkMoniker()),
Constants.AnyRid,
addedPackage.CommandNames.Single()),
- out RestoredCommand restoredCommand
+ out ToolCommand restoredCommand
).Should().BeTrue();
_fileSystem.File.Exists(restoredCommand.Executable.Value);
diff --git a/test/dotnet.Tests/CommandTests/Tool/List/ToolListGlobalOrToolPathCommandTests.cs b/test/dotnet.Tests/CommandTests/Tool/List/ToolListGlobalOrToolPathCommandTests.cs
index cdcd5dedda5f..2f5840f20df2 100644
--- a/test/dotnet.Tests/CommandTests/Tool/List/ToolListGlobalOrToolPathCommandTests.cs
+++ b/test/dotnet.Tests/CommandTests/Tool/List/ToolListGlobalOrToolPathCommandTests.cs
@@ -114,7 +114,7 @@ public void GivenASingleInstalledPackageItPrintsThePackage()
CreateMockToolPackage(
"test.tool",
"1.3.5-preview",
- new RestoredCommand(new ToolCommandName("foo"), "dotnet", new FilePath("tool"))
+ new ToolCommand(new ToolCommandName("foo"), "dotnet", new FilePath("tool"))
)
});
@@ -135,17 +135,17 @@ public void GivenMultipleInstalledPackagesItPrintsThePackages()
CreateMockToolPackage(
"test.tool",
"1.3.5-preview",
- new RestoredCommand(new ToolCommandName("foo"), "dotnet", new FilePath("tool"))
+ new ToolCommand(new ToolCommandName("foo"), "dotnet", new FilePath("tool"))
),
CreateMockToolPackage(
"another.tool",
"2.7.3",
- new RestoredCommand(new ToolCommandName("bar"), "dotnet", new FilePath("tool"))
+ new ToolCommand(new ToolCommandName("bar"), "dotnet", new FilePath("tool"))
),
CreateMockToolPackage(
"some.tool",
"1.0.0",
- new RestoredCommand(new ToolCommandName("fancy-foo"), "dotnet", new FilePath("tool"))
+ new ToolCommand(new ToolCommandName("fancy-foo"), "dotnet", new FilePath("tool"))
)
});
@@ -167,12 +167,12 @@ public void GivenMultipleInstalledPackagesItPrintsThePackagesForJsonFormat()
CreateMockToolPackage(
"test.tool",
"1.3.5-preview",
- new RestoredCommand(new ToolCommandName("foo"), "dotnet", new FilePath("tool"))
+ new ToolCommand(new ToolCommandName("foo"), "dotnet", new FilePath("tool"))
),
CreateMockToolPackage(
"another.tool",
"2.7.3",
- new RestoredCommand(new ToolCommandName("bar"), "dotnet", new FilePath("tool"))
+ new ToolCommand(new ToolCommandName("bar"), "dotnet", new FilePath("tool"))
)
});
@@ -207,7 +207,7 @@ public void GivenAPackageWithMultipleCommandsItListsThem()
CreateMockToolPackage(
"test.tool",
"1.3.5-preview",
- new RestoredCommand(new ToolCommandName("foo"), "dotnet", new FilePath("tool")))
+ new ToolCommand(new ToolCommandName("foo"), "dotnet", new FilePath("tool")))
});
var command = CreateCommand(store.Object, "-g");
@@ -227,13 +227,13 @@ public void GivenABrokenPackageItPrintsWarning()
CreateMockToolPackage(
"test.tool",
"1.3.5-preview",
- new RestoredCommand(new ToolCommandName("foo"), "dotnet", new FilePath("tool"))
+ new ToolCommand(new ToolCommandName("foo"), "dotnet", new FilePath("tool"))
),
CreateMockBrokenPackage("another.tool", "2.7.3"),
CreateMockToolPackage(
"some.tool",
"1.0.0",
- new RestoredCommand(new ToolCommandName("fancy-foo"), "dotnet", new FilePath("tool"))
+ new ToolCommand(new ToolCommandName("fancy-foo"), "dotnet", new FilePath("tool"))
)
});
@@ -249,7 +249,7 @@ public void GivenABrokenPackageItPrintsWarning()
"broken").Yellow()));
}
- private IToolPackage CreateMockToolPackage(string id, string version, RestoredCommand command)
+ private IToolPackage CreateMockToolPackage(string id, string version, ToolCommand command)
{
var package = new Mock(MockBehavior.Strict);
@@ -269,17 +269,17 @@ public void GivenPackageIdArgItPrintsThatPackage()
CreateMockToolPackage(
"test.tool",
"1.3.5-preview",
- new RestoredCommand(new ToolCommandName("foo"), "dotnet", new FilePath("tool"))
+ new ToolCommand(new ToolCommandName("foo"), "dotnet", new FilePath("tool"))
),
CreateMockToolPackage(
"another.tool",
"2.7.3",
- new RestoredCommand(new ToolCommandName("bar"), "dotnet", new FilePath("tool"))
+ new ToolCommand(new ToolCommandName("bar"), "dotnet", new FilePath("tool"))
),
CreateMockToolPackage(
"some.tool",
"1.0.0",
- new RestoredCommand(new ToolCommandName("fancy-foo"), "dotnet", new FilePath("tool"))
+ new ToolCommand(new ToolCommandName("fancy-foo"), "dotnet", new FilePath("tool"))
)
});
@@ -300,7 +300,7 @@ public void GivenNotInstalledPackageItPrintsEmpty()
CreateMockToolPackage(
"test.tool",
"1.3.5-preview",
- new RestoredCommand(new ToolCommandName("foo"), "dotnet", new FilePath("tool"))
+ new ToolCommand(new ToolCommandName("foo"), "dotnet", new FilePath("tool"))
)
});
diff --git a/test/dotnet.Tests/CommandTests/Tool/Restore/ToolRestoreCommandTests.cs b/test/dotnet.Tests/CommandTests/Tool/Restore/ToolRestoreCommandTests.cs
index 5f3610d1b8ec..fa5ec522ab3b 100644
--- a/test/dotnet.Tests/CommandTests/Tool/Restore/ToolRestoreCommandTests.cs
+++ b/test/dotnet.Tests/CommandTests/Tool/Restore/ToolRestoreCommandTests.cs
@@ -140,7 +140,7 @@ public void WhenRunItCanSaveCommandsToCache()
_packageVersionA,
NuGetFramework.Parse(BundledTargetFramework.GetTargetFrameworkMoniker()),
Constants.AnyRid,
- _toolCommandNameA), out RestoredCommand restoredCommand)
+ _toolCommandNameA), out ToolCommand restoredCommand)
.Should().BeTrue();
_fileSystem.File.Exists(restoredCommand.Executable.Value)
diff --git a/test/dotnet.Tests/CommandTests/Tool/Restore/ToolRestoreCommandWithMultipleNugetConfigTests.cs b/test/dotnet.Tests/CommandTests/Tool/Restore/ToolRestoreCommandWithMultipleNugetConfigTests.cs
index fbcff27f2ad7..4db59dbac6dc 100644
--- a/test/dotnet.Tests/CommandTests/Tool/Restore/ToolRestoreCommandWithMultipleNugetConfigTests.cs
+++ b/test/dotnet.Tests/CommandTests/Tool/Restore/ToolRestoreCommandWithMultipleNugetConfigTests.cs
@@ -145,7 +145,7 @@ public void WhenManifestPackageAreFromDifferentDirectoryItCanFindTheRightNugetCo
_packageVersionA,
NuGetFramework.Parse(BundledTargetFramework.GetTargetFrameworkMoniker()),
Constants.AnyRid,
- _toolCommandNameA), out RestoredCommand _)
+ _toolCommandNameA), out ToolCommand _)
.Should().BeTrue();
_localToolsResolverCache.TryLoad(
@@ -154,7 +154,7 @@ public void WhenManifestPackageAreFromDifferentDirectoryItCanFindTheRightNugetCo
_packageVersionB,
NuGetFramework.Parse(BundledTargetFramework.GetTargetFrameworkMoniker()),
Constants.AnyRid,
- _toolCommandNameB), out RestoredCommand _)
+ _toolCommandNameB), out ToolCommand _)
.Should().BeTrue();
}
diff --git a/test/dotnet.Tests/CommandTests/Tool/Run/ToolRunCommandTests.cs b/test/dotnet.Tests/CommandTests/Tool/Run/ToolRunCommandTests.cs
index aa309d74d0c5..21ccc5a8b9b6 100644
--- a/test/dotnet.Tests/CommandTests/Tool/Run/ToolRunCommandTests.cs
+++ b/test/dotnet.Tests/CommandTests/Tool/Run/ToolRunCommandTests.cs
@@ -40,7 +40,7 @@ public void WhenRunWithRollForwardOptionItShouldIncludeRollForwardInNativeHost()
}, toolRunCommand._allowRollForward);
result.Should().NotBeNull();
- result.Args.Should().Contain("--roll-forward", "Major", fakeExecutable.Value);
+ result.Args.Should().ContainAll("--roll-forward", "Major", fakeExecutable.Value);
}
[Fact]
@@ -86,7 +86,7 @@ public void WhenRunWithoutRollForwardOptionItShouldNotIncludeRollForwardInNative
new DirectoryPath(Path.Combine(temporaryDirectory, "cache")));
localToolsResolverCache.Save(
- new Dictionary
+ new Dictionary
{
[new RestoredCommandIdentifier(
new PackageId("local.tool.console.a"),
@@ -94,7 +94,7 @@ [new RestoredCommandIdentifier(
NuGetFramework.Parse(BundledTargetFramework.GetTargetFrameworkMoniker()),
Constants.AnyRid,
toolCommandNameA)]
- = new RestoredCommand(toolCommandNameA, "dotnet", fakeExecutable)
+ = new ToolCommand(toolCommandNameA, "dotnet", fakeExecutable)
});
var localToolsCommandResolver = new LocalToolsCommandResolver(
diff --git a/test/dotnet.Tests/CommandTests/Tool/Uninstall/ToolUninstallGlobalOrToolPathCommandTests.cs b/test/dotnet.Tests/CommandTests/Tool/Uninstall/ToolUninstallGlobalOrToolPathCommandTests.cs
index 276e1c53895f..7bf8eed51e8c 100644
--- a/test/dotnet.Tests/CommandTests/Tool/Uninstall/ToolUninstallGlobalOrToolPathCommandTests.cs
+++ b/test/dotnet.Tests/CommandTests/Tool/Uninstall/ToolUninstallGlobalOrToolPathCommandTests.cs
@@ -231,17 +231,19 @@ private ToolInstallGlobalOrToolPathCommand CreateInstallCommand(string options)
var store = new ToolPackageStoreMock(new DirectoryPath(_toolsDirectory), _fileSystem);
- var packageDownloaderMock = new ToolPackageDownloaderMock(
- store: store,
- fileSystem: _fileSystem,
- _reporter
- );
- var toolPackageDownloaderMock = new ToolPackageUninstallerMock(_fileSystem, store);
+
+ var toolPackageUninstallerMock = new ToolPackageUninstallerMock(_fileSystem, store);
+
+ var toolPackageDownloaderMock = new ToolPackageDownloaderMock2(store,
+ runtimeJsonPathForTests: TestContext.GetRuntimeGraphFilePath(),
+ currentWorkingDirectory: null,
+ fileSystem: _fileSystem);
+
return new ToolInstallGlobalOrToolPathCommand(
result,
new PackageId(PackageId),
- (location, forwardArguments, currentWorkingDirectory) => (store, store, packageDownloaderMock, toolPackageDownloaderMock),
+ (location, forwardArguments, currentWorkingDirectory) => (store, store, toolPackageDownloaderMock, toolPackageUninstallerMock),
(_, _) => new ShellShimRepository(
new DirectoryPath(_shimsDirectory),
string.Empty,
diff --git a/test/dotnet.Tests/CommandTests/Tool/Update/ToolUpdateGlobalOrToolPathCommandTests.cs b/test/dotnet.Tests/CommandTests/Tool/Update/ToolUpdateGlobalOrToolPathCommandTests.cs
index 5e07a6c38983..cab679766e46 100644
--- a/test/dotnet.Tests/CommandTests/Tool/Update/ToolUpdateGlobalOrToolPathCommandTests.cs
+++ b/test/dotnet.Tests/CommandTests/Tool/Update/ToolUpdateGlobalOrToolPathCommandTests.cs
@@ -4,20 +4,22 @@
#nullable disable
using System.CommandLine;
+using Microsoft.DotNet.Cli;
+using Microsoft.DotNet.Cli.Commands;
+using Microsoft.DotNet.Cli.Commands.Tool.Install;
+using Microsoft.DotNet.Cli.Commands.Tool.Update;
+using Microsoft.DotNet.Cli.NuGetPackageDownloader;
+using Microsoft.DotNet.Cli.ShellShim;
+using Microsoft.DotNet.Cli.ToolPackage;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Tools.Tests.ComponentMocks;
using Microsoft.Extensions.DependencyModel.Tests;
using Microsoft.Extensions.EnvironmentAbstractions;
using Parser = Microsoft.DotNet.Cli.Parser;
-using Microsoft.DotNet.Cli.ShellShim;
-using Microsoft.DotNet.Cli.ToolPackage;
-using Microsoft.DotNet.Cli.Commands.Tool.Install;
-using Microsoft.DotNet.Cli.Commands.Tool.Update;
-using Microsoft.DotNet.Cli.Commands;
namespace Microsoft.DotNet.Tests.Commands.Tool
{
- public class ToolUpdateGlobalOrToolPathCommandTests
+ public class ToolUpdateGlobalOrToolPathCommandTests : SdkTest
{
private readonly BufferedReporter _reporter;
private readonly IFileSystem _fileSystem;
@@ -32,8 +34,9 @@ public class ToolUpdateGlobalOrToolPathCommandTests
private readonly string _shimsDirectory;
private readonly string _toolsDirectory;
private readonly string _tempDirectory;
+ private readonly ToolPackageDownloaderMock2 _toolPackageDownloader;
- public ToolUpdateGlobalOrToolPathCommandTests()
+ public ToolUpdateGlobalOrToolPathCommandTests(ITestOutputHelper log) : base(log)
{
_reporter = new BufferedReporter();
_fileSystem = new FileSystemMockBuilder().UseCurrentSystemTemporaryDirectory().Build();
@@ -88,6 +91,16 @@ public ToolUpdateGlobalOrToolPathCommandTests()
}
}
};
+
+ _toolPackageDownloader = new ToolPackageDownloaderMock2(_store,
+ runtimeJsonPathForTests: TestContext.GetRuntimeGraphFilePath(),
+ currentWorkingDirectory: null,
+ fileSystem: _fileSystem);
+
+ foreach (var package in _mockFeeds.SelectMany(p => p.Packages))
+ {
+ _toolPackageDownloader.AddMockPackage(package);
+ }
}
[Fact]
@@ -119,7 +132,7 @@ public void GivenANonFeedExistentPackageItErrors()
a.Should().Throw().And.Message
.Should().Contain(
- CliCommandStrings.ToolInstallationRestoreFailed);
+ string.Format(CliStrings.IsNotFoundInNuGetFeeds, packageId, MockNuGetPackageDownloader.MOCK_FEEDS_TEXT));
}
[Fact]
@@ -170,13 +183,7 @@ public void GivenAnExistedLowerversionInstallationWhenCallFromRedirectorItCanUpd
var toolUpdateGlobalOrToolPathCommand = new ToolUpdateGlobalOrToolPathCommand(
result,
- (location, forwardArguments, currentWorkingDirectory) => (_store, _store, new ToolPackageDownloaderMock(
- store: _store,
- fileSystem: _fileSystem,
- reporter: _reporter,
- feeds: _mockFeeds
- ),
- new ToolPackageUninstallerMock(_fileSystem, _store)),
+ (location, forwardArguments, currentWorkingDirectory) => (_store, _store, _toolPackageDownloader, new ToolPackageUninstallerMock(_fileSystem, _store)),
(_, _) => GetMockedShellShimRepository(),
_reporter);
@@ -404,31 +411,25 @@ public void GivenAnExistedLowerversionWhenReinstallThrowsItRollsBack()
[Fact]
public void GivenPackagedShimIsProvidedWhenRunWithPackageIdItCreatesShimUsingPackagedShim()
{
- CreateInstallCommand($"-g {_packageId} --version {LowerPackageVersion}").Execute();
- _reporter.Lines.Clear();
+
+ Log.WriteLine($"Current RuntimeIdentifier: {RuntimeInformation.RuntimeIdentifier}");
+
+ string toolTargetRuntimeIdentifier = OperatingSystem.IsWindows() ? "win-x64" : RuntimeInformation.RuntimeIdentifier;
var extension = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".exe" : string.Empty;
- var prepackagedShimPath = Path.Combine(Path.GetTempPath(), "SimulatorCommand" + extension);
var tokenToIdentifyPackagedShim = "packagedShim";
- _fileSystem.File.WriteAllText(prepackagedShimPath, tokenToIdentifyPackagedShim);
+ var mockPackage = _mockFeeds[0].Packages.Single(p => p.PackageId == _packageId.ToString() && p.Version == HigherPackageVersion);
+ mockPackage.AdditionalFiles[$"tools/{ToolPackageDownloaderMock2.DefaultTargetFramework}/any/shims/{toolTargetRuntimeIdentifier}/{mockPackage.ToolCommandName}{extension}"] = tokenToIdentifyPackagedShim;
- var packagedShimsMap = new Dictionary>
- {
- [_packageId] = new[] { new FilePath(prepackagedShimPath) }
- };
+ CreateInstallCommand($"-g {_packageId} --version {LowerPackageVersion}").Execute();
+ _reporter.Lines.Clear();
string options = $"-g {_packageId}";
ParseResult result = Parser.Instance.Parse("dotnet tool update " + options);
var command = new ToolUpdateGlobalOrToolPathCommand(
result,
- (_, _, _) => (_store, _store, new ToolPackageDownloaderMock(
- store:_store,
- fileSystem: _fileSystem,
- reporter: _reporter,
- feeds: _mockFeeds,
- packagedShimsMap: packagedShimsMap),
- new ToolPackageUninstallerMock(_fileSystem, _store)),
+ (_, _, _) => (_store, _store, _toolPackageDownloader, new ToolPackageUninstallerMock(_fileSystem, _store)),
(_, _) => GetMockedShellShimRepository(),
_reporter);
@@ -438,7 +439,7 @@ public void GivenPackagedShimIsProvidedWhenRunWithPackageIdItCreatesShimUsingPac
string ExpectedCommandPath()
{
- var extension = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".exe" : string.Empty;
+
return Path.Combine(
_shimsDirectory,
"SimulatorCommand" + extension);
@@ -448,19 +449,11 @@ string ExpectedCommandPath()
private ToolInstallGlobalOrToolPathCommand CreateInstallCommand(string options, string packageId = null)
{
ParseResult result = Parser.Instance.Parse("dotnet tool install " + options);
- var store = new ToolPackageStoreMock(
- new DirectoryPath(_toolsDirectory),
- _fileSystem);
return new ToolInstallGlobalOrToolPathCommand(
result,
packageId is null ? _packageId : new PackageId(packageId) ,
- (location, forwardArguments, currentWorkingDirectory) => (_store, _store, new ToolPackageDownloaderMock(
- store: _store,
- fileSystem: _fileSystem,
- _reporter,
- _mockFeeds
- ), new ToolPackageUninstallerMock(_fileSystem, store)),
+ (location, forwardArguments, currentWorkingDirectory) => (_store, _store, _toolPackageDownloader, new ToolPackageUninstallerMock(_fileSystem, _store)),
(_, _) => GetMockedShellShimRepository(),
_environmentPathInstructionMock,
_reporter);
@@ -472,13 +465,7 @@ private ToolUpdateGlobalOrToolPathCommand CreateUpdateCommand(string options)
return new ToolUpdateGlobalOrToolPathCommand(
result,
- (location, forwardArguments, currentWorkingDirectory) => (_store, _store, new ToolPackageDownloaderMock(
- store: _store,
- fileSystem: _fileSystem,
- _reporter,
- _mockFeeds
- ),
- new ToolPackageUninstallerMock(_fileSystem, _store)),
+ (location, forwardArguments, currentWorkingDirectory) => (_store, _store, _toolPackageDownloader, new ToolPackageUninstallerMock(_fileSystem, _store)),
(_, _) => GetMockedShellShimRepository(),
_reporter,
_store);
diff --git a/test/dotnet.Tests/CommandTests/Tool/Update/ToolUpdateLocalCommandTests.cs b/test/dotnet.Tests/CommandTests/Tool/Update/ToolUpdateLocalCommandTests.cs
index e2b3edb201a8..835fda4897ce 100644
--- a/test/dotnet.Tests/CommandTests/Tool/Update/ToolUpdateLocalCommandTests.cs
+++ b/test/dotnet.Tests/CommandTests/Tool/Update/ToolUpdateLocalCommandTests.cs
@@ -423,7 +423,7 @@ private void AssertUpdateSuccess(
NuGetFramework.Parse(BundledTargetFramework.GetTargetFrameworkMoniker()),
Constants.AnyRid,
updatedPackage.CommandNames.Single()),
- out RestoredCommand restoredCommand
+ out ToolCommand restoredCommand
).Should().BeTrue();
_fileSystem.File.Exists(restoredCommand.Executable.Value).Should().BeTrue();
diff --git a/test/dotnet.Tests/CompletionTests/snapshots/bash/DotnetCliSnapshotTests.VerifyCompletions.verified.sh b/test/dotnet.Tests/CompletionTests/snapshots/bash/DotnetCliSnapshotTests.VerifyCompletions.verified.sh
index 6e76bbce5854..b4041b1e123c 100644
--- a/test/dotnet.Tests/CompletionTests/snapshots/bash/DotnetCliSnapshotTests.VerifyCompletions.verified.sh
+++ b/test/dotnet.Tests/CompletionTests/snapshots/bash/DotnetCliSnapshotTests.VerifyCompletions.verified.sh
@@ -970,7 +970,7 @@ _testhost_pack() {
prev="${COMP_WORDS[COMP_CWORD-1]}"
COMPREPLY=()
- opts="--output --artifacts-path --no-build --include-symbols --include-source --serviceable --nologo --interactive --no-restore --verbosity --version-suffix --configuration --disable-build-servers --use-current-runtime --help"
+ opts="--output --artifacts-path --no-build --include-symbols --include-source --serviceable --nologo --interactive --no-restore --verbosity --version-suffix --configuration --disable-build-servers --use-current-runtime --runtime --help"
if [[ $COMP_CWORD == "$1" ]]; then
COMPREPLY=( $(compgen -W "$opts" -- "$cur") )
@@ -990,6 +990,10 @@ _testhost_pack() {
COMPREPLY=( $(compgen -W "(${COMP_WORDS[0]} complete --position ${COMP_POINT} ${COMP_LINE} 2>/dev/null | tr '\n' ' ')" -- "$cur") )
return
;;
+ --runtime|-r)
+ COMPREPLY=( $(compgen -W "(${COMP_WORDS[0]} complete --position ${COMP_POINT} ${COMP_LINE} 2>/dev/null | tr '\n' ' ')" -- "$cur") )
+ return
+ ;;
esac
COMPREPLY=( $(compgen -W "$opts" -- "$cur") )
diff --git a/test/dotnet.Tests/CompletionTests/snapshots/pwsh/DotnetCliSnapshotTests.VerifyCompletions.verified.ps1 b/test/dotnet.Tests/CompletionTests/snapshots/pwsh/DotnetCliSnapshotTests.VerifyCompletions.verified.ps1
index a8f44291ac57..3d96499b00d8 100644
--- a/test/dotnet.Tests/CompletionTests/snapshots/pwsh/DotnetCliSnapshotTests.VerifyCompletions.verified.ps1
+++ b/test/dotnet.Tests/CompletionTests/snapshots/pwsh/DotnetCliSnapshotTests.VerifyCompletions.verified.ps1
@@ -557,6 +557,8 @@ Register-ArgumentCompleter -Native -CommandName 'testhost' -ScriptBlock {
[CompletionResult]::new('--disable-build-servers', '--disable-build-servers', [CompletionResultType]::ParameterName, "Force the command to ignore any persistent build servers.")
[CompletionResult]::new('--use-current-runtime', '--use-current-runtime', [CompletionResultType]::ParameterName, "Use current runtime as the target runtime.")
[CompletionResult]::new('--use-current-runtime', '--ucr', [CompletionResultType]::ParameterName, "Use current runtime as the target runtime.")
+ [CompletionResult]::new('--runtime', '--runtime', [CompletionResultType]::ParameterName, "The target runtime to build for.")
+ [CompletionResult]::new('--runtime', '-r', [CompletionResultType]::ParameterName, "The target runtime to build for.")
[CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, "Show command line help.")
[CompletionResult]::new('--help', '-h', [CompletionResultType]::ParameterName, "Show command line help.")
)
diff --git a/test/dotnet.Tests/CompletionTests/snapshots/zsh/DotnetCliSnapshotTests.VerifyCompletions.verified.zsh b/test/dotnet.Tests/CompletionTests/snapshots/zsh/DotnetCliSnapshotTests.VerifyCompletions.verified.zsh
index eda18093af84..a35e334962a1 100644
--- a/test/dotnet.Tests/CompletionTests/snapshots/zsh/DotnetCliSnapshotTests.VerifyCompletions.verified.zsh
+++ b/test/dotnet.Tests/CompletionTests/snapshots/zsh/DotnetCliSnapshotTests.VerifyCompletions.verified.zsh
@@ -536,6 +536,8 @@ _testhost() {
'--disable-build-servers[Force the command to ignore any persistent build servers.]' \
'--use-current-runtime[Use current runtime as the target runtime.]' \
'--ucr[Use current runtime as the target runtime.]' \
+ '--runtime=[The target runtime to build for.]:RUNTIME_IDENTIFIER:->dotnet_dynamic_complete' \
+ '-r=[The target runtime to build for.]:RUNTIME_IDENTIFIER:->dotnet_dynamic_complete' \
'--help[Show command line help.]' \
'-h[Show command line help.]' \
'*::PROJECT | SOLUTION -- The project or solution file to operate on. If a file is not specified, the command will search the current directory for one.: ' \
diff --git a/test/dotnet.Tests/ShellShimTests/ShellShimRepositoryTests.cs b/test/dotnet.Tests/ShellShimTests/ShellShimRepositoryTests.cs
index 877b89dee843..facb4cda8184 100644
--- a/test/dotnet.Tests/ShellShimTests/ShellShimRepositoryTests.cs
+++ b/test/dotnet.Tests/ShellShimTests/ShellShimRepositoryTests.cs
@@ -32,7 +32,9 @@ public void GivenAnExecutablePathItCanGenerateShimFile()
ShellShimRepository shellShimRepository = ConfigBasicTestDependencyShellShimRepository(pathToShim);
var shellCommandName = nameof(ShellShimRepositoryTests) + Path.GetRandomFileName();
- shellShimRepository.CreateShim(outputDll, new ToolCommandName(shellCommandName));
+ var command = new ToolCommand(new ToolCommandName(shellCommandName), "dotnet", outputDll);
+
+ shellShimRepository.CreateShim(command);
var stdOut = ExecuteInShell(shellCommandName, pathToShim);
@@ -53,7 +55,8 @@ public void GivenAnExecutableAndRelativePathToShimPathItCanGenerateShimFile()
ShellShimRepository shellShimRepository = ConfigBasicTestDependencyShellShimRepository(relativePathToShim);
var shellCommandName = nameof(ShellShimRepositoryTests) + Path.GetRandomFileName();
- shellShimRepository.CreateShim(outputDll, new ToolCommandName(shellCommandName));
+ var command = new ToolCommand(new ToolCommandName(shellCommandName), "dotnet", outputDll);
+ shellShimRepository.CreateShim(command);
var stdOut = ExecuteInShell(shellCommandName, relativePathToShim);
@@ -75,11 +78,13 @@ public void GivenAnExecutablePathItCanGenerateShimFileInTransaction()
var shellShimRepository = ConfigBasicTestDependencyShellShimRepository(pathToShim);
var shellCommandName = nameof(ShellShimRepositoryTests) + Path.GetRandomFileName();
+ var command = new ToolCommand(new ToolCommandName(shellCommandName), "dotnet", outputDll);
+
using (var transactionScope = new TransactionScope(
TransactionScopeOption.Required,
TimeSpan.Zero))
{
- shellShimRepository.CreateShim(outputDll, new ToolCommandName(shellCommandName));
+ shellShimRepository.CreateShim(command);
transactionScope.Complete();
}
@@ -96,8 +101,9 @@ public void GivenAnExecutablePathDirectoryThatDoesNotExistItCanGenerateShimFile(
var extraNonExistDirectory = Path.GetRandomFileName();
var shellShimRepository = new ShellShimRepository(new DirectoryPath(Path.Combine(testFolder, extraNonExistDirectory)), GetAppHostTemplateFromStage2());
var shellCommandName = nameof(ShellShimRepositoryTests) + Path.GetRandomFileName();
+ var command = new ToolCommand(new ToolCommandName(shellCommandName), "dotnet", outputDll);
- Action a = () => shellShimRepository.CreateShim(outputDll, new ToolCommandName(shellCommandName));
+ Action a = () => shellShimRepository.CreateShim(command);
a.Should().NotThrow();
}
@@ -112,8 +118,9 @@ public void GivenAShimItPassesThroughArguments(string arguments, string[] expect
var pathToShim = GetNewCleanFolderUnderTempRoot();
var shellShimRepository = ConfigBasicTestDependencyShellShimRepository(pathToShim);
var shellCommandName = nameof(ShellShimRepositoryTests) + Path.GetRandomFileName();
+ var command = new ToolCommand(new ToolCommandName(shellCommandName), "dotnet", outputDll);
- shellShimRepository.CreateShim(outputDll, new ToolCommandName(shellCommandName));
+ shellShimRepository.CreateShim(command);
var stdOut = ExecuteInShell(shellCommandName, pathToShim, arguments);
@@ -142,13 +149,15 @@ public void GivenAShimConflictItWillRollback(bool testMockBehaviorIsInSync)
shellShimRepository = ConfigBasicTestDependencyShellShimRepository(pathToShim);
}
+ var command = new ToolCommand(new ToolCommandName(shellCommandName), "dotnet", new FilePath("dummy.dll"));
+
Action a = () =>
{
using (var scope = new TransactionScope(
TransactionScopeOption.Required,
TimeSpan.Zero))
{
- shellShimRepository.CreateShim(new FilePath("dummy.dll"), new ToolCommandName(shellCommandName));
+ shellShimRepository.CreateShim(command);
scope.Complete();
}
@@ -184,8 +193,12 @@ public void GivenAnExceptionItWillRollback(bool testMockBehaviorIsInSync)
shellShimRepository = ConfigBasicTestDependencyShellShimRepository(pathToShim);
}
+
+
Action intendedError = () => throw new ToolPackageException("simulated error");
+
+
Action a = () =>
{
using (var scope = new TransactionScope(
@@ -193,7 +206,8 @@ public void GivenAnExceptionItWillRollback(bool testMockBehaviorIsInSync)
TimeSpan.Zero))
{
FilePath targetExecutablePath = MakeHelloWorldExecutableDll(identifier: testMockBehaviorIsInSync.ToString());
- shellShimRepository.CreateShim(targetExecutablePath, new ToolCommandName(shellCommandName));
+ var command = new ToolCommand(new ToolCommandName(shellCommandName), "dotnet", targetExecutablePath);
+ shellShimRepository.CreateShim(command);
intendedError();
scope.Complete();
@@ -224,7 +238,9 @@ public void GivenANonexistentShimRemoveDoesNotThrow(bool testMockBehaviorIsInSyn
Directory.EnumerateFileSystemEntries(pathToShim).Should().BeEmpty();
- shellShimRepository.RemoveShim(new ToolCommandName(shellCommandName));
+ var command = new ToolCommand(new ToolCommandName(shellCommandName), "dotnet", new FilePath("dummyExe"));
+
+ shellShimRepository.RemoveShim(command);
Directory.EnumerateFileSystemEntries(pathToShim).Should().BeEmpty();
}
@@ -250,11 +266,12 @@ public void GivenAnInstalledShimRemoveDeletesTheShimFiles(bool testMockBehaviorI
Directory.EnumerateFileSystemEntries(pathToShim).Should().BeEmpty();
FilePath targetExecutablePath = MakeHelloWorldExecutableDll(identifier: testMockBehaviorIsInSync.ToString());
- shellShimRepository.CreateShim(targetExecutablePath, new ToolCommandName(shellCommandName));
+ var command = new ToolCommand(new ToolCommandName(shellCommandName), "dotnet", targetExecutablePath);
+ shellShimRepository.CreateShim(command);
Directory.EnumerateFileSystemEntries(pathToShim).Should().NotBeEmpty();
- shellShimRepository.RemoveShim(new ToolCommandName(shellCommandName));
+ shellShimRepository.RemoveShim(command);
Directory.EnumerateFileSystemEntries(pathToShim).Should().BeEmpty();
}
@@ -280,7 +297,8 @@ public void GivenAnInstalledShimRemoveRollsbackIfTransactionIsAborted(bool testM
Directory.EnumerateFileSystemEntries(pathToShim).Should().BeEmpty();
FilePath targetExecutablePath = MakeHelloWorldExecutableDll(identifier: testMockBehaviorIsInSync.ToString());
- shellShimRepository.CreateShim(targetExecutablePath, new ToolCommandName(shellCommandName));
+ var command = new ToolCommand(new ToolCommandName(shellCommandName), "dotnet", targetExecutablePath);
+ shellShimRepository.CreateShim(command);
Directory.EnumerateFileSystemEntries(pathToShim).Should().NotBeEmpty();
@@ -288,7 +306,7 @@ public void GivenAnInstalledShimRemoveRollsbackIfTransactionIsAborted(bool testM
TransactionScopeOption.Required,
TimeSpan.Zero))
{
- shellShimRepository.RemoveShim(new ToolCommandName(shellCommandName));
+ shellShimRepository.RemoveShim(command);
Directory.EnumerateFileSystemEntries(pathToShim).Should().BeEmpty();
}
@@ -317,7 +335,8 @@ public void GivenAnInstalledShimRemoveCommitsIfTransactionIsCompleted(bool testM
Directory.EnumerateFileSystemEntries(pathToShim).Should().BeEmpty();
FilePath targetExecutablePath = MakeHelloWorldExecutableDll(identifier: testMockBehaviorIsInSync.ToString());
- shellShimRepository.CreateShim(targetExecutablePath, new ToolCommandName(shellCommandName));
+ var command = new ToolCommand(new ToolCommandName(shellCommandName), "dotnet", targetExecutablePath);
+ shellShimRepository.CreateShim(command);
Directory.EnumerateFileSystemEntries(pathToShim).Should().NotBeEmpty();
@@ -325,7 +344,7 @@ public void GivenAnInstalledShimRemoveCommitsIfTransactionIsCompleted(bool testM
TransactionScopeOption.Required,
TimeSpan.Zero))
{
- shellShimRepository.RemoveShim(new ToolCommandName(shellCommandName));
+ shellShimRepository.RemoveShim(command);
Directory.EnumerateFileSystemEntries(pathToShim).Should().BeEmpty();
@@ -354,9 +373,10 @@ public void WhenPackagedShimProvidedItCopies()
ShellShimRepository shellShimRepository = GetShellShimRepositoryWithMockMaker(pathToShim);
+ var command = new ToolCommand(new ToolCommandName(shellCommandName), "dotnet", new FilePath("dummy.dll"));
+
shellShimRepository.CreateShim(
- new FilePath("dummy.dll"),
- new ToolCommandName(shellCommandName),
+ command,
new[] { new FilePath(dummyShimPath) });
var createdShim = Directory.EnumerateFileSystemEntries(pathToShim).Single();
@@ -383,9 +403,10 @@ public void WhenMultipleSameNamePackagedShimProvidedItThrows()
FilePath[] filePaths = new[] { new FilePath(dummyShimPath), new FilePath("path" + dummyShimPath) };
+ var command = new ToolCommand(new ToolCommandName(shellCommandName), "dotnet", new FilePath("dummy.dll"));
+
Action a = () => shellShimRepository.CreateShim(
- new FilePath("dummy.dll"),
- new ToolCommandName(shellCommandName),
+ command,
new[] { new FilePath(dummyShimPath), new FilePath("path" + dummyShimPath) });
a.Should().Throw()