Skip to content
This repository was archived by the owner on Apr 20, 2023. It is now read-only.

Commit 0598e6c

Browse files
author
William Lee
authored
tool-path option -- "Session tool" (#8716)
* Change to escape string via XML * tool-path option -- "Session tool" From the beginning design, shim and packageInstaller take package location from constructor and don't have assumption anymore. From previous discussion, tool-path will simply change global location to the one user want, and everything else is the same. However, this "override" need to happen during the call, that means InstallToolCommand will create different shim and packageInstaller object according to the tool-path during the call instead of constructor DI. * global package location change * block of leading dot as command name * Localization of tool-path option
1 parent 65a761a commit 0598e6c

File tree

60 files changed

+884
-265
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+884
-265
lines changed

src/Microsoft.DotNet.Configurer/CliFolderPathCalculator.cs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,19 @@
44
using System;
55
using System.IO;
66
using System.Runtime.InteropServices;
7-
using Microsoft.DotNet.Cli.Utils;
8-
using Microsoft.DotNet.PlatformAbstractions;
97
using NuGet.Common;
108

119
namespace Microsoft.DotNet.Configurer
1210
{
1311
public class CliFolderPathCalculator
1412
{
15-
// ToolsShimFolderName ToolPackageFolderName cannot be the same
16-
// or if the PackageId is the same as CommandName, they will conflict on unix.
17-
private const string ToolsShimFolderName = "tools";
18-
private const string ToolPackageFolderName = "toolspkgs";
1913
private const string DotnetProfileDirectoryName = ".dotnet";
14+
private const string ToolsShimFolderName = "tools";
2015

2116
public string CliFallbackFolderPath => Environment.GetEnvironmentVariable("DOTNET_CLI_TEST_FALLBACKFOLDER") ??
2217
Path.Combine(new DirectoryInfo(AppContext.BaseDirectory).Parent.FullName, "NuGetFallbackFolder");
23-
2418
public string ToolsShimPath => Path.Combine(DotnetUserProfileFolderPath, ToolsShimFolderName);
25-
public string ToolsPackagePath => Path.Combine(DotnetUserProfileFolderPath, ToolPackageFolderName);
19+
public string ToolsPackagePath => ToolPackageFolderPathCalculator.GetToolPackageFolderPath(ToolsShimPath);
2620
public BashPathUnderHomeDirectory ToolsShimPathInUnix
2721
{
2822
get
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright (c) .NET Foundation and contributors. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System.IO;
5+
6+
namespace Microsoft.DotNet.Configurer
7+
{
8+
public static class ToolPackageFolderPathCalculator
9+
{
10+
private const string NestedToolPackageFolderName = ".store";
11+
public static string GetToolPackageFolderPath(string toolsShimPath)
12+
{
13+
return Path.Combine(toolsShimPath, NestedToolPackageFolderName);
14+
}
15+
}
16+
}

src/Microsoft.DotNet.InternalAbstractions/DirectoryPath.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ public string ToQuotedString()
3434
return $"\"{Value}\"";
3535
}
3636

37+
public string ToXmlEncodeString()
38+
{
39+
return System.Net.WebUtility.HtmlEncode(Value);
40+
}
41+
3742
public override string ToString()
3843
{
3944
return ToQuotedString();

src/dotnet/CommonLocalizableStrings.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -625,4 +625,7 @@ setx PATH "%PATH%;{0}"
625625
<data name="ColumnMaxWidthMustBeGreaterThanZero" xml:space="preserve">
626626
<value>Column maximum width must be greater than zero.</value>
627627
</data>
628+
<data name="ToolSettingsInvalidLeadingDotCommandName" xml:space="preserve">
629+
<value>Command '{0}' has a leading dot.</value>
630+
</data>
628631
</root>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright (c) .NET Foundation and contributors. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using Microsoft.DotNet.Configurer;
5+
using Microsoft.Extensions.EnvironmentAbstractions;
6+
7+
namespace Microsoft.DotNet.ShellShim
8+
{
9+
internal static class ShellShimRepositoryFactory
10+
{
11+
public static IShellShimRepository CreateShellShimRepository(DirectoryPath? nonGlobalLocation = null)
12+
{
13+
return new ShellShimRepository(nonGlobalLocation ?? GetShimLocation());
14+
}
15+
16+
private static DirectoryPath GetShimLocation()
17+
{
18+
var cliFolderPathCalculator = new CliFolderPathCalculator();
19+
return new DirectoryPath(cliFolderPathCalculator.ToolsShimPath);
20+
}
21+
}
22+
}

src/dotnet/ToolPackage/ToolConfiguration.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public ToolConfiguration(
2727
commandName));
2828
}
2929

30+
EnsureNoLeadingDot(commandName);
3031
EnsureNoInvalidFilenameCharacters(commandName);
3132

3233
CommandName = commandName;
@@ -46,6 +47,17 @@ private void EnsureNoInvalidFilenameCharacters(string commandName)
4647
}
4748
}
4849

