dependabot-nuget 0.286.0 → 0.287.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/AnalyzeWorker.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/CompatabilityChecker.cs +24 -5
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/NuGetContext.cs +15 -4
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/VersionFinder.cs +9 -38
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DiscoveryWorker.cs +8 -6
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/ProjectBuildFile.cs +15 -8
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackageReferenceUpdater.cs +15 -5
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +5 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/PathHelper.cs +49 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTests.cs +302 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.cs +269 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/RunWorkerTests.cs +250 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackageReference.cs +40 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/PathHelperTests.cs +14 -0
- data/helpers/lib/NuGetUpdater/global.json +1 -1
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3bb2d903f08322511a7917fba47df7b66208dbbaca42e52d30a1954f9ef3eaa2
|
4
|
+
data.tar.gz: f19cfed3ad2939c93812727546b53ecec603c712641a6c1d0581469cce72d584
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a3fdc15bd985678106cf45f57c6af6dd4be57858f54b50abea6f4521a8aed3ab66b7ca67cb54f9e73dabe536d8c012619bbf049662207211bc92cbb5e938c321
|
7
|
+
data.tar.gz: 3542f489f10b67fe78b3bd55703cc420a58279bf5fb131da4a99be0d99a20fcd7430b124c4b49100929b74f39178b3c7e108e7bb0170baef5f5a91a16dfbd63f
|
@@ -50,7 +50,7 @@ public partial class AnalyzeWorker : IAnalyzeWorker
|
|
50
50
|
when (ex.StatusCode == HttpStatusCode.Unauthorized || ex.StatusCode == HttpStatusCode.Forbidden)
|
51
51
|
{
|
52
52
|
var localPath = PathHelper.JoinPath(repoRoot, discovery.Path);
|
53
|
-
var nugetContext = new NuGetContext(localPath);
|
53
|
+
using var nugetContext = new NuGetContext(localPath);
|
54
54
|
analysisResult = new AnalysisResult
|
55
55
|
{
|
56
56
|
ErrorType = ErrorType.AuthenticationFailure,
|
@@ -24,11 +24,16 @@ internal static class CompatibilityChecker
|
|
24
24
|
ILogger logger,
|
25
25
|
CancellationToken cancellationToken)
|
26
26
|
{
|
27
|
-
var
|
27
|
+
var packageInfo = await GetPackageInfoAsync(
|
28
28
|
package,
|
29
29
|
nugetContext,
|
30
30
|
cancellationToken);
|
31
|
+
if (packageInfo is null)
|
32
|
+
{
|
33
|
+
return false;
|
34
|
+
}
|
31
35
|
|
36
|
+
var (isDevDependency, packageFrameworks) = packageInfo.GetValueOrDefault();
|
32
37
|
return PerformCheck(package, projectFrameworks, isDevDependency, packageFrameworks, logger);
|
33
38
|
}
|
34
39
|
|
@@ -70,7 +75,7 @@ internal static class CompatibilityChecker
|
|
70
75
|
return true;
|
71
76
|
}
|
72
77
|
|
73
|
-
internal static async Task<
|
78
|
+
internal static async Task<PackageReaders?> GetPackageReadersAsync(
|
74
79
|
PackageIdentity package,
|
75
80
|
NuGetContext nugetContext,
|
76
81
|
CancellationToken cancellationToken)
|
@@ -79,7 +84,21 @@ internal static class CompatibilityChecker
|
|
79
84
|
var readers = File.Exists(tempPackagePath)
|
80
85
|
? ReadPackage(tempPackagePath)
|
81
86
|
: await DownloadPackageAsync(package, nugetContext, cancellationToken);
|
87
|
+
return readers;
|
88
|
+
}
|
89
|
+
|
90
|
+
internal static async Task<PackageInfo?> GetPackageInfoAsync(
|
91
|
+
PackageIdentity package,
|
92
|
+
NuGetContext nugetContext,
|
93
|
+
CancellationToken cancellationToken)
|
94
|
+
{
|
95
|
+
var readersOption = await GetPackageReadersAsync(package, nugetContext, cancellationToken);
|
96
|
+
if (readersOption is null)
|
97
|
+
{
|
98
|
+
return null;
|
99
|
+
}
|
82
100
|
|
101
|
+
var readers = readersOption.GetValueOrDefault();
|
83
102
|
var nuspecStream = await readers.CoreReader.GetNuspecAsync(cancellationToken);
|
84
103
|
var reader = new NuspecReader(nuspecStream);
|
85
104
|
|
@@ -127,7 +146,7 @@ internal static class CompatibilityChecker
|
|
127
146
|
return (archiveReader, archiveReader);
|
128
147
|
}
|
129
148
|
|
130
|
-
internal static async Task<PackageReaders
|
149
|
+
internal static async Task<PackageReaders?> DownloadPackageAsync(
|
131
150
|
PackageIdentity package,
|
132
151
|
NuGetContext context,
|
133
152
|
CancellationToken cancellationToken)
|
@@ -179,13 +198,13 @@ internal static class CompatibilityChecker
|
|
179
198
|
var isDownloaded = await downloader.CopyNupkgFileToAsync(tempPackagePath, cancellationToken);
|
180
199
|
if (!isDownloaded)
|
181
200
|
{
|
182
|
-
|
201
|
+
continue;
|
183
202
|
}
|
184
203
|
|
185
204
|
return (downloader.CoreReader, downloader.ContentReader);
|
186
205
|
}
|
187
206
|
|
188
|
-
|
207
|
+
return null;
|
189
208
|
}
|
190
209
|
|
191
210
|
internal static string GetTempPackagePath(PackageIdentity package, NuGetContext context)
|
@@ -142,11 +142,22 @@ internal record NuGetContext : IDisposable
|
|
142
142
|
}
|
143
143
|
|
144
144
|
var metadataResource = await sourceRepository.GetResourceAsync<PackageMetadataResource>(cancellationToken);
|
145
|
-
|
146
|
-
var url = metadata.ProjectUrl ?? metadata.LicenseUrl;
|
147
|
-
if (url is not null)
|
145
|
+
if (metadataResource is not null)
|
148
146
|
{
|
149
|
-
|
147
|
+
try
|
148
|
+
{
|
149
|
+
var metadata = await metadataResource.GetMetadataAsync(packageIdentity, SourceCacheContext, Logger, cancellationToken);
|
150
|
+
var url = metadata.ProjectUrl ?? metadata.LicenseUrl;
|
151
|
+
if (url is not null)
|
152
|
+
{
|
153
|
+
return url.ToString();
|
154
|
+
}
|
155
|
+
}
|
156
|
+
catch (ArgumentException)
|
157
|
+
{
|
158
|
+
// there was an issue deserializing the package metadata; this doesn't necessarily mean the package
|
159
|
+
// is unavailable, just that we can't return a URL
|
160
|
+
}
|
150
161
|
}
|
151
162
|
}
|
152
163
|
|
@@ -151,46 +151,17 @@ internal static class VersionFinder
|
|
151
151
|
ILogger logger,
|
152
152
|
CancellationToken cancellationToken)
|
153
153
|
{
|
154
|
-
|
155
|
-
|
156
|
-
var
|
157
|
-
|
158
|
-
var sources = packageSources.Count == 0
|
159
|
-
? nugetContext.PackageSources
|
160
|
-
: nugetContext.PackageSources
|
161
|
-
.Where(p => packageSources.Contains(p.Name))
|
162
|
-
.ToImmutableArray();
|
163
|
-
|
164
|
-
foreach (var source in sources)
|
154
|
+
// if it can be downloaded, it exists
|
155
|
+
var downloader = await CompatibilityChecker.DownloadPackageAsync(new PackageIdentity(packageId, version), nugetContext, cancellationToken);
|
156
|
+
var packageAndVersionExists = downloader is not null;
|
157
|
+
if (packageAndVersionExists)
|
165
158
|
{
|
166
|
-
|
167
|
-
var
|
168
|
-
|
169
|
-
|
170
|
-
logger.Log($"Failed to get MetadataResource for [{source.Source}]");
|
171
|
-
continue;
|
172
|
-
}
|
173
|
-
|
174
|
-
try
|
175
|
-
{
|
176
|
-
// a non-compliant v2 API returning 404 can cause this to throw
|
177
|
-
var existsInFeed = await feed.Exists(
|
178
|
-
new PackageIdentity(packageId, version),
|
179
|
-
includeUnlisted: false,
|
180
|
-
nugetContext.SourceCacheContext,
|
181
|
-
NullLogger.Instance,
|
182
|
-
cancellationToken);
|
183
|
-
if (existsInFeed)
|
184
|
-
{
|
185
|
-
return true;
|
186
|
-
}
|
187
|
-
}
|
188
|
-
catch (FatalProtocolException)
|
189
|
-
{
|
190
|
-
// if anything goes wrong here, the package source obviously doesn't contain the requested package
|
191
|
-
}
|
159
|
+
// release the handles
|
160
|
+
var readers = downloader.GetValueOrDefault();
|
161
|
+
(readers.CoreReader as IDisposable)?.Dispose();
|
162
|
+
(readers.ContentReader as IDisposable)?.Dispose();
|
192
163
|
}
|
193
164
|
|
194
|
-
return
|
165
|
+
return packageAndVersionExists;
|
195
166
|
}
|
196
167
|
}
|
@@ -275,22 +275,24 @@ public partial class DiscoveryWorker : IDiscoveryWorker
|
|
275
275
|
foreach (var projectPath in projectPaths)
|
276
276
|
{
|
277
277
|
// If there is some MSBuild logic that needs to run to fully resolve the path skip the project
|
278
|
-
|
278
|
+
// Ensure file existence is checked case-insensitively
|
279
|
+
var actualProjectPath = PathHelper.ResolveCaseInsensitivePathInsideRepoRoot(projectPath, repoRootPath);
|
280
|
+
if (actualProjectPath == null)
|
279
281
|
{
|
280
282
|
continue;
|
281
283
|
}
|
282
284
|
|
283
|
-
if (_processedProjectPaths.Contains(
|
285
|
+
if (_processedProjectPaths.Contains(actualProjectPath))
|
284
286
|
{
|
285
287
|
continue;
|
286
288
|
}
|
287
|
-
_processedProjectPaths.Add(
|
289
|
+
_processedProjectPaths.Add(actualProjectPath);
|
288
290
|
|
289
|
-
var relativeProjectPath = Path.GetRelativePath(workspacePath,
|
291
|
+
var relativeProjectPath = Path.GetRelativePath(workspacePath, actualProjectPath);
|
290
292
|
var packagesConfigDependencies = PackagesConfigDiscovery.Discover(workspacePath, projectPath, _logger)
|
291
293
|
?.Dependencies;
|
292
294
|
|
293
|
-
var projectResults = await SdkProjectDiscovery.DiscoverAsync(repoRootPath, workspacePath,
|
295
|
+
var projectResults = await SdkProjectDiscovery.DiscoverAsync(repoRootPath, workspacePath, actualProjectPath, _logger);
|
294
296
|
|
295
297
|
// Determine if there were unrestored MSBuildSdks
|
296
298
|
var msbuildSdks = projectResults.SelectMany(p => p.Dependencies.Where(d => d.Type == DependencyType.MSBuildSdk)).ToImmutableArray();
|
@@ -299,7 +301,7 @@ public partial class DiscoveryWorker : IDiscoveryWorker
|
|
299
301
|
// If new SDKs were restored, then we need to rerun SdkProjectDiscovery.
|
300
302
|
if (await TryRestoreMSBuildSdksAsync(repoRootPath, workspacePath, msbuildSdks, _logger))
|
301
303
|
{
|
302
|
-
projectResults = await SdkProjectDiscovery.DiscoverAsync(repoRootPath, workspacePath,
|
304
|
+
projectResults = await SdkProjectDiscovery.DiscoverAsync(repoRootPath, workspacePath, actualProjectPath, _logger);
|
303
305
|
}
|
304
306
|
}
|
305
307
|
|
@@ -43,7 +43,7 @@ internal sealed class ProjectBuildFile : XmlBuildFile
|
|
43
43
|
{
|
44
44
|
var sdkDependencies = GetSdkDependencies();
|
45
45
|
var packageDependencies = PackageItemNodes
|
46
|
-
.
|
46
|
+
.SelectMany(e => GetPackageDependencies(e) ?? Enumerable.Empty<Dependency>())
|
47
47
|
.OfType<Dependency>();
|
48
48
|
return sdkDependencies.Concat(packageDependencies);
|
49
49
|
}
|
@@ -89,8 +89,9 @@ internal sealed class ProjectBuildFile : XmlBuildFile
|
|
89
89
|
: new Dependency(name, version, DependencyType.MSBuildSdk);
|
90
90
|
}
|
91
91
|
|
92
|
-
private static Dependency
|
92
|
+
private static IEnumerable<Dependency>? GetPackageDependencies(IXmlElementSyntax element)
|
93
93
|
{
|
94
|
+
List<Dependency> dependencies = [];
|
94
95
|
var isUpdate = false;
|
95
96
|
|
96
97
|
var name = element.GetAttributeOrSubElementValue("Include", StringComparison.OrdinalIgnoreCase)?.Trim();
|
@@ -113,12 +114,18 @@ internal sealed class ProjectBuildFile : XmlBuildFile
|
|
113
114
|
isVersionOverride = version is not null;
|
114
115
|
}
|
115
116
|
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
117
|
+
dependencies.AddRange(
|
118
|
+
name.Split(';', StringSplitOptions.RemoveEmptyEntries)
|
119
|
+
.Select(dep => new Dependency(
|
120
|
+
Name: dep.Trim(),
|
121
|
+
Version: string.IsNullOrEmpty(version) ? null : version,
|
122
|
+
Type: GetDependencyType(element.Name),
|
123
|
+
IsUpdate: isUpdate,
|
124
|
+
IsOverride: isVersionOverride))
|
125
|
+
);
|
126
|
+
|
127
|
+
|
128
|
+
return dependencies;
|
122
129
|
}
|
123
130
|
|
124
131
|
private static DependencyType GetDependencyType(string name)
|
@@ -674,11 +674,21 @@ internal static class PackageReferenceUpdater
|
|
674
674
|
ProjectBuildFile buildFile,
|
675
675
|
string packageName)
|
676
676
|
=> buildFile.PackageItemNodes.Where(e =>
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
677
|
+
{
|
678
|
+
// Attempt to get "Include" or "Update" attribute values
|
679
|
+
var includeOrUpdateValue = e.GetAttributeOrSubElementValue("Include", StringComparison.OrdinalIgnoreCase)
|
680
|
+
?? e.GetAttributeOrSubElementValue("Update", StringComparison.OrdinalIgnoreCase);
|
681
|
+
// Trim and split if there's a valid value
|
682
|
+
var packageNames = includeOrUpdateValue?
|
683
|
+
.Trim()
|
684
|
+
.Split(';', StringSplitOptions.RemoveEmptyEntries)
|
685
|
+
.Select(t => t.Trim())
|
686
|
+
.Where(t => t.Equals(packageName.Trim(), StringComparison.OrdinalIgnoreCase));
|
687
|
+
// Check if there's a matching package name and a non-null version attribute
|
688
|
+
return packageNames?.Any() == true &&
|
689
|
+
(e.GetAttributeOrSubElementValue("Version", StringComparison.OrdinalIgnoreCase)
|
690
|
+
?? e.GetAttributeOrSubElementValue("VersionOverride", StringComparison.OrdinalIgnoreCase)) is not null;
|
691
|
+
});
|
682
692
|
|
683
693
|
private static async Task<bool> AreDependenciesCoherentAsync(string repoRootPath, string projectPath, string dependencyName, ILogger logger, ImmutableArray<ProjectBuildFile> buildFiles, string[] tfms)
|
684
694
|
{
|
@@ -261,7 +261,11 @@ internal static partial class MSBuildHelper
|
|
261
261
|
? evaluationResult.EvaluatedValue.TrimStart('[', '(').TrimEnd(']', ')')
|
262
262
|
: evaluationResult.EvaluatedValue;
|
263
263
|
|
264
|
-
|
264
|
+
// If at this point we have a semicolon in the name then split it and yield multiple dependencies.
|
265
|
+
foreach (var splitName in name.Split(';', StringSplitOptions.RemoveEmptyEntries))
|
266
|
+
{
|
267
|
+
yield return new Dependency(splitName.Trim(), packageVersion, dependencyType, EvaluationResult: evaluationResult, IsUpdate: isUpdate);
|
268
|
+
}
|
265
269
|
}
|
266
270
|
}
|
267
271
|
|
@@ -87,6 +87,55 @@ internal static class PathHelper
|
|
87
87
|
return candidatePaths.ToArray();
|
88
88
|
}
|
89
89
|
|
90
|
+
/// <summary>
|
91
|
+
/// Resolves the case of the file path in a case-insensitive manner. Returns null if the file path is not found. file path must be a full path inside the repoRootPath.
|
92
|
+
/// </summary>
|
93
|
+
/// <param name="filePath">The file path to resolve.</param>
|
94
|
+
/// <param name="repoRootPath">The root path of the repository.</param>
|
95
|
+
public static string? ResolveCaseInsensitivePathInsideRepoRoot(string filePath, string repoRootPath)
|
96
|
+
{
|
97
|
+
if (string.IsNullOrEmpty(filePath) || string.IsNullOrEmpty(repoRootPath))
|
98
|
+
{
|
99
|
+
return null; // Invalid input
|
100
|
+
}
|
101
|
+
|
102
|
+
// Normalize paths
|
103
|
+
var normalizedFilePath = filePath.FullyNormalizedRootedPath();
|
104
|
+
var normalizedRepoRoot = repoRootPath.FullyNormalizedRootedPath();
|
105
|
+
|
106
|
+
// Ensure the file path starts with the repo root path
|
107
|
+
if (!normalizedFilePath.StartsWith(normalizedRepoRoot + "/", StringComparison.OrdinalIgnoreCase))
|
108
|
+
{
|
109
|
+
return null; // filePath is outside of repoRootPath
|
110
|
+
}
|
111
|
+
|
112
|
+
// Start resolving from the root path
|
113
|
+
var currentPath = normalizedRepoRoot;
|
114
|
+
var relativePath = normalizedFilePath.Substring(normalizedRepoRoot.Length).TrimStart('/');
|
115
|
+
|
116
|
+
foreach (var part in relativePath.Split('/'))
|
117
|
+
{
|
118
|
+
if (string.IsNullOrEmpty(part))
|
119
|
+
{
|
120
|
+
continue;
|
121
|
+
}
|
122
|
+
|
123
|
+
// Enumerate the current directory to find a case-insensitive match
|
124
|
+
var nextPath = Directory
|
125
|
+
.EnumerateFileSystemEntries(currentPath)
|
126
|
+
.FirstOrDefault(entry => string.Equals(Path.GetFileName(entry), part, StringComparison.OrdinalIgnoreCase));
|
127
|
+
|
128
|
+
if (nextPath == null)
|
129
|
+
{
|
130
|
+
return null; // Part of the path does not exist
|
131
|
+
}
|
132
|
+
|
133
|
+
currentPath = nextPath;
|
134
|
+
}
|
135
|
+
|
136
|
+
return currentPath; // Fully resolved path with correct casing
|
137
|
+
}
|
138
|
+
|
90
139
|
/// <summary>
|
91
140
|
/// Check in every directory from <paramref name="initialPath"/> up to <paramref name="rootPath"/> for the file specified in <paramref name="fileName"/>.
|
92
141
|
/// </summary>
|