dependabot-nuget 0.248.0 → 0.250.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.Cli.Test/EntryPointTests.Update.cs +57 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/SdkPackageUpdater.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +26 -5
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.Sdk.cs +31 -0
- data/lib/dependabot/nuget/file_fetcher/import_paths_finder.rb +1 -0
- data/lib/dependabot/nuget/file_fetcher/sln_project_paths_finder.rb +2 -0
- data/lib/dependabot/nuget/file_parser/dotnet_tools_json_parser.rb +1 -0
- data/lib/dependabot/nuget/file_parser/global_json_parser.rb +1 -0
- data/lib/dependabot/nuget/file_parser/packages_config_parser.rb +1 -0
- data/lib/dependabot/nuget/file_parser/project_file_parser.rb +1 -0
- data/lib/dependabot/nuget/file_parser/property_value_finder.rb +2 -0
- data/lib/dependabot/nuget/file_parser.rb +32 -11
- data/lib/dependabot/nuget/file_updater/property_value_updater.rb +1 -0
- data/lib/dependabot/nuget/update_checker/compatibility_checker.rb +28 -7
- data/lib/dependabot/nuget/update_checker/dependency_finder.rb +70 -19
- data/lib/dependabot/nuget/update_checker/nuspec_fetcher.rb +1 -1
- data/lib/dependabot/nuget/update_checker/property_updater.rb +108 -44
- data/lib/dependabot/nuget/update_checker/repository_finder.rb +90 -18
- data/lib/dependabot/nuget/update_checker/tfm_comparer.rb +8 -3
- data/lib/dependabot/nuget/update_checker/tfm_finder.rb +51 -13
- 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: 144460a4e43c2169e3526841828a5a3baa717f83e0becb327f128cb971a3deb8
|
4
|
+
data.tar.gz: 1fdb2e2284043c4c27eb536dbbc0eaef6d180a59c61e6c32c2a74f4aadfb9a85
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1d1c53febbc055e0eeecbff13cb9101c17f0b989b039caa719baf2cf6a69e4fc43f8babbe7e533cf75baeb97dd3d58e7344a1ede890410a4c5046ab7951fd2f3
|
7
|
+
data.tar.gz: 285ed503fcefca8cd3ed0d731f59543c76eca79b0da7c738ae1bef523521697c5ee05fcc0c2d8425d86e8c657d1b579464822f359699ed67ca01077d27eb5972
|
@@ -3,6 +3,8 @@ using System.IO;
|
|
3
3
|
using System.Text;
|
4
4
|
using System.Threading.Tasks;
|
5
5
|
|
6
|
+
using NuGetUpdater.Core;
|
7
|
+
using NuGetUpdater.Core.Test;
|
6
8
|
using NuGetUpdater.Core.Test.Update;
|
7
9
|
|
8
10
|
using Xunit;
|
@@ -291,6 +293,61 @@ public partial class EntryPointTests
|
|
291
293
|
);
|
292
294
|
}
|
293
295
|
|
296
|
+
[Fact]
|
297
|
+
public async Task UpdaterDoesNotUseRepoGlobalJsonForMSBuildTasks()
|
298
|
+
{
|
299
|
+
// This is a _very_ specific scenario where the `NuGetUpdater.Cli` tool might pick up a `global.json` from
|
300
|
+
// the root of the repo under test and use it's `sdk` property when trying to locate MSBuild. To properly
|
301
|
+
// test this, it must be tested in a new process where MSBuild has not been loaded yet and the runner tool
|
302
|
+
// must be started with its working directory at the test repo's root.
|
303
|
+
using var tempDir = new TemporaryDirectory();
|
304
|
+
await File.WriteAllTextAsync(Path.Join(tempDir.DirectoryPath, "global.json"), """
|
305
|
+
{
|
306
|
+
"sdk": {
|
307
|
+
"version": "99.99.99"
|
308
|
+
}
|
309
|
+
}
|
310
|
+
""");
|
311
|
+
await File.WriteAllTextAsync(Path.Join(tempDir.DirectoryPath, "project.csproj"), """
|
312
|
+
<Project Sdk="Microsoft.NET.Sdk">
|
313
|
+
<PropertyGroup>
|
314
|
+
<TargetFramework>net8.0</TargetFramework>
|
315
|
+
</PropertyGroup>
|
316
|
+
<ItemGroup>
|
317
|
+
<PackageReference Include="Newtonsoft.Json" Version="7.0.1" />
|
318
|
+
</ItemGroup>
|
319
|
+
</Project>
|
320
|
+
""");
|
321
|
+
var executableName = $"NuGetUpdater.Cli{(Environment.OSVersion.Platform == PlatformID.Win32NT ? ".exe" : "")}";
|
322
|
+
var executableArgs = string.Join(" ",
|
323
|
+
[
|
324
|
+
"update",
|
325
|
+
"--repo-root",
|
326
|
+
tempDir.DirectoryPath,
|
327
|
+
"--solution-or-project",
|
328
|
+
Path.Join(tempDir.DirectoryPath, "project.csproj"),
|
329
|
+
"--dependency",
|
330
|
+
"Newtonsoft.Json",
|
331
|
+
"--new-version",
|
332
|
+
"13.0.1",
|
333
|
+
"--previous-version",
|
334
|
+
"7.0.1",
|
335
|
+
"--verbose"
|
336
|
+
]);
|
337
|
+
|
338
|
+
// verify base run
|
339
|
+
var (exitCode, output, error) = await ProcessEx.RunAsync(executableName, executableArgs, workingDirectory: tempDir.DirectoryPath);
|
340
|
+
Assert.True(exitCode == 0, $"Error running update on unsupported SDK.\nSTDOUT:\n{output}\nSTDERR:\n{error}");
|
341
|
+
|
342
|
+
// verify project update
|
343
|
+
var updatedProjectContents = await File.ReadAllTextAsync(Path.Join(tempDir.DirectoryPath, "project.csproj"));
|
344
|
+
Assert.Contains("13.0.1", updatedProjectContents);
|
345
|
+
|
346
|
+
// verify `global.json` untouched
|
347
|
+
var updatedGlobalJsonContents = await File.ReadAllTextAsync(Path.Join(tempDir.DirectoryPath, "global.json"));
|
348
|
+
Assert.Contains("99.99.99", updatedGlobalJsonContents);
|
349
|
+
}
|
350
|
+
|
294
351
|
private static async Task Run(Func<string, string[]> getArgs, (string Path, string Content)[] initialFiles, (string, string)[] expectedFiles)
|
295
352
|
{
|
296
353
|
var actualFiles = await RunUpdate(initialFiles, async path =>
|
@@ -231,7 +231,7 @@ internal static class SdkPackageUpdater
|
|
231
231
|
logger.Log($" Adding [{dependencyName}/{newDependencyVersion}] as a top-level package reference.");
|
232
232
|
|
233
233
|
// see https://learn.microsoft.com/nuget/consume-packages/install-use-packages-dotnet-cli
|
234
|
-
var (exitCode, _, _) = await ProcessEx.RunAsync("dotnet", $"add {projectPath} package {dependencyName} --version {newDependencyVersion}");
|
234
|
+
var (exitCode, _, _) = await ProcessEx.RunAsync("dotnet", $"add {projectPath} package {dependencyName} --version {newDependencyVersion}", workingDirectory: Path.GetDirectoryName(projectPath));
|
235
235
|
if (exitCode != 0)
|
236
236
|
{
|
237
237
|
logger.Log($" Transitive dependency [{dependencyName}/{newDependencyVersion}] was not added.");
|
@@ -41,9 +41,29 @@ internal static partial class MSBuildHelper
|
|
41
41
|
// Ensure MSBuild types are registered before calling a method that loads the types
|
42
42
|
if (!IsMSBuildRegistered)
|
43
43
|
{
|
44
|
-
var
|
45
|
-
|
46
|
-
|
44
|
+
var globalJsonPath = "global.json";
|
45
|
+
var tempGlobalJsonPath = globalJsonPath + Guid.NewGuid().ToString();
|
46
|
+
var globalJsonExists = File.Exists(globalJsonPath);
|
47
|
+
try
|
48
|
+
{
|
49
|
+
if (globalJsonExists)
|
50
|
+
{
|
51
|
+
Console.WriteLine("Temporarily removing `global.json` for MSBuild detection.");
|
52
|
+
File.Move(globalJsonPath, tempGlobalJsonPath);
|
53
|
+
}
|
54
|
+
|
55
|
+
var defaultInstance = MSBuildLocator.QueryVisualStudioInstances().First();
|
56
|
+
MSBuildPath = defaultInstance.MSBuildPath;
|
57
|
+
MSBuildLocator.RegisterInstance(defaultInstance);
|
58
|
+
}
|
59
|
+
finally
|
60
|
+
{
|
61
|
+
if (globalJsonExists)
|
62
|
+
{
|
63
|
+
Console.WriteLine("Restoring `global.json` after MSBuild detection.");
|
64
|
+
File.Move(tempGlobalJsonPath, globalJsonPath);
|
65
|
+
}
|
66
|
+
}
|
47
67
|
}
|
48
68
|
}
|
49
69
|
|
@@ -311,7 +331,7 @@ internal static partial class MSBuildHelper
|
|
311
331
|
try
|
312
332
|
{
|
313
333
|
var tempProjectPath = await CreateTempProjectAsync(tempDirectory, repoRoot, projectPath, targetFramework, packages);
|
314
|
-
var (exitCode, stdOut, stdErr) = await ProcessEx.RunAsync("dotnet", $"restore \"{tempProjectPath}\"");
|
334
|
+
var (exitCode, stdOut, stdErr) = await ProcessEx.RunAsync("dotnet", $"restore \"{tempProjectPath}\"", workingDirectory: tempDirectory.FullName);
|
315
335
|
|
316
336
|
// NU1608: Detected package version outside of dependency constraint
|
317
337
|
|
@@ -451,7 +471,7 @@ internal static partial class MSBuildHelper
|
|
451
471
|
{
|
452
472
|
var tempProjectPath = await CreateTempProjectAsync(tempDirectory, repoRoot, projectPath, targetFramework, packages);
|
453
473
|
|
454
|
-
var (exitCode, stdout, stderr) = await ProcessEx.RunAsync("dotnet", $"build \"{tempProjectPath}\" /t:_ReportDependencies");
|
474
|
+
var (exitCode, stdout, stderr) = await ProcessEx.RunAsync("dotnet", $"build \"{tempProjectPath}\" /t:_ReportDependencies", workingDirectory: tempDirectory.FullName);
|
455
475
|
|
456
476
|
if (exitCode == 0)
|
457
477
|
{
|
@@ -548,6 +568,7 @@ internal static partial class MSBuildHelper
|
|
548
568
|
var repoRootPathPrefix = repoRootPath.NormalizePathToUnix() + "/";
|
549
569
|
var buildFilesInRepo = buildFileList
|
550
570
|
.Where(f => f.StartsWith(repoRootPathPrefix, StringComparison.OrdinalIgnoreCase))
|
571
|
+
.Where(File.Exists)
|
551
572
|
.Distinct()
|
552
573
|
.ToArray();
|
553
574
|
var result = buildFilesInRepo
|
@@ -2497,5 +2497,36 @@ public partial class UpdateWorkerTests
|
|
2497
2497
|
"""
|
2498
2498
|
);
|
2499
2499
|
}
|
2500
|
+
|
2501
|
+
[Fact]
|
2502
|
+
public async Task ProcessingProjectWithAspireDoesNotFailEvenThoughWorkloadIsNotInstalled()
|
2503
|
+
{
|
2504
|
+
// enumerating the build files will fail if the Aspire workload is not installed; this test ensures we can
|
2505
|
+
// still process the update
|
2506
|
+
await TestUpdateForProject("Newtonsoft.Json", "7.0.1", "13.0.1",
|
2507
|
+
projectContents: """
|
2508
|
+
<Project Sdk="Microsoft.NET.Sdk">
|
2509
|
+
<PropertyGroup>
|
2510
|
+
<TargetFramework>net8.0</TargetFramework>
|
2511
|
+
<IsAspireHost>true</IsAspireHost>
|
2512
|
+
</PropertyGroup>
|
2513
|
+
<ItemGroup>
|
2514
|
+
<PackageReference Include="Newtonsoft.Json" Version="7.0.1" />
|
2515
|
+
</ItemGroup>
|
2516
|
+
</Project>
|
2517
|
+
""",
|
2518
|
+
expectedProjectContents: """
|
2519
|
+
<Project Sdk="Microsoft.NET.Sdk">
|
2520
|
+
<PropertyGroup>
|
2521
|
+
<TargetFramework>net8.0</TargetFramework>
|
2522
|
+
<IsAspireHost>true</IsAspireHost>
|
2523
|
+
</PropertyGroup>
|
2524
|
+
<ItemGroup>
|
2525
|
+
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
2526
|
+
</ItemGroup>
|
2527
|
+
</Project>
|
2528
|
+
"""
|
2529
|
+
);
|
2530
|
+
}
|
2500
2531
|
}
|
2501
2532
|
}
|
@@ -63,9 +63,18 @@ module Dependabot
|
|
63
63
|
def project_file_dependencies
|
64
64
|
dependency_set = DependencySet.new
|
65
65
|
|
66
|
-
|
67
|
-
|
68
|
-
|
66
|
+
project_files.each do |project_file|
|
67
|
+
tfms = project_file_parser.target_frameworks(project_file: project_file)
|
68
|
+
unless tfms.any?
|
69
|
+
Dependabot.logger.warn "Excluding project file '#{project_file.name}' due to unresolvable target framework"
|
70
|
+
next
|
71
|
+
end
|
72
|
+
|
73
|
+
dependency_set += project_file_parser.dependency_set(project_file: project_file)
|
74
|
+
end
|
75
|
+
|
76
|
+
proj_files.each do |proj_file|
|
77
|
+
dependency_set += project_file_parser.dependency_set(project_file: proj_file)
|
69
78
|
end
|
70
79
|
|
71
80
|
dependency_set
|
@@ -109,14 +118,21 @@ module Dependabot
|
|
109
118
|
)
|
110
119
|
end
|
111
120
|
|
121
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
122
|
+
def proj_files
|
123
|
+
projfile = /\.proj$/
|
124
|
+
|
125
|
+
dependency_files.select do |df|
|
126
|
+
df.name.match?(projfile)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
112
130
|
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
113
131
|
def project_files
|
114
|
-
|
115
|
-
packageprops = /[Dd]irectory.[Pp]ackages.props/
|
132
|
+
projectfile = /\.(cs|vb|fs)proj$/
|
116
133
|
|
117
134
|
dependency_files.select do |df|
|
118
|
-
df.name.match?(
|
119
|
-
df.name.match?(packageprops)
|
135
|
+
df.name.match?(projectfile)
|
120
136
|
end
|
121
137
|
end
|
122
138
|
|
@@ -144,19 +160,24 @@ module Dependabot
|
|
144
160
|
|
145
161
|
sig { returns(T.nilable(Dependabot::DependencyFile)) }
|
146
162
|
def global_json
|
147
|
-
dependency_files.find { |f| f.name.casecmp("global.json")
|
163
|
+
dependency_files.find { |f| f.name.casecmp?("global.json") }
|
148
164
|
end
|
149
165
|
|
150
166
|
sig { returns(T.nilable(Dependabot::DependencyFile)) }
|
151
167
|
def dotnet_tools_json
|
152
|
-
dependency_files.find { |f| f.name.casecmp(".config/dotnet-tools.json")
|
168
|
+
dependency_files.find { |f| f.name.casecmp?(".config/dotnet-tools.json") }
|
153
169
|
end
|
154
170
|
|
155
171
|
sig { override.void }
|
156
172
|
def check_required_files
|
157
|
-
|
173
|
+
if project_files.any? || proj_files.any? || packages_config_files.any? || global_json || dotnet_tools_json
|
174
|
+
return
|
175
|
+
end
|
158
176
|
|
159
|
-
raise
|
177
|
+
raise Dependabot::DependencyFileNotFound.new(
|
178
|
+
"*.(cs|vb|fs)proj, *.proj, packages.config, global.json, dotnet-tools.json",
|
179
|
+
"No project file, *.proj, packages.config, global.json, or dotnet-tools.json!"
|
180
|
+
)
|
160
181
|
end
|
161
182
|
end
|
162
183
|
end
|
@@ -1,22 +1,34 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
+
require "sorbet-runtime"
|
5
|
+
|
4
6
|
require "dependabot/update_checkers/base"
|
5
7
|
|
6
8
|
module Dependabot
|
7
9
|
module Nuget
|
8
10
|
class CompatibilityChecker
|
11
|
+
extend T::Sig
|
12
|
+
|
9
13
|
require_relative "nuspec_fetcher"
|
10
14
|
require_relative "nupkg_fetcher"
|
11
15
|
require_relative "tfm_finder"
|
12
16
|
require_relative "tfm_comparer"
|
13
17
|
|
18
|
+
sig do
|
19
|
+
params(
|
20
|
+
dependency_urls: T::Array[T::Hash[Symbol, String]],
|
21
|
+
dependency: Dependabot::Dependency,
|
22
|
+
tfm_finder: Dependabot::Nuget::TfmFinder
|
23
|
+
).void
|
24
|
+
end
|
14
25
|
def initialize(dependency_urls:, dependency:, tfm_finder:)
|
15
26
|
@dependency_urls = dependency_urls
|
16
27
|
@dependency = dependency
|
17
28
|
@tfm_finder = tfm_finder
|
18
29
|
end
|
19
30
|
|
31
|
+
sig { params(version: String).returns(T::Boolean) }
|
20
32
|
def compatible?(version)
|
21
33
|
nuspec_xml = NuspecFetcher.fetch_nuspec(dependency_urls, dependency.name, version)
|
22
34
|
return false unless nuspec_xml
|
@@ -32,15 +44,23 @@ module Dependabot
|
|
32
44
|
return true if package_tfms.nil?
|
33
45
|
return false if package_tfms.empty?
|
34
46
|
|
35
|
-
return false if project_tfms.nil? || project_tfms
|
47
|
+
return false if project_tfms.nil? || project_tfms&.empty?
|
36
48
|
|
37
|
-
TfmComparer.are_frameworks_compatible?(project_tfms, package_tfms)
|
49
|
+
TfmComparer.are_frameworks_compatible?(T.must(project_tfms), package_tfms)
|
38
50
|
end
|
39
51
|
|
40
52
|
private
|
41
53
|
|
42
|
-
|
54
|
+
sig { returns(T::Array[T::Hash[Symbol, String]]) }
|
55
|
+
attr_reader :dependency_urls
|
43
56
|
|
57
|
+
sig { returns(Dependabot::Dependency) }
|
58
|
+
attr_reader :dependency
|
59
|
+
|
60
|
+
sig { returns(Dependabot::Nuget::TfmFinder) }
|
61
|
+
attr_reader :tfm_finder
|
62
|
+
|
63
|
+
sig { params(nuspec_xml: Nokogiri::XML::Document).returns(T::Boolean) }
|
44
64
|
def pure_development_dependency?(nuspec_xml)
|
45
65
|
contents = nuspec_xml.at_xpath("package/metadata/developmentDependency")&.content&.strip
|
46
66
|
return false unless contents # no `developmentDependency` element
|
@@ -55,16 +75,17 @@ module Dependabot
|
|
55
75
|
dependency_groups_with_target_framework.to_a.empty?
|
56
76
|
end
|
57
77
|
|
78
|
+
sig { params(nuspec_xml: Nokogiri::XML::Document).returns(T::Array[String]) }
|
58
79
|
def parse_package_tfms(nuspec_xml)
|
59
80
|
nuspec_xml.xpath("//dependencies/group").filter_map { |group| group.attribute("targetFramework") }
|
60
81
|
end
|
61
82
|
|
83
|
+
sig { returns(T.nilable(T::Array[String])) }
|
62
84
|
def project_tfms
|
63
|
-
|
64
|
-
|
65
|
-
@project_tfms = tfm_finder.frameworks(dependency)
|
85
|
+
@project_tfms ||= T.let(tfm_finder.frameworks(dependency), T.nilable(T::Array[String]))
|
66
86
|
end
|
67
87
|
|
88
|
+
sig { params(dependency_version: String).returns(T.nilable(T::Array[String])) }
|
68
89
|
def fetch_package_tfms(dependency_version)
|
69
90
|
cache = CacheManager.cache("compatibility_checker_tfms_cache")
|
70
91
|
key = "#{dependency.name}::#{dependency_version}"
|
@@ -1,9 +1,11 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require "nokogiri"
|
5
|
-
require "
|
5
|
+
require "sorbet-runtime"
|
6
6
|
require "stringio"
|
7
|
+
require "zip"
|
8
|
+
|
7
9
|
require "dependabot/update_checkers/base"
|
8
10
|
require "dependabot/nuget/version"
|
9
11
|
|
@@ -11,21 +13,34 @@ module Dependabot
|
|
11
13
|
module Nuget
|
12
14
|
class UpdateChecker < Dependabot::UpdateCheckers::Base
|
13
15
|
class DependencyFinder
|
16
|
+
extend T::Sig
|
17
|
+
|
14
18
|
require_relative "requirements_updater"
|
15
19
|
require_relative "nuspec_fetcher"
|
16
20
|
|
21
|
+
sig { returns(T::Hash[String, T.untyped]) }
|
17
22
|
def self.transitive_dependencies_cache
|
18
23
|
CacheManager.cache("dependency_finder_transitive_dependencies")
|
19
24
|
end
|
20
25
|
|
26
|
+
sig { returns(T::Hash[String, T.untyped]) }
|
21
27
|
def self.updated_peer_dependencies_cache
|
22
28
|
CacheManager.cache("dependency_finder_updated_peer_dependencies")
|
23
29
|
end
|
24
30
|
|
31
|
+
sig { returns(T::Hash[String, T.untyped]) }
|
25
32
|
def self.fetch_dependencies_cache
|
26
33
|
CacheManager.cache("dependency_finder_fetch_dependencies")
|
27
34
|
end
|
28
35
|
|
36
|
+
sig do
|
37
|
+
params(
|
38
|
+
dependency: Dependabot::Dependency,
|
39
|
+
dependency_files: T::Array[Dependabot::DependencyFile],
|
40
|
+
credentials: T::Array[Dependabot::Credential],
|
41
|
+
repo_contents_path: T.nilable(String)
|
42
|
+
).void
|
43
|
+
end
|
29
44
|
def initialize(dependency:, dependency_files:, credentials:, repo_contents_path:)
|
30
45
|
@dependency = dependency
|
31
46
|
@dependency_files = dependency_files
|
@@ -33,6 +48,7 @@ module Dependabot
|
|
33
48
|
@repo_contents_path = repo_contents_path
|
34
49
|
end
|
35
50
|
|
51
|
+
sig { returns(T::Array[Dependabot::Dependency]) }
|
36
52
|
def transitive_dependencies
|
37
53
|
key = "#{dependency.name.downcase}::#{dependency.version}"
|
38
54
|
cache = DependencyFinder.transitive_dependencies_cache
|
@@ -44,7 +60,7 @@ module Dependabot
|
|
44
60
|
|
45
61
|
cache[key] = fetch_transitive_dependencies(
|
46
62
|
@dependency.name,
|
47
|
-
@dependency.version
|
63
|
+
T.must(@dependency.version)
|
48
64
|
).map do |dependency_info|
|
49
65
|
package_name = dependency_info["packageName"]
|
50
66
|
target_version = dependency_info["version"]
|
@@ -65,13 +81,14 @@ module Dependabot
|
|
65
81
|
cache[key]
|
66
82
|
end
|
67
83
|
|
84
|
+
sig { returns(T::Array[Dependabot::Dependency]) }
|
68
85
|
def updated_peer_dependencies
|
69
86
|
key = "#{dependency.name.downcase}::#{dependency.version}"
|
70
87
|
cache = DependencyFinder.updated_peer_dependencies_cache
|
71
88
|
|
72
89
|
cache[key] ||= fetch_transitive_dependencies(
|
73
90
|
@dependency.name,
|
74
|
-
@dependency.version
|
91
|
+
T.must(@dependency.version)
|
75
92
|
).filter_map do |dependency_info|
|
76
93
|
package_name = dependency_info["packageName"]
|
77
94
|
target_version = dependency_info["version"]
|
@@ -104,48 +121,79 @@ module Dependabot
|
|
104
121
|
|
105
122
|
private
|
106
123
|
|
107
|
-
|
124
|
+
sig { returns(Dependabot::Dependency) }
|
125
|
+
attr_reader :dependency
|
126
|
+
|
127
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
128
|
+
attr_reader :dependency_files
|
129
|
+
|
130
|
+
sig { returns(T::Array[Dependabot::Credential]) }
|
131
|
+
attr_reader :credentials
|
108
132
|
|
133
|
+
sig { returns(T.nilable(String)) }
|
134
|
+
attr_reader :repo_contents_path
|
135
|
+
|
136
|
+
sig do
|
137
|
+
params(
|
138
|
+
dep: Dependabot::Dependency,
|
139
|
+
target_version_details: T::Hash[Symbol, T.untyped]
|
140
|
+
)
|
141
|
+
.returns(T::Array[T::Hash[String, T.untyped]])
|
142
|
+
end
|
109
143
|
def updated_requirements(dep, target_version_details)
|
110
|
-
@updated_requirements ||= {}
|
144
|
+
@updated_requirements ||= T.let({}, T.nilable(T::Hash[String, T.untyped]))
|
111
145
|
@updated_requirements[dep.name] ||=
|
112
146
|
RequirementsUpdater.new(
|
113
147
|
requirements: dep.requirements,
|
114
148
|
latest_version: target_version_details.fetch(:version).to_s,
|
115
|
-
source_details: target_version_details
|
116
|
-
&.slice(:nuspec_url, :repo_url, :source_url)
|
149
|
+
source_details: target_version_details.slice(:nuspec_url, :repo_url, :source_url)
|
117
150
|
).updated_requirements
|
118
151
|
end
|
119
152
|
|
153
|
+
sig { returns(T::Array[Dependabot::Dependency]) }
|
120
154
|
def top_level_dependencies
|
121
155
|
@top_level_dependencies ||=
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
156
|
+
T.let(
|
157
|
+
Nuget::FileParser.new(
|
158
|
+
dependency_files: dependency_files,
|
159
|
+
source: nil
|
160
|
+
).parse.select(&:top_level?),
|
161
|
+
T.nilable(T::Array[Dependabot::Dependency])
|
162
|
+
)
|
126
163
|
end
|
127
164
|
|
165
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
128
166
|
def nuget_configs
|
129
167
|
@nuget_configs ||=
|
130
|
-
|
168
|
+
T.let(
|
169
|
+
@dependency_files.select { |f| f.name.match?(/nuget\.config$/i) },
|
170
|
+
T.nilable(T::Array[Dependabot::DependencyFile])
|
171
|
+
)
|
131
172
|
end
|
132
173
|
|
174
|
+
sig { returns(T::Array[T::Hash[Symbol, String]]) }
|
133
175
|
def dependency_urls
|
134
176
|
@dependency_urls ||=
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
177
|
+
T.let(
|
178
|
+
RepositoryFinder.new(
|
179
|
+
dependency: @dependency,
|
180
|
+
credentials: @credentials,
|
181
|
+
config_files: nuget_configs
|
182
|
+
)
|
183
|
+
.dependency_urls
|
184
|
+
.select { |url| url.fetch(:repository_type) == "v3" },
|
185
|
+
T.nilable(T::Array[T::Hash[Symbol, String]])
|
186
|
+
)
|
141
187
|
end
|
142
188
|
|
189
|
+
sig { params(package_id: String, package_version: String).returns(T::Array[T::Hash[String, T.untyped]]) }
|
143
190
|
def fetch_transitive_dependencies(package_id, package_version)
|
144
191
|
all_dependencies = {}
|
145
192
|
fetch_transitive_dependencies_impl(package_id, package_version, all_dependencies)
|
146
193
|
all_dependencies.map { |_, dependency_info| dependency_info }
|
147
194
|
end
|
148
195
|
|
196
|
+
sig { params(package_id: String, package_version: String, all_dependencies: T::Hash[String, T.untyped]).void }
|
149
197
|
def fetch_transitive_dependencies_impl(package_id, package_version, all_dependencies)
|
150
198
|
dependencies = fetch_dependencies(package_id, package_version)
|
151
199
|
return unless dependencies.any?
|
@@ -175,6 +223,7 @@ module Dependabot
|
|
175
223
|
end
|
176
224
|
end
|
177
225
|
|
226
|
+
sig { params(package_id: String, package_version: String).returns(T::Array[T::Hash[String, T.untyped]]) }
|
178
227
|
def fetch_dependencies(package_id, package_version)
|
179
228
|
key = "#{package_id.downcase}::#{package_version}"
|
180
229
|
cache = DependencyFinder.fetch_dependencies_cache
|
@@ -191,6 +240,7 @@ module Dependabot
|
|
191
240
|
cache[key]
|
192
241
|
end
|
193
242
|
|
243
|
+
sig { params(nuspec_xml: Nokogiri::XML::Document).returns(T::Array[T::Hash[String, String]]) }
|
194
244
|
def read_dependencies_from_nuspec(nuspec_xml) # rubocop:disable Metrics/PerceivedComplexity
|
195
245
|
# we want to exclude development dependencies from the lookup
|
196
246
|
allowed_attributes = %w(all compile native runtime)
|
@@ -223,6 +273,7 @@ module Dependabot
|
|
223
273
|
dependency_list
|
224
274
|
end
|
225
275
|
|
276
|
+
sig { params(dep: Dependabot::Dependency).returns(Dependabot::Nuget::UpdateChecker::VersionFinder) }
|
226
277
|
def version_finder(dep)
|
227
278
|
VersionFinder.new(
|
228
279
|
dependency: dep,
|