50+
private void EnsureNoLeadingDot(string commandName)
51+
{
52+
if (commandName.StartsWith(".", StringComparison.OrdinalIgnoreCase))
53+
{
54+
throw new ToolConfigurationException(
55+
string.Format(
56+
CommonLocalizableStrings.ToolSettingsInvalidLeadingDotCommandName,
57+
commandName));
58+
}
59+
}
60+
4961
public string CommandName { get; }
5062
public string ToolAssemblyEntryPoint { get; }
5163
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright (c) .NET Foundation and contributors. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using Microsoft.DotNet.Cli.Utils;
5+
using Microsoft.DotNet.Configurer;
6+
using Microsoft.DotNet.Tools.Install.Tool;
7+
using Microsoft.Extensions.EnvironmentAbstractions;
8+
9+
namespace Microsoft.DotNet.ToolPackage
10+
{
11+
internal static class ToolPackageFactory
12+
{
13+
public static (IToolPackageStore, IToolPackageInstaller) CreateToolPackageStoreAndInstaller(
14+
DirectoryPath? nonGlobalLocation = null)
15+
{
16+
IToolPackageStore toolPackageStore = CreateToolPackageStore(nonGlobalLocation);
17+
var toolPackageInstaller = new ToolPackageInstaller(
18+
toolPackageStore,
19+
new ProjectRestorer(Reporter.Output));
20+
21+
return (toolPackageStore, toolPackageInstaller);
22+
}
23+
24+
public static IToolPackageStore CreateToolPackageStore(
25+
DirectoryPath? nonGlobalLocation = null)
26+
{
27+
var toolPackageStore =
28+
new ToolPackageStore(nonGlobalLocation.HasValue
29+
? new DirectoryPath(ToolPackageFolderPathCalculator.GetToolPackageFolderPath(nonGlobalLocation.Value.Value))
30+
: GetPackageLocation());
31+
32+
return toolPackageStore;
33+
}
34+
35+
private static DirectoryPath GetPackageLocation()
36+
{
37+
var cliFolderPathCalculator = new CliFolderPathCalculator();
38+
return new DirectoryPath(cliFolderPathCalculator.ToolsPackagePath);
39+
}
40+
}
41+
}

src/dotnet/commands/dotnet-install/dotnet-install-tool/InstallToolCommand.cs

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,16 @@
1717

