Skip to content

Commit 6fab085

Browse files
committed
Factor out some tool restore functionality into separate class
1 parent 4c9b747 commit 6fab085

File tree

2 files changed

+177
-117
lines changed

2 files changed

+177
-117
lines changed
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Text;
7+
using Microsoft.DotNet.Cli.NuGetPackageDownloader;
8+
using Microsoft.DotNet.Cli.ToolManifest;
9+
using Microsoft.DotNet.Cli.ToolPackage;
10+
using Microsoft.DotNet.Cli.Utils;
11+
using Microsoft.Extensions.EnvironmentAbstractions;
12+
using NuGet.Commands;
13+
using NuGet.Frameworks;
14+
using NuGet.Versioning;
15+
using static Microsoft.DotNet.Cli.Commands.Tool.Restore.ToolRestoreCommand;
16+
17+
namespace Microsoft.DotNet.Cli.Commands.Tool.Restore;
18+
19+
internal class ToolPackageRestorer
20+
{
21+
private readonly IToolPackageDownloader _toolPackageDownloader;
22+
private readonly string[] _additionalSources;
23+
private readonly string[] _overrideSources;
24+
private readonly VerbosityOptions _verbosity;
25+
private readonly RestoreActionConfig _restoreActionConfig;
26+
27+
private readonly ILocalToolsResolverCache _localToolsResolverCache;
28+
private readonly IFileSystem _fileSystem;
29+
30+
31+
32+
public ToolPackageRestorer(IToolPackageDownloader toolPackageDownloader,
33+
string[] additionalSources,
34+
string[] overrideSources,
35+
VerbosityOptions verbosity,
36+
RestoreActionConfig restoreActionConfig,
37+
ILocalToolsResolverCache? localToolsResolverCache = null,
38+
IFileSystem? fileSystem = null)
39+
{
40+
_toolPackageDownloader = toolPackageDownloader;
41+
_additionalSources = additionalSources;
42+
_overrideSources = overrideSources;
43+
_verbosity = verbosity;
44+
_restoreActionConfig = restoreActionConfig;
45+
46+
_localToolsResolverCache = localToolsResolverCache ?? new LocalToolsResolverCache();
47+
_fileSystem = fileSystem ?? new FileSystemWrapper();
48+
}
49+
50+
public ToolRestoreResult InstallPackages(
51+
ToolManifestPackage package,
52+
FilePath? configFile)
53+
{
54+
string targetFramework = BundledTargetFramework.GetTargetFrameworkMoniker();
55+
56+
if (PackageHasBeenRestored(package, targetFramework))
57+
{
58+
return ToolRestoreResult.Success(
59+
saveToCache: [],
60+
message: string.Format(
61+
CliCommandStrings.RestoreSuccessful, package.PackageId,
62+
package.Version.ToNormalizedString(), string.Join(", ", package.CommandNames)));
63+
}
64+
65+
try
66+
{
67+
IToolPackage toolPackage =
68+
_toolPackageDownloader.InstallPackage(
69+
new PackageLocation(
70+
nugetConfig: configFile,
71+
additionalFeeds: _additionalSources,
72+
sourceFeedOverrides: _overrideSources,
73+
rootConfigDirectory: package.FirstEffectDirectory),
74+
package.PackageId,
75+
verbosity: _verbosity,
76+
ToVersionRangeWithOnlyOneVersion(package.Version),
77+
targetFramework,
78+
restoreActionConfig: _restoreActionConfig
79+
);
80+
81+
if (!ManifestCommandMatchesActualInPackage(package.CommandNames, [toolPackage.Command]))
82+
{
83+
return ToolRestoreResult.Failure(
84+
string.Format(CliCommandStrings.CommandsMismatch,
85+
JoinBySpaceWithQuote(package.CommandNames.Select(c => c.Value.ToString())),
86+
package.PackageId,
87+
toolPackage.Command.Name));
88+
}
89+
90+
return ToolRestoreResult.Success(
91+
saveToCache:
92+
[(new RestoredCommandIdentifier(
93+
toolPackage.Id,
94+
toolPackage.Version,
95+
NuGetFramework.Parse(targetFramework),
96+
Constants.AnyRid,
97+
toolPackage.Command.Name),
98+
toolPackage.Command)],
99+
message: string.Format(
100+
CliCommandStrings.RestoreSuccessful,
101+
package.PackageId,
102+
package.Version.ToNormalizedString(),
103+
string.Join(" ", package.CommandNames)));
104+
}
105+
catch (ToolPackageException e)
106+
{
107+
return ToolRestoreResult.Failure(package.PackageId, e);
108+
}
109+
}
110+
111+
private static bool ManifestCommandMatchesActualInPackage(
112+
ToolCommandName[] commandsFromManifest,
113+
IReadOnlyList<ToolCommand> toolPackageCommands)
114+
{
115+
ToolCommandName[] commandsFromPackage = [.. toolPackageCommands.Select(t => t.Name)];
116+
foreach (var command in commandsFromManifest)
117+
{
118+
if (!commandsFromPackage.Contains(command))
119+
{
120+
return false;
121+
}
122+
}
123+
124+
foreach (var command in commandsFromPackage)
125+
{
126+
if (!commandsFromManifest.Contains(command))
127+
{
128+
return false;
129+
}
130+
}
131+
132+
return true;
133+
}
134+
135+
public bool PackageHasBeenRestored(
136+
ToolManifestPackage package,
137+
string targetFramework)
138+
{
139+
var sampleRestoredCommandIdentifierOfThePackage = new RestoredCommandIdentifier(
140+
package.PackageId,
141+
package.Version,
142+
NuGetFramework.Parse(targetFramework),
143+
Constants.AnyRid,
144+
package.CommandNames.First());
145+
146+
return _localToolsResolverCache.TryLoad(
147+
sampleRestoredCommandIdentifierOfThePackage,
148+
out var toolCommand)
149+
&& _fileSystem.File.Exists(toolCommand.Executable.Value);
150+
}
151+
152+
private static string JoinBySpaceWithQuote(IEnumerable<object> objects)
153+
{
154+
return string.Join(" ", objects.Select(o => $"\"{o.ToString()}\""));
155+
}
156+
157+
private static VersionRange ToVersionRangeWithOnlyOneVersion(NuGetVersion version)
158+
{
159+
return new VersionRange(
160+
version,
161+
includeMinVersion: true,
162+
maxVersion: version,
163+
includeMaxVersion: true);
164+
}
165+
}
166+

