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

Commit 5ebbd61

Browse files
author
Peter Huene
committed
Fix case sensitivity of tool package identifiers.
This commit fixes the case sensitivity of tool package identifiers. Previously the install and uninstall commands unintentionally required the tool package ids to specified in all lowercase for the install / uninstall to work. Fixes #8682.
1 parent 4490fd5 commit 5ebbd61

Some content is hidden

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

44 files changed

+626
-176
lines changed

src/dotnet/CommonLocalizableStrings.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,9 @@ setx PATH "%PATH%;{0}"
619619
<data name="ToolPackageConflictPackageId" xml:space="preserve">
620620
<value>Tool '{0}' (version '{1}') is already installed.</value>
621621
</data>
622+
<data name="FailedToFindStagedToolPackage" xml:space="preserve">
623+
<value>Failed to find staged tool package '{0}'.</value>
624+
</data>
622625
<data name="ColumnMaxWidthMustBeGreaterThanZero" xml:space="preserve">
623626
<value>Column maximum width must be greater than zero.</value>
624627
</data>

src/dotnet/ToolPackage/IToolPackage.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@
44
using System;
55
using System.Collections.Generic;
66
using Microsoft.Extensions.EnvironmentAbstractions;
7+
using NuGet.Versioning;
78

89
namespace Microsoft.DotNet.ToolPackage
910
{
1011
internal interface IToolPackage
1112
{
12-
string PackageId { get; }
13+
PackageId Id { get; }
1314

14-
string PackageVersion { get; }
15+
NuGetVersion Version { get; }
1516

1617
DirectoryPath PackageDirectory { get; }
1718

src/dotnet/ToolPackage/IToolPackageInstaller.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@
44
using System;
55
using System.Collections.Generic;
66
using Microsoft.Extensions.EnvironmentAbstractions;
7+
using NuGet.Versioning;
78

89
namespace Microsoft.DotNet.ToolPackage
910
{
1011
internal interface IToolPackageInstaller
1112
{
1213
IToolPackage InstallPackage(
13-
string packageId,
14-
string packageVersion = null,
14+
PackageId packageId,
15+
VersionRange versionRange = null,
1516
string targetFramework = null,
1617
FilePath? nugetConfig = null,
1718
string source = null,

src/dotnet/ToolPackage/IToolPackageStore.cs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,26 @@
44
using System;
55
using System.Collections.Generic;
66
using Microsoft.Extensions.EnvironmentAbstractions;
7+
using NuGet.Versioning;
78

89
namespace Microsoft.DotNet.ToolPackage
910
{
1011
internal interface IToolPackageStore
1112
{
1213
DirectoryPath Root { get; }
1314

14-
IEnumerable<IToolPackage> GetInstalledPackages(string packageId = null);
15+
DirectoryPath GetRandomStagingDirectory();
16+
17+
NuGetVersion GetStagedPackageVersion(DirectoryPath stagingDirectory, PackageId packageId);
18+
19+
DirectoryPath GetRootPackageDirectory(PackageId packageId);
20+
21+
DirectoryPath GetPackageDirectory(PackageId packageId, NuGetVersion version);
22+
23+
IEnumerable<IToolPackage> EnumeratePackages();
24+
25+
IEnumerable<IToolPackage> EnumeratePackageVersions(PackageId packageId);
26+
27+
IToolPackage GetPackage(PackageId packageId, NuGetVersion version);
1528
}
1629
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
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;
5+
using Microsoft.DotNet.InternalAbstractions;
6+
7+
namespace Microsoft.DotNet.ToolPackage
8+
{
9+
internal struct PackageId : IEquatable<PackageId>, IComparable<PackageId>
10+
{
11+
private string _id;
12+
13+
public PackageId(string id)
14+
{
15+
_id = id?.ToLowerInvariant() ?? throw new ArgumentNullException(nameof(id));
16+
}
17+
18+
public bool Equals(PackageId other)
19+
{
20+
return ToString() == other.ToString();
21+
}
22+
23+
public int CompareTo(PackageId other)
24+
{
25+
return string.Compare(ToString(), other.ToString(), StringComparison.Ordinal);
26+
}
27+
28+
public override bool Equals(object obj)
29+
{
30+
return obj is PackageId id && Equals(id);
31+
}
32+
33+
public override int GetHashCode()
34+
{
35+
return ToString().GetHashCode();
36+
}
37+
38+
public override string ToString()
39+
{
40+
return _id ?? "";
41+
}
42+
}
43+
}

src/dotnet/ToolPackage/ToolPackageInstaller.cs

Lines changed: 15 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,12 @@
77
using Microsoft.DotNet.Configurer;
88
using Microsoft.DotNet.Tools;
99
using Microsoft.Extensions.EnvironmentAbstractions;
10+
using NuGet.Versioning;
1011

1112
namespace Microsoft.DotNet.ToolPackage
1213
{
1314
internal class ToolPackageInstaller : IToolPackageInstaller
1415
{
15-
public const string StagingDirectory = ".stage";
16-
1716
private readonly IToolPackageStore _store;
1817
private readonly IProjectRestorer _projectRestorer;
1918
private readonly FilePath? _tempProject;
@@ -32,33 +31,27 @@ public ToolPackageInstaller(
3231
}
3332

3433
public IToolPackage InstallPackage(
35-
string packageId,
36-
string packageVersion = null,
34+
PackageId packageId,
35+
VersionRange versionRange = null,
3736
string targetFramework = null,
3837
FilePath? nugetConfig = null,
3938
string source = null,
4039
string verbosity = null)
4140
{
42-
if (packageId == null)
43-
{
44-
throw new ArgumentNullException(nameof(packageId));
45-
}
46-
47-
var packageRootDirectory = _store.Root.WithSubDirectories(packageId);
41+
var packageRootDirectory = _store.GetRootPackageDirectory(packageId);
4842
string rollbackDirectory = null;
4943

5044
return TransactionalAction.Run<IToolPackage>(
5145
action: () => {
5246
try
5347
{
54-
55-
var stageDirectory = _store.Root.WithSubDirectories(StagingDirectory, Path.GetRandomFileName());
48+
var stageDirectory = _store.GetRandomStagingDirectory();
5649
Directory.CreateDirectory(stageDirectory.Value);
5750
rollbackDirectory = stageDirectory.Value;
5851

5952
var tempProject = CreateTempProject(
6053
packageId: packageId,
61-
packageVersion: packageVersion,
54+
versionRange: versionRange,
6255
targetFramework: targetFramework ?? BundledTargetFramework.GetTargetFrameworkMoniker(),
6356
restoreDirectory: stageDirectory);
6457

@@ -76,29 +69,22 @@ public IToolPackage InstallPackage(
7669
File.Delete(tempProject.Value);
7770
}
7871

79-
packageVersion = Path.GetFileName(
80-
Directory.EnumerateDirectories(
81-
stageDirectory.WithSubDirectories(packageId).Value).Single());
82-
83-
var packageDirectory = packageRootDirectory.WithSubDirectories(packageVersion);
72+
var version = _store.GetStagedPackageVersion(stageDirectory, packageId);
73+
var packageDirectory = _store.GetPackageDirectory(packageId, version);
8474
if (Directory.Exists(packageDirectory.Value))
8575
{
8676
throw new ToolPackageException(
8777
string.Format(
8878
CommonLocalizableStrings.ToolPackageConflictPackageId,
8979
packageId,
90-
packageVersion));
80+
version.ToNormalizedString()));
9181
}
9282

9383
Directory.CreateDirectory(packageRootDirectory.Value);
9484
Directory.Move(stageDirectory.Value, packageDirectory.Value);
9585
rollbackDirectory = packageDirectory.Value;
9686

97-
return new ToolPackageInstance(
98-
_store,
99-
packageId,
100-
packageVersion,
101-
packageDirectory);
87+
return new ToolPackageInstance(_store, packageId, version, packageDirectory);
10288
}
10389
catch (Exception ex) when (ex is UnauthorizedAccessException || ex is IOException)
10490
{
@@ -126,8 +112,8 @@ public IToolPackage InstallPackage(
126112
}
127113

128114
private FilePath CreateTempProject(
129-
string packageId,
130-
string packageVersion,
115+
PackageId packageId,
116+
VersionRange versionRange,
131117
string targetFramework,
132118
DirectoryPath restoreDirectory)
133119
{
@@ -159,8 +145,9 @@ private FilePath CreateTempProject(
159145
new XElement("DisableImplicitNuGetFallbackFolder", "true")), // disable SDK side implicit NuGetFallbackFolder
160146
new XElement("ItemGroup",
161147
new XElement("PackageReference",
162-
new XAttribute("Include", packageId),
163-
new XAttribute("Version", packageVersion ?? "*") // nuget will restore * for latest
148+
new XAttribute("Include", packageId.ToString()),
149+
new XAttribute("Version",
150+
versionRange?.ToString("S", new VersionRangeFormatter()) ?? "*") // nuget will restore latest stable for *
164151
))
165152
));
166153

src/dotnet/ToolPackage/ToolPackageInstance.cs

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using Microsoft.DotNet.Tools;
77
using Microsoft.Extensions.EnvironmentAbstractions;
88
using NuGet.ProjectModel;
9+
using NuGet.Versioning;
910

1011
namespace Microsoft.DotNet.ToolPackage
1112
{
@@ -17,20 +18,21 @@ internal class ToolPackageInstance : IToolPackage
1718

1819
public ToolPackageInstance(
1920
IToolPackageStore store,
20-
string packageId,
21-
string packageVersion,
21+
PackageId id,
22+
NuGetVersion version,
2223
DirectoryPath packageDirectory)
2324
{
2425
_store = store ?? throw new ArgumentNullException(nameof(store));
25-
PackageId = packageId ?? throw new ArgumentNullException(nameof(packageId));
26-
PackageVersion = packageVersion ?? throw new ArgumentNullException(nameof(packageVersion));
27-
PackageDirectory = packageDirectory;
2826
_commands = new Lazy<IReadOnlyList<CommandSettings>>(GetCommands);
27+
28+
Id = id;
29+
Version = version ?? throw new ArgumentNullException(nameof(version));
30+
PackageDirectory = packageDirectory;
2931
}
3032

31-
public string PackageId { get; private set; }
33+
public PackageId Id { get; private set; }
3234

33-
public string PackageVersion { get; private set; }
35+
public NuGetVersion Version { get; private set; }
3436

3537
public DirectoryPath PackageDirectory { get; private set; }
3638

@@ -53,13 +55,9 @@ public void Uninstall()
5355
{
5456
if (Directory.Exists(PackageDirectory.Value))
5557
{
56-
// Use the same staging directory for uninstall instead of temp
58+
// Use the staging directory for uninstall
5759
// This prevents cross-device moves when temp is mounted to a different device
58-
var tempPath = _store
59-
.Root
60-
.WithSubDirectories(ToolPackageInstaller.StagingDirectory)
61-
.WithFile(Path.GetRandomFileName())
62-
.Value;
60+
var tempPath = _store.GetRandomStagingDirectory().Value;
6361
Directory.Move(PackageDirectory.Value, tempPath);
6462
tempPackageDirectory = tempPath;
6563
}
@@ -75,7 +73,7 @@ public void Uninstall()
7573
throw new ToolPackageException(
7674
string.Format(
7775
CommonLocalizableStrings.FailedToUninstallToolPackage,
78-
PackageId,
76+
Id,
7977
ex.Message),
8078
ex);
8179
}
@@ -116,7 +114,7 @@ private IReadOnlyList<CommandSettings> GetCommands()
116114
var toolConfigurationPath =
117115
PackageDirectory
118116
.WithSubDirectories(
119-
PackageId,
117+
Id.ToString(),
120118
library.Version.ToNormalizedString())
121119
.WithFile(dotnetToolSettings.Path);
122120

@@ -138,7 +136,7 @@ private IReadOnlyList<CommandSettings> GetCommands()
138136
"dotnet",
139137
PackageDirectory
140138
.WithSubDirectories(
141-
PackageId,
139+
Id.ToString(),
142140
library.Version.ToNormalizedString())
143141
.WithFile(entryPointFromLockFile.Path)));
144142

@@ -158,7 +156,8 @@ private LockFileTargetLibrary FindLibraryInLockFile(LockFile lockFile)
158156
{
159157
return lockFile
160158
?.Targets?.SingleOrDefault(t => t.RuntimeIdentifier != null)
161-
?.Libraries?.SingleOrDefault(l => l.Name == PackageId);
159+
?.Libraries?.SingleOrDefault(l =>
160+
string.Compare(l.Name, Id.ToString(), StringComparison.CurrentCultureIgnoreCase) == 0);
162161
}
163162

164163
private static LockFileItem FindItemInTargetLibrary(LockFileTargetLibrary library, string targetRelativeFilePath)

0 commit comments

Comments
 (0)