1818
namespace Microsoft.DotNet.Tools.Install.Tool
1919
{
20+
internal delegate IShellShimRepository CreateShellShimRepository(DirectoryPath? nonGlobalLocation = null);
21+
internal delegate (IToolPackageStore, IToolPackageInstaller) CreateToolPackageStoreAndInstaller(DirectoryPath? nonGlobalLocation = null);
22+
2023
internal class InstallToolCommand : CommandBase
2124
{
22-
private readonly IToolPackageStore _toolPackageStore;
23-
private readonly IToolPackageInstaller _toolPackageInstaller;
24-
private readonly IShellShimRepository _shellShimRepository;
2525
private readonly IEnvironmentPathInstruction _environmentPathInstruction;
2626
private readonly IReporter _reporter;
2727
private readonly IReporter _errorReporter;
28+
private CreateShellShimRepository _createShellShimRepository;
29+
private CreateToolPackageStoreAndInstaller _createToolPackageStoreAndInstaller;
2830

2931
private readonly PackageId _packageId;
3032
private readonly string _packageVersion;
@@ -33,13 +35,13 @@ internal class InstallToolCommand : CommandBase
3335
private readonly string _source;
3436
private readonly bool _global;
3537
private readonly string _verbosity;
38+
private readonly string _toolPath;
3639

3740
public InstallToolCommand(
3841
AppliedOption appliedCommand,
3942
ParseResult parseResult,
40-
IToolPackageStore toolPackageStore = null,
41-
IToolPackageInstaller toolPackageInstaller = null,
42-
IShellShimRepository shellShimRepository = null,
43+
CreateToolPackageStoreAndInstaller createToolPackageStoreAndInstaller = null,
44+
CreateShellShimRepository createShellShimRepository = null,
4345
IEnvironmentPathInstruction environmentPathInstruction = null,
4446
IReporter reporter = null)
4547
: base(parseResult)
@@ -56,32 +58,30 @@ public InstallToolCommand(
5658
_source = appliedCommand.ValueOrDefault<string>("source");
5759
_global = appliedCommand.ValueOrDefault<bool>("global");
5860
_verbosity = appliedCommand.SingleArgumentOrDefault("verbosity");
61+
_toolPath = appliedCommand.SingleArgumentOrDefault("tool-path");
5962

6063
var cliFolderPathCalculator = new CliFolderPathCalculator();
6164

62-
_toolPackageStore = toolPackageStore
63-
?? new ToolPackageStore(new DirectoryPath(cliFolderPathCalculator.ToolsPackagePath));
64-
65-
_toolPackageInstaller = toolPackageInstaller
66-
?? new ToolPackageInstaller(
67-
_toolPackageStore,
68-
new ProjectRestorer(_reporter));
65+
_createToolPackageStoreAndInstaller = createToolPackageStoreAndInstaller ?? ToolPackageFactory.CreateToolPackageStoreAndInstaller;
6966

7067
_environmentPathInstruction = environmentPathInstruction
7168
?? EnvironmentPathFactory.CreateEnvironmentPathInstruction();
72-
73-
_shellShimRepository = shellShimRepository
74-
?? new ShellShimRepository(new DirectoryPath(cliFolderPathCalculator.ToolsShimPath));
69+
_createShellShimRepository = createShellShimRepository ?? ShellShimRepositoryFactory.CreateShellShimRepository;
7570

7671
_reporter = (reporter ?? Reporter.Output);
7772
_errorReporter = (reporter ?? Reporter.Error);
7873
}
7974

8075
public override int Execute()
8176
{
82-
if (!_global)
77+
if (string.IsNullOrWhiteSpace(_toolPath) && !_global)
8378
{
84-
throw new GracefulException(LocalizableStrings.InstallToolCommandOnlySupportGlobal);
79+
throw new GracefulException(LocalizableStrings.InstallToolCommandNeedGlobalOrToolPath);
80+
}
81+
82+
if (!string.IsNullOrWhiteSpace(_toolPath) && _global)
83+
{
84+
throw new GracefulException(LocalizableStrings.InstallToolCommandInvalidGlobalAndToolPath);
8585
}
8686

8787
if (_configFilePath != null && !File.Exists(_configFilePath))
@@ -92,6 +92,7 @@ public override int Execute()
9292
Path.GetFullPath(_configFilePath)));
9393
}
9494

95+
9596
VersionRange versionRange = null;
9697
if (!string.IsNullOrEmpty(_packageVersion) && !VersionRange.TryParse(_packageVersion, out versionRange))
9798
{
@@ -101,7 +102,18 @@ public override int Execute()
101102
_packageVersion));
102103
}
103104