src/Cli/dotnet/Commands/Tool/Restore/ToolRestoreCommand.cs

Lines changed: 11 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,19 @@ public override int Execute()
103103
return 0;
104104
}
105105

106+
var toolPackageRestorer = new ToolPackageRestorer(
107+
_toolPackageDownloader,
108+
_sources,
109+
overrideSources: [],
110+
_verbosity,
111+
_restoreActionConfig,
112+
_localToolsResolverCache,
113+
_fileSystem);
114+
106115
ToolRestoreResult[] toolRestoreResults =
107116
[.. packagesFromManifest
108117
.AsEnumerable()
109-
.Select(package => InstallPackages(package, configFile))];
118+
.Select(package => toolPackageRestorer.InstallPackages(package, configFile))];
110119

111120
Dictionary<RestoredCommandIdentifier, ToolCommand> downloaded =
112121
toolRestoreResults.SelectMany(result => result.SaveToCache)
@@ -119,66 +128,6 @@ [.. packagesFromManifest
119128
return PrintConclusionAndReturn(toolRestoreResults);
120129
}
121130

122-
private ToolRestoreResult InstallPackages(
123-
ToolManifestPackage package,
124-
FilePath? configFile)
125-
{
126-
string targetFramework = BundledTargetFramework.GetTargetFrameworkMoniker();
127-
128-
if (PackageHasBeenRestored(package, targetFramework))
129-
{
130-
return ToolRestoreResult.Success(
131-
saveToCache: [],
132-
message: string.Format(
133-
CliCommandStrings.RestoreSuccessful, package.PackageId,
134-
package.Version.ToNormalizedString(), string.Join(", ", package.CommandNames)));
135-
}
136-
137-
try
138-
{
139-
IToolPackage toolPackage =
140-
_toolPackageDownloader.InstallPackage(
141-
new PackageLocation(
142-
nugetConfig: configFile,
143-
additionalFeeds: _sources,
144-
rootConfigDirectory: package.FirstEffectDirectory),
145-
package.PackageId,
146-
verbosity: _verbosity,
147-
ToVersionRangeWithOnlyOneVersion(package.Version),
148-
targetFramework,
149-
restoreActionConfig: _restoreActionConfig
150-
);
151-
152-
if (!ManifestCommandMatchesActualInPackage(package.CommandNames, [toolPackage.Command]))
153-
{
154-
return ToolRestoreResult.Failure(
155-
string.Format(CliCommandStrings.CommandsMismatch,
156-
JoinBySpaceWithQuote(package.CommandNames.Select(c => c.Value.ToString())),
157-
package.PackageId,
158-
toolPackage.Command.Name));
159-
}
160-
161-
return ToolRestoreResult.Success(
162-
saveToCache:
163-
[(new RestoredCommandIdentifier(
164-
toolPackage.Id,
165-
toolPackage.Version,
166-
NuGetFramework.Parse(targetFramework),
167-
Constants.AnyRid,
168-
toolPackage.Command.Name),
169-
toolPackage.Command)],
170-
message: string.Format(
171-
CliCommandStrings.RestoreSuccessful,
172-
package.PackageId,
173-
package.Version.ToNormalizedString(),
174-
string.Join(" ", package.CommandNames)));
175-
}
176-
catch (ToolPackageException e)
177-
{
178-
return ToolRestoreResult.Failure(package.PackageId, e);
179-
}
180-
}
181-
182131
private int PrintConclusionAndReturn(ToolRestoreResult[] toolRestoreResults)
183132
{
184133
if (toolRestoreResults.Any(r => !r.IsSuccess))
@@ -214,47 +163,6 @@ private int PrintConclusionAndReturn(ToolRestoreResult[] toolRestoreResults)
214163
}
215164
}
216165

