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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 01a6eb36ac3591d016d45ddfc4fc9dbb4068bda72e8560b6453461f5019362f7
4
- data.tar.gz: 4db4968d74f3b9bfac17cbf32a8017635b07cf5338ad0f9db53dd9a16b188874
3
+ metadata.gz: 3bb2d903f08322511a7917fba47df7b66208dbbaca42e52d30a1954f9ef3eaa2
4
+ data.tar.gz: f19cfed3ad2939c93812727546b53ecec603c712641a6c1d0581469cce72d584
5
5
  SHA512:
6
- metadata.gz: 1fce16345ed91813776f2b83b802212e466e15cf5784fcd239c8907ec3af683f0727b7a8e00df7fcb6b97035802c68023ddeb2481a28acce479db6fdfdb6674b
7
- data.tar.gz: 59d4ac62296d157fbeb3870bcfc18313df3deac4e3f86c0c040ea0c2d2d3c73c1c8d0e84f05d32d83a9129583e6b6e38a1f5314e2cbd0df833c1657c5eb2d7f9
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 (isDevDependency, packageFrameworks) = await GetPackageInfoAsync(
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<PackageInfo> GetPackageInfoAsync(
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> DownloadPackageAsync(
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
- throw new Exception($"Failed to download package [{package.Id}/{package.Version}] from [${source.SourceUri}]");
201
+ continue;
183
202
  }
184
203
 
185
204
  return (downloader.CoreReader, downloader.ContentReader);
186
205
  }
187
206
 
188
- throw new Exception($"Package [{package.Id}/{package.Version}] does not exist in any of the configured sources.");
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
- var metadata = await metadataResource.GetMetadataAsync(packageIdentity, SourceCacheContext, Logger, cancellationToken);
146
- var url = metadata.ProjectUrl ?? metadata.LicenseUrl;
147
- if (url is not null)
145
+ if (metadataResource is not null)
148
146
  {
149
- return url.ToString();
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
- var includePrerelease = version.IsPrerelease;
155
-
156
- var sourceMapping = PackageSourceMapping.GetPackageSourceMapping(nugetContext.Settings);
157
- var packageSources = sourceMapping.GetConfiguredPackageSources(packageId).ToHashSet();
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
- var sourceRepository = Repository.Factory.GetCoreV3(source);
167
- var feed = await sourceRepository.GetResourceAsync<MetadataResource>();
168
- if (feed is null)
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 false;
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
- if (!File.Exists(projectPath))
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(projectPath))
285
+ if (_processedProjectPaths.Contains(actualProjectPath))
284
286
  {
285
287
  continue;
286
288
  }
287
- _processedProjectPaths.Add(projectPath);
289
+ _processedProjectPaths.Add(actualProjectPath);
288
290
 
289
- var relativeProjectPath = Path.GetRelativePath(workspacePath, projectPath);
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, projectPath, _logger);
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, projectPath, _logger);
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
- .Select(GetPackageDependency)
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? GetPackageDependency(IXmlElementSyntax element)
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
- return new Dependency(
117
- Name: name,
118
- Version: version?.Length == 0 ? null : version,
119
- Type: GetDependencyType(element.Name),
120
- IsUpdate: isUpdate,
121
- IsOverride: isVersionOverride);
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
- string.Equals(
678
- (e.GetAttributeOrSubElementValue("Include", StringComparison.OrdinalIgnoreCase) ?? e.GetAttributeOrSubElementValue("Update", StringComparison.OrdinalIgnoreCase))?.Trim(),
679
- packageName,
680
- StringComparison.OrdinalIgnoreCase) &&
681
- (e.GetAttributeOrSubElementValue("Version", StringComparison.OrdinalIgnoreCase) ?? e.GetAttributeOrSubElementValue("VersionOverride", StringComparison.OrdinalIgnoreCase)) is not null);
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
- yield return new Dependency(name, packageVersion, dependencyType, EvaluationResult: evaluationResult, IsUpdate: isUpdate);
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>