104-
if (_toolPackageStore.EnumeratePackageVersions(_packageId).FirstOrDefault() != null)
105+
DirectoryPath? toolPath = null;
106+
if (_toolPath != null)
107+
{
108+
toolPath = new DirectoryPath(_toolPath);
109+
}
110+
111+
(IToolPackageStore toolPackageStore, IToolPackageInstaller toolPackageInstaller) =
112+
_createToolPackageStoreAndInstaller(toolPath);
113+
IShellShimRepository shellShimRepository = _createShellShimRepository(toolPath);
114+
115+
// Prevent installation if any version of the package is installed
116+
if (toolPackageStore.EnumeratePackageVersions(_packageId).FirstOrDefault() != null)
105117
{
106118
_errorReporter.WriteLine(string.Format(LocalizableStrings.ToolAlreadyInstalled, _packageId).Red());
107119
return 1;
@@ -120,7 +132,7 @@ public override int Execute()
120132
TransactionScopeOption.Required,
121133
TimeSpan.Zero))
122134
{
123-
package = _toolPackageInstaller.InstallPackage(
135+
package = toolPackageInstaller.InstallPackage(
124136
packageId: _packageId,
125137
versionRange: versionRange,
126138
targetFramework: _framework,
@@ -130,13 +142,16 @@ public override int Execute()
130142

131143
foreach (var command in package.Commands)
132144
{
133-
_shellShimRepository.CreateShim(command.Executable, command.Name);
145+
shellShimRepository.CreateShim(command.Executable, command.Name);
134146
}
135147

136148
scope.Complete();
137149
}
138150

139-
_environmentPathInstruction.PrintAddPathInstructionIfPathDoesNotExist();
151+
if (_global)
152+
{
153+
_environmentPathInstruction.PrintAddPathInstructionIfPathDoesNotExist();
154+
}
140155

141156
_reporter.WriteLine(
142157
string.Format(

src/dotnet/commands/dotnet-install/dotnet-install-tool/InstallToolCommandParser.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ public static Command InstallTool()
1919
"-g|--global",
2020
LocalizableStrings.GlobalOptionDescription,
2121
Accept.NoArguments()),
22+
Create.Option(
23+
"--tool-path",
24+
LocalizableStrings.ToolPathDescription,
25+
Accept.ExactlyOneArgument()),
2226
Create.Option(
2327
"--version",
2428
LocalizableStrings.VersionOptionDescription,

src/dotnet/commands/dotnet-install/dotnet-install-tool/LocalizableStrings.resx

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -157,9 +157,6 @@ Tool '{1}' (version '{2}') was successfully installed.</value>
157157
<data name="InstallFullCommandNameLocalized" xml:space="preserve">
158158
<value>.NET Install Command</value>
159159
</data>
160-
<data name="InstallToolCommandOnlySupportGlobal" xml:space="preserve">
161-
<value>The --global switch (-g) is currently required because only user wide tools are supported.</value>
162-
</data>
163160
<data name="InvalidToolConfiguration" xml:space="preserve">
164161
<value>The settings file in the tool's NuGet package is invalid: {0}</value>
165162
</data>
@@ -181,4 +178,13 @@ Tool '{1}' (version '{2}') was successfully installed.</value>
181178
<data name="InvalidNuGetVersionRange" xml:space="preserve">
182179
<value>Specified version '{0}' is not a valid NuGet version range.</value>
183180
</data>
184-
</root>
181+
<data name="InstallToolCommandNeedGlobalOrToolPath" xml:space="preserve">
182+
<value>Need either global or tool-path provided.</value>
183+
</data>
184+
<data name="InstallToolCommandInvalidGlobalAndToolPath" xml:space="preserve">
185+
<value>Cannot have global and tool-path as opinion at the same time.</value>
186+
</data>
187+
<data name="ToolPathDescription" xml:space="preserve">
188+
<value>Location of shim to access tool</value>
189+
</data>
190+
</root>

0 commit comments

Comments
 (0)