217-
private static bool ManifestCommandMatchesActualInPackage(
218-
ToolCommandName[] commandsFromManifest,
219-
IReadOnlyList<ToolCommand> toolPackageCommands)
220-
{
221-
ToolCommandName[] commandsFromPackage = [.. toolPackageCommands.Select(t => t.Name)];
222-
foreach (var command in commandsFromManifest)
223-
{
224-
if (!commandsFromPackage.Contains(command))
225-
{
226-
return false;
227-
}
228-
}
229-
230-
foreach (var command in commandsFromPackage)
231-
{
232-
if (!commandsFromManifest.Contains(command))
233-
{
234-
return false;
235-
}
236-
}
237-
238-
return true;
239-
}
240-
241-
private bool PackageHasBeenRestored(
242-
ToolManifestPackage package,
243-
string targetFramework)
244-
{
245-
var sampleRestoredCommandIdentifierOfThePackage = new RestoredCommandIdentifier(
246-
package.PackageId,
247-
package.Version,
248-
NuGetFramework.Parse(targetFramework),
249-
Constants.AnyRid,
250-
package.CommandNames.First());
251-
252-
return _localToolsResolverCache.TryLoad(
253-
sampleRestoredCommandIdentifierOfThePackage,
254-
out var toolCommand)
255-
&& _fileSystem.File.Exists(toolCommand.Executable.Value);
256-
}
257-
258166
private FilePath? GetCustomManifestFileLocation()
259167
{
260168
string customFile = _parseResult.GetValue(ToolRestoreCommandParser.ToolManifestOption);
@@ -292,21 +200,7 @@ private static void EnsureNoCommandNameCollision(Dictionary<RestoredCommandIdent
292200
}
293201
}
294202

295-
private static string JoinBySpaceWithQuote(IEnumerable<object> objects)
296-
{
297-
return string.Join(" ", objects.Select(o => $"\"{o.ToString()}\""));
298-
}
299-
300-
private static VersionRange ToVersionRangeWithOnlyOneVersion(NuGetVersion version)
301-
{
302-
return new VersionRange(
303-
version,
304-
includeMinVersion: true,
305-
maxVersion: version,
306-
includeMaxVersion: true);
307-
}
308-
309-
private struct ToolRestoreResult
203+
public struct ToolRestoreResult
310204
{
311205
public (RestoredCommandIdentifier, ToolCommand)[] SaveToCache { get; }
312206
public bool IsSuccess { get; }

0 commit comments

Comments
 (0)