dependabot-nuget 0.288.0 → 0.289.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/helpers/lib/NuGetUpdater/Directory.Packages.props +19 -17
- data/helpers/lib/NuGetUpdater/NuGetProjects/NuGet.Packaging/NuGet.Packaging.csproj +0 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Analyze.cs +3 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Discover.cs +23 -3
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/AnalyzeWorker.cs +30 -15
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/CompatabilityChecker.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/RequirementArrayConverter.cs +39 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/VersionFinder.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Clone/ShellGitCommandHandler.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DiscoveryWorker.cs +60 -66
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DotNetToolsJsonDiscovery.cs +2 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/GlobalJsonDiscovery.cs +2 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/PackagesConfigDiscovery.cs +11 -3
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/PackagesConfigDiscoveryResult.cs +1 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/ProjectDiscoveryResult.cs +2 -4
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/SdkProjectDiscovery.cs +54 -11
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/WorkspaceDiscoveryResult.cs +0 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/ExperimentsManager.cs +1 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/JsonBuildFile.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/FrameworkChecker/CompatabilityChecker.cs +2 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/RunWorker.cs +43 -54
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/BindingRedirectManager.cs +13 -43
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/DotNetToolsJsonUpdater.cs +4 -4
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/GlobalJsonUpdater.cs +5 -5
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/LockFileUpdater.cs +2 -10
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackageReferenceUpdater.cs +38 -33
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackagesConfigUpdater.cs +12 -11
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdaterWorker.cs +16 -12
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/ConsoleLogger.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/DependencyConflictResolver.cs +19 -19
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/ILogger.cs +11 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +18 -17
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/NuGetHelper.cs +1 -17
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/PathHelper.cs +17 -9
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/ProjectHelper.cs +96 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTests.cs +87 -5
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTestBase.cs +2 -5
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.PackagesConfig.cs +16 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Proj.cs +6 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Project.cs +147 -36
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.cs +184 -48
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/ExpectedDiscoveryResults.cs +5 -5
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/SdkProjectDiscoveryTests.cs +32 -10
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/RunWorkerTests.cs +400 -76
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/SerializationTests.cs +2 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/UpdatedDependencyListTests.cs +60 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/TestLogger.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/BindingRedirectsTests.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTestBase.cs +4 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackageReference.cs +40 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackagesConfig.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/AssertEx.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/LinuxOnlyAttribute.cs +12 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/MSBuildHelperTests.cs +8 -5
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/PathHelperTests.cs +47 -2
- data/lib/dependabot/nuget/analysis/analysis_json_reader.rb +3 -1
- data/lib/dependabot/nuget/file_fetcher.rb +12 -393
- data/lib/dependabot/nuget/file_parser.rb +23 -60
- data/lib/dependabot/nuget/file_updater.rb +21 -16
- data/lib/dependabot/nuget/native_discovery/native_dependency_file_discovery.rb +2 -9
- data/lib/dependabot/nuget/native_discovery/native_discovery_json_reader.rb +183 -77
- data/lib/dependabot/nuget/native_discovery/native_project_discovery.rb +25 -3
- data/lib/dependabot/nuget/native_discovery/native_workspace_discovery.rb +1 -8
- data/lib/dependabot/nuget/native_update_checker/native_update_checker.rb +17 -4
- metadata +8 -9
- data/helpers/lib/NuGetUpdater/NuGetProjects/Directory.Packages.props +0 -29
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/RequirementConverter.cs +0 -17
- data/lib/dependabot/nuget/file_fetcher/import_paths_finder.rb +0 -73
- data/lib/dependabot/nuget/file_fetcher/sln_project_paths_finder.rb +0 -60
@@ -1,9 +1,10 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strong
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require "dependabot/file_fetchers"
|
5
5
|
require "dependabot/file_fetchers/base"
|
6
|
-
require "dependabot/nuget/
|
6
|
+
require "dependabot/nuget/native_discovery/native_discovery_json_reader"
|
7
|
+
require "dependabot/nuget/native_helpers"
|
7
8
|
require "set"
|
8
9
|
require "sorbet-runtime"
|
9
10
|
|
@@ -13,410 +14,28 @@ module Dependabot
|
|
13
14
|
extend T::Sig
|
14
15
|
extend T::Helpers
|
15
16
|
|
16
|
-
require_relative "file_fetcher/import_paths_finder"
|
17
|
-
require_relative "file_fetcher/sln_project_paths_finder"
|
18
|
-
|
19
|
-
BUILD_FILE_NAMES = /^Directory\.Build\.(props|targets)$/i # Directory.Build.props, Directory.Build.targets
|
20
|
-
|
21
17
|
sig { override.params(filenames: T::Array[String]).returns(T::Boolean) }
|
22
18
|
def self.required_files_in?(filenames)
|
23
|
-
return true if filenames.any? { |f| f.match?(/^packages\.config$/i) }
|
24
|
-
return true if filenames.any? { |f| f.end_with?(".sln") }
|
25
|
-
return true if filenames.any? { |f| f.match?("^src$") }
|
26
|
-
return true if filenames.any? { |f| f.end_with?(".proj") }
|
27
|
-
|
28
19
|
filenames.any? { |name| name.match?(/\.(cs|vb|fs)proj$/) }
|
29
20
|
end
|
30
21
|
|
31
22
|
sig { override.returns(String) }
|
32
23
|
def self.required_files_message
|
33
|
-
"Repo must contain
|
34
|
-
end
|
35
|
-
|
36
|
-
sig do
|
37
|
-
override
|
38
|
-
.params(
|
39
|
-
source: Dependabot::Source,
|
40
|
-
credentials: T::Array[Credential],
|
41
|
-
repo_contents_path: T.nilable(String),
|
42
|
-
options: T::Hash[String, String]
|
43
|
-
).void
|
44
|
-
end
|
45
|
-
def initialize(source:, credentials:, repo_contents_path: nil, options: {})
|
46
|
-
super
|
47
|
-
|
48
|
-
@sln_files = T.let(nil, T.nilable(T::Array[Dependabot::DependencyFile]))
|
49
|
-
@sln_project_files = T.let(nil, T.nilable(T::Array[Dependabot::DependencyFile]))
|
50
|
-
@project_files = T.let([], T::Array[Dependabot::DependencyFile])
|
51
|
-
@fetched_files = T.let({}, T::Hash[String, T::Array[Dependabot::DependencyFile]])
|
52
|
-
@nuget_config_files = T.let(nil, T.nilable(T::Array[Dependabot::DependencyFile]))
|
53
|
-
@packages_config_files = T.let(nil, T.nilable(T::Array[Dependabot::DependencyFile]))
|
54
|
-
@assembly_binding_redirect_config_files = T.let(nil, T.nilable(T::Array[Dependabot::DependencyFile]))
|
55
|
-
@packages_lock_files = T.let(nil, T.nilable(T::Array[Dependabot::DependencyFile]))
|
24
|
+
"Repo must contain .(cs|vb|fs)proj file."
|
56
25
|
end
|
57
26
|
|
58
27
|
sig { override.returns(T::Array[DependencyFile]) }
|
59
28
|
def fetch_files
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
*packages_config_files,
|
65
|
-
*assembly_binding_redirect_config_files,
|
66
|
-
*nuget_config_files,
|
67
|
-
*packages_lock_files,
|
68
|
-
global_json,
|
69
|
-
dotnet_tools_json,
|
70
|
-
packages_props
|
71
|
-
].compact
|
72
|
-
|
73
|
-
# dedup files based on their absolute path
|
74
|
-
fetched_files = fetched_files.uniq do |fetched_file|
|
75
|
-
Pathname.new(fetched_file.directory).join(fetched_file.name).cleanpath.to_path
|
76
|
-
end
|
77
|
-
|
78
|
-
if project_files.none? && packages_config_files.none?
|
79
|
-
raise T.must(@missing_sln_project_file_errors.first) if @missing_sln_project_file_errors&.any?
|
80
|
-
|
81
|
-
raise_dependency_file_not_found
|
82
|
-
end
|
83
|
-
|
84
|
-
fetched_files
|
85
|
-
end
|
86
|
-
|
87
|
-
private
|
88
|
-
|
89
|
-
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
90
|
-
def project_files
|
91
|
-
return @project_files if @project_files.any?
|
92
|
-
|
93
|
-
@project_files =
|
94
|
-
begin
|
95
|
-
project_files = []
|
96
|
-
project_files += csproj_file
|
97
|
-
project_files += vbproj_file
|
98
|
-
project_files += fsproj_file
|
99
|
-
project_files += sln_project_files
|
100
|
-
project_files += proj_files
|
101
|
-
project_files += project_files.filter_map do |f|
|
102
|
-
named_file_up_tree_from_project_file(f, "Directory.Packages.props")
|
103
|
-
end
|
104
|
-
project_files
|
105
|
-
end
|
106
|
-
rescue Octokit::NotFound, Gitlab::Error::NotFound
|
107
|
-
raise_dependency_file_not_found
|
108
|
-
end
|
109
|
-
|
110
|
-
sig { returns(T.noreturn) }
|
111
|
-
def raise_dependency_file_not_found
|
112
|
-
raise(
|
113
|
-
Dependabot::DependencyFileNotFound.new(
|
114
|
-
File.join(directory, "*.(sln|csproj|vbproj|fsproj|proj)"),
|
115
|
-
"Unable to find `*.sln`, `*.(cs|vb|fs)proj`, or `*.proj` in directory `#{directory}`"
|
116
|
-
)
|
29
|
+
discovery_json_reader = NativeDiscoveryJsonReader.run_discovery_in_directory(
|
30
|
+
repo_contents_path: T.must(repo_contents_path),
|
31
|
+
directory: directory,
|
32
|
+
credentials: credentials
|
117
33
|
)
|
118
|
-
end
|
119
|
-
|
120
|
-
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
121
|
-
def packages_config_files
|
122
|
-
return @packages_config_files if @packages_config_files
|
123
|
-
|
124
|
-
imported_project_files = imported_property_files.filter { |f| f.name.match?(/\.(cs|vb|fs)proj$/) }
|
125
|
-
|
126
|
-
@packages_config_files = [*project_files, *imported_project_files].filter_map do |f|
|
127
|
-
named_file_next_to_project_file(f, "packages.config")
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
132
|
-
def assembly_binding_redirect_config_files
|
133
|
-
return @assembly_binding_redirect_config_files if @assembly_binding_redirect_config_files
|
134
|
-
|
135
|
-
candidate_paths =
|
136
|
-
[*project_files.map { |f| File.dirname(f.name) }, "."].uniq
|
137
|
-
|
138
|
-
# Assembly binding redirects can appear in any app/web.config file for a .NET Framework project
|
139
|
-
# https://learn.microsoft.com/en-us/dotnet/framework/configure-apps/redirect-assembly-versions#specify-assembly-binding-in-configuration-files
|
140
|
-
@assembly_binding_redirect_config_files =
|
141
|
-
candidate_paths.filter_map do |dir|
|
142
|
-
file = repo_contents(dir: dir)
|
143
|
-
.find { |f| f.name.match?(/^(app|web)\.config$/i) }
|
144
|
-
fetch_file_from_host(File.join(dir, file.name)) if file
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
# rubocop:disable Metrics/PerceivedComplexity
|
149
|
-
sig { returns(T.nilable(T::Array[T.untyped])) }
|
150
|
-
def sln_file_names
|
151
|
-
sln_files = repo_contents.select { |f| f.name.end_with?(".sln") }
|
152
|
-
src_dir = repo_contents.any? { |f| f.name == "src" && f.type == "dir" }
|
153
|
-
|
154
|
-
# If there are no sln files but there is a src directory, check that dir
|
155
|
-
if sln_files.none? && src_dir
|
156
|
-
sln_files = repo_contents(dir: "src")
|
157
|
-
.select { |f| f.name.end_with?(".sln") }.map(&:dup)
|
158
|
-
.map { |file| file.tap { |f| f.name = "src/" + f.name } }
|
159
|
-
end
|
160
|
-
|
161
|
-
# Return `nil` if no sln files were found
|
162
|
-
return if sln_files.none?
|
163
|
-
|
164
|
-
sln_files.map(&:name)
|
165
|
-
end
|
166
|
-
# rubocop:enable Metrics/PerceivedComplexity
|
167
|
-
|
168
|
-
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
169
|
-
def directory_build_files
|
170
|
-
@directory_build_files ||= T.let(fetch_directory_build_files, T.nilable(T::Array[Dependabot::DependencyFile]))
|
171
|
-
end
|
172
|
-
|
173
|
-
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
174
|
-
def fetch_directory_build_files
|
175
|
-
attempted_dirs = T.let([], T::Array[Pathname])
|
176
|
-
directory_build_files = T.let([], T::Array[Dependabot::DependencyFile])
|
177
|
-
directory_path = Pathname.new(directory)
|
178
|
-
|
179
|
-
# find all build files (Directory.Build.props/.targets) relative to the given project file
|
180
|
-
project_files.map { |f| Pathname.new(f.directory).join(f.name).dirname }.uniq.each do |dir|
|
181
|
-
# Simulate MSBuild walking up the directory structure looking for a file
|
182
|
-
dir.descend.each do |possible_dir|
|
183
|
-
break if attempted_dirs.include?(possible_dir)
|
184
|
-
|
185
|
-
attempted_dirs << possible_dir
|
186
|
-
relative_possible_dir = Pathname.new(possible_dir).relative_path_from(directory_path).to_s
|
187
|
-
build_files = repo_contents(dir: relative_possible_dir).select { |f| f.name.match?(BUILD_FILE_NAMES) }
|
188
|
-
directory_build_files += build_files.map do |file|
|
189
|
-
possible_file = File.join(relative_possible_dir, file.name).delete_prefix("/")
|
190
|
-
fetch_file_from_host(possible_file)
|
191
|
-
end
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
directory_build_files
|
196
|
-
end
|
197
|
-
|
198
|
-
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
199
|
-
def sln_project_files
|
200
|
-
return [] unless sln_files
|
201
|
-
|
202
|
-
@sln_project_files ||=
|
203
|
-
begin
|
204
|
-
paths = T.must(sln_files).flat_map do |sln_file|
|
205
|
-
SlnProjectPathsFinder
|
206
|
-
.new(sln_file: sln_file)
|
207
|
-
.project_paths
|
208
|
-
end
|
209
|
-
|
210
|
-
paths.filter_map do |path|
|
211
|
-
fetch_file_from_host(path)
|
212
|
-
rescue Dependabot::DependencyFileNotFound => e
|
213
|
-
@missing_sln_project_file_errors ||= T.let([], T.nilable(T::Array[Dependabot::DependencyFileNotFound]))
|
214
|
-
@missing_sln_project_file_errors << e
|
215
|
-
# Don't worry about missing files too much for now (at least
|
216
|
-
# until we start resolving properties)
|
217
|
-
nil
|
218
|
-
end
|
219
|
-
end
|
220
|
-
end
|
221
|
-
|
222
|
-
sig { returns(T.nilable(T::Array[Dependabot::DependencyFile])) }
|
223
|
-
def sln_files
|
224
|
-
return unless sln_file_names
|
225
|
-
|
226
|
-
@sln_files ||=
|
227
|
-
sln_file_names
|
228
|
-
&.map { |sln_file_name| fetch_file_from_host(sln_file_name) }
|
229
|
-
&.select { |file| file.content&.valid_encoding? }
|
230
|
-
end
|
231
|
-
|
232
|
-
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
233
|
-
def csproj_file
|
234
|
-
@csproj_file ||= T.let(find_and_fetch_with_suffix(".csproj"), T.nilable(T::Array[Dependabot::DependencyFile]))
|
235
|
-
end
|
236
|
-
|
237
|
-
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
238
|
-
def vbproj_file
|
239
|
-
@vbproj_file ||= T.let(find_and_fetch_with_suffix(".vbproj"), T.nilable(T::Array[Dependabot::DependencyFile]))
|
240
|
-
end
|
241
|
-
|
242
|
-
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
243
|
-
def fsproj_file
|
244
|
-
@fsproj_file ||= T.let(find_and_fetch_with_suffix(".fsproj"), T.nilable(T::Array[Dependabot::DependencyFile]))
|
245
|
-
end
|
246
|
-
|
247
|
-
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
248
|
-
def proj_files
|
249
|
-
@proj_files ||= T.let(find_and_fetch_with_suffix(".proj"), T.nilable(T::Array[Dependabot::DependencyFile]))
|
250
|
-
end
|
251
|
-
|
252
|
-
sig { params(suffix: String).returns(T::Array[Dependabot::DependencyFile]) }
|
253
|
-
def find_and_fetch_with_suffix(suffix)
|
254
|
-
repo_contents.select { |f| f.name.end_with?(suffix) }.map { |f| fetch_file_from_host(f.name) }
|
255
|
-
end
|
256
|
-
|
257
|
-
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
258
|
-
def nuget_config_files
|
259
|
-
return @nuget_config_files if @nuget_config_files
|
260
|
-
|
261
|
-
@nuget_config_files = [*project_files.map do |f|
|
262
|
-
named_file_up_tree_from_project_file(f, "nuget.config")
|
263
|
-
end].compact.uniq
|
264
|
-
@nuget_config_files
|
265
|
-
end
|
266
|
-
|
267
|
-
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
268
|
-
def packages_lock_files
|
269
|
-
return @packages_lock_files if @packages_lock_files
|
270
|
-
|
271
|
-
candidate_paths =
|
272
|
-
[*project_files.map { |f| File.dirname(f.name) }, "."].uniq
|
273
|
-
|
274
|
-
@packages_lock_files =
|
275
|
-
candidate_paths.filter_map do |dir|
|
276
|
-
file = repo_contents(dir: dir)
|
277
|
-
.find { |f| f.name.casecmp("packages.lock.json").zero? }
|
278
|
-
fetch_file_from_host(File.join(dir, file.name)) if file
|
279
|
-
end
|
280
|
-
end
|
281
|
-
|
282
|
-
sig do
|
283
|
-
params(
|
284
|
-
project_file: Dependabot::DependencyFile,
|
285
|
-
expected_file_name: String
|
286
|
-
)
|
287
|
-
.returns(T.nilable(Dependabot::DependencyFile))
|
288
|
-
end
|
289
|
-
def named_file_up_tree_from_project_file(project_file, expected_file_name)
|
290
|
-
found_expected_file = T.let(nil, T.nilable(Dependabot::DependencyFile))
|
291
|
-
directory_path = Pathname.new(directory)
|
292
|
-
full_project_dir = Pathname.new(project_file.directory).join(project_file.name).dirname
|
293
|
-
full_project_dir.ascend.each do |base|
|
294
|
-
break if found_expected_file
|
295
|
-
|
296
|
-
candidate_file_path = Pathname.new(base).join(expected_file_name).cleanpath.to_path
|
297
|
-
candidate_directory = Pathname.new(File.dirname(candidate_file_path))
|
298
|
-
relative_candidate_directory = candidate_directory.relative_path_from(directory_path)
|
299
|
-
candidate_file = repo_contents(dir: relative_candidate_directory).find do |f|
|
300
|
-
f.name.casecmp?(expected_file_name)
|
301
|
-
end
|
302
|
-
if candidate_file
|
303
|
-
found_expected_file = fetch_file_from_host(File.join(relative_candidate_directory,
|
304
|
-
candidate_file.name))
|
305
|
-
end
|
306
|
-
end
|
307
|
-
|
308
|
-
found_expected_file
|
309
|
-
end
|
310
|
-
|
311
|
-
sig do
|
312
|
-
params(
|
313
|
-
project_file: Dependabot::DependencyFile,
|
314
|
-
expected_file_name: String
|
315
|
-
)
|
316
|
-
.returns(T.nilable(Dependabot::DependencyFile))
|
317
|
-
end
|
318
|
-
def named_file_next_to_project_file(project_file, expected_file_name)
|
319
|
-
found_expected_file = T.let(nil, T.nilable(Dependabot::DependencyFile))
|
320
|
-
directory_path = Pathname.new(directory)
|
321
|
-
full_project_dir = Pathname.new(project_file.directory).join(project_file.name).dirname
|
322
|
-
|
323
|
-
candidate_file_path = Pathname.new(full_project_dir).join(expected_file_name).cleanpath.to_path
|
324
|
-
candidate_directory = Pathname.new(File.dirname(candidate_file_path))
|
325
|
-
relative_candidate_directory = candidate_directory.relative_path_from(directory_path)
|
326
|
-
candidate_file = repo_contents(dir: relative_candidate_directory).find do |f|
|
327
|
-
f.name.casecmp?(expected_file_name)
|
328
|
-
end
|
329
|
-
if candidate_file
|
330
|
-
found_expected_file = fetch_file_from_host(File.join(relative_candidate_directory,
|
331
|
-
candidate_file.name))
|
332
|
-
end
|
333
|
-
|
334
|
-
found_expected_file
|
335
|
-
end
|
336
|
-
|
337
|
-
sig { returns(T.nilable(Dependabot::DependencyFile)) }
|
338
|
-
def global_json
|
339
|
-
@global_json ||= T.let(fetch_file_if_present("global.json"), T.nilable(Dependabot::DependencyFile))
|
340
|
-
end
|
341
|
-
|
342
|
-
sig { returns(T.nilable(Dependabot::DependencyFile)) }
|
343
|
-
def dotnet_tools_json
|
344
|
-
@dotnet_tools_json ||= T.let(fetch_file_if_present(".config/dotnet-tools.json"),
|
345
|
-
T.nilable(Dependabot::DependencyFile))
|
346
|
-
end
|
347
|
-
|
348
|
-
sig { returns(T.nilable(Dependabot::DependencyFile)) }
|
349
|
-
def packages_props
|
350
|
-
@packages_props ||= T.let(fetch_file_if_present("Packages.props"), T.nilable(Dependabot::DependencyFile))
|
351
|
-
end
|
352
|
-
|
353
|
-
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
354
|
-
def imported_property_files
|
355
|
-
imported_property_files = T.let([], T::Array[Dependabot::DependencyFile])
|
356
|
-
|
357
|
-
files = [*project_files, *directory_build_files]
|
358
|
-
|
359
|
-
files.each do |proj_file|
|
360
|
-
previously_fetched_files = project_files + imported_property_files
|
361
|
-
imported_property_files +=
|
362
|
-
fetch_imported_property_files(
|
363
|
-
file: proj_file,
|
364
|
-
previously_fetched_files: previously_fetched_files
|
365
|
-
)
|
366
|
-
end
|
367
|
-
|
368
|
-
imported_property_files
|
369
|
-
end
|
370
|
-
|
371
|
-
sig do
|
372
|
-
params(
|
373
|
-
file: Dependabot::DependencyFile,
|
374
|
-
previously_fetched_files: T::Array[Dependabot::DependencyFile]
|
375
|
-
)
|
376
|
-
.returns(T::Array[Dependabot::DependencyFile])
|
377
|
-
end
|
378
|
-
def fetch_imported_property_files(file:, previously_fetched_files:)
|
379
|
-
file_id = file.directory + "/" + file.name
|
380
|
-
|
381
|
-
if @fetched_files[file_id]
|
382
|
-
T.must(@fetched_files[file_id])
|
383
|
-
else
|
384
|
-
paths =
|
385
|
-
ImportPathsFinder.new(project_file: file).import_paths +
|
386
|
-
ImportPathsFinder.new(project_file: file).project_reference_paths +
|
387
|
-
ImportPathsFinder.new(project_file: file).project_file_paths
|
388
|
-
|
389
|
-
# Initialize a set to hold fetched files temporarily to avoid duplicates
|
390
|
-
fetched_files_set = Set.new([file])
|
391
|
-
|
392
|
-
paths.each do |path|
|
393
|
-
next if previously_fetched_files.map(&:name).include?(path)
|
394
|
-
next if file.name == path
|
395
|
-
next if path.include?("$(")
|
396
|
-
|
397
|
-
begin
|
398
|
-
fetched_file = fetch_file_from_host(path)
|
399
|
-
grandchild_property_files = fetch_imported_property_files(
|
400
|
-
file: fetched_file,
|
401
|
-
previously_fetched_files: previously_fetched_files + [file]
|
402
|
-
)
|
403
|
-
|
404
|
-
# Add fetched file and grandchild property files to the set
|
405
|
-
fetched_files_set << fetched_file
|
406
|
-
fetched_files_set.merge(grandchild_property_files)
|
407
|
-
rescue Dependabot::DependencyFileNotFound
|
408
|
-
# Don't worry about missing files, just skip them for now
|
409
|
-
Dependabot.logger.info("unable to find expected file #{file.name}")
|
410
|
-
nil
|
411
|
-
end
|
412
|
-
end
|
413
|
-
|
414
|
-
# Convert the set to an array and cache the fetched files
|
415
|
-
fetched_files = fetched_files_set.to_a
|
416
|
-
@fetched_files[file_id] = fetched_files
|
417
34
|
|
418
|
-
|
419
|
-
|
35
|
+
NativeDiscoveryJsonReader.debug_report_discovery_files(error_if_missing: false)
|
36
|
+
discovery_json_reader.dependency_file_paths.map do |p|
|
37
|
+
relative_path = Pathname.new(p).relative_path_from(directory).to_path
|
38
|
+
fetch_file_from_host(relative_path)
|
420
39
|
end
|
421
40
|
end
|
422
41
|
end
|
@@ -16,79 +16,42 @@ module Dependabot
|
|
16
16
|
extend T::Sig
|
17
17
|
|
18
18
|
require "dependabot/file_parsers/base/dependency_set"
|
19
|
-
require_relative "cache_manager"
|
20
|
-
|
21
|
-
sig { returns(T::Hash[String, T::Array[Dependabot::Dependency]]) }
|
22
|
-
def self.file_dependency_cache
|
23
|
-
T.let(CacheManager.cache("file_parser.parse"), T::Hash[String, T::Array[Dependabot::Dependency]])
|
24
|
-
end
|
25
19
|
|
26
20
|
sig { override.returns(T::Array[Dependabot::Dependency]) }
|
27
21
|
def parse
|
28
|
-
|
29
|
-
|
30
|
-
key = NativeDiscoveryJsonReader.create_cache_key(dependency_files)
|
31
|
-
workspace_path = source&.directory || "/"
|
32
|
-
self.class.file_dependency_cache[key] ||= begin
|
33
|
-
# run discovery for the repo
|
34
|
-
discovery_json_path = NativeDiscoveryJsonReader.create_discovery_file_path_from_dependency_files(
|
35
|
-
dependency_files
|
36
|
-
)
|
37
|
-
NativeHelpers.run_nuget_discover_tool(job_path: job_file_path,
|
38
|
-
repo_root: T.must(repo_contents_path),
|
39
|
-
workspace_path: workspace_path,
|
40
|
-
output_path: discovery_json_path,
|
41
|
-
credentials: credentials)
|
42
|
-
|
43
|
-
discovery_json = NativeDiscoveryJsonReader.discovery_json_from_path(discovery_json_path)
|
44
|
-
return [] unless discovery_json
|
45
|
-
|
46
|
-
Dependabot.logger.info("Discovery JSON content: #{discovery_json.content}")
|
47
|
-
discovery_json_reader = NativeDiscoveryJsonReader.new(
|
48
|
-
discovery_json: discovery_json
|
49
|
-
)
|
50
|
-
|
51
|
-
# cache discovery results
|
52
|
-
NativeDiscoveryJsonReader.set_discovery_from_dependency_files(dependency_files: dependency_files,
|
53
|
-
discovery: discovery_json_reader)
|
54
|
-
discovery_json_reader.dependency_set.dependencies
|
55
|
-
end
|
56
|
-
|
57
|
-
T.must(self.class.file_dependency_cache[key])
|
22
|
+
dependencies
|
58
23
|
end
|
59
24
|
|
60
25
|
private
|
61
26
|
|
62
|
-
sig { returns(
|
63
|
-
def
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
77
|
-
def project_files
|
78
|
-
projectfile = /\.(cs|vb|fs)proj$/
|
79
|
-
|
80
|
-
dependency_files.select do |df|
|
81
|
-
df.name.match?(projectfile)
|
82
|
-
end
|
27
|
+
sig { returns(T::Array[Dependabot::Dependency]) }
|
28
|
+
def dependencies
|
29
|
+
@dependencies ||= T.let(begin
|
30
|
+
NativeDiscoveryJsonReader.debug_report_discovery_files(error_if_missing: true)
|
31
|
+
directory = source&.directory || "/"
|
32
|
+
discovery_json_reader = NativeDiscoveryJsonReader.run_discovery_in_directory(
|
33
|
+
repo_contents_path: T.must(repo_contents_path),
|
34
|
+
directory: directory,
|
35
|
+
credentials: credentials
|
36
|
+
)
|
37
|
+
discovery_json_reader.dependency_set.dependencies
|
38
|
+
end, T.nilable(T::Array[Dependabot::Dependency]))
|
83
39
|
end
|
84
40
|
|
85
41
|
sig { override.void }
|
86
42
|
def check_required_files
|
87
|
-
|
43
|
+
requirement_files = dependencies.flat_map do |dep|
|
44
|
+
dep.requirements.map { |r| T.let(r.fetch(:file), String) }
|
45
|
+
end.uniq
|
46
|
+
|
47
|
+
project_files = requirement_files.select { |f| File.basename(f).match?(/\.(cs|vb|fs)proj$/) }
|
48
|
+
global_json_file = requirement_files.select { |f| File.basename(f) == "global.json" }
|
49
|
+
dotnet_tools_json_file = requirement_files.select { |f| File.basename(f) == "dotnet-tools.json" }
|
50
|
+
return if project_files.any? || global_json_file.any? || dotnet_tools_json_file.any?
|
88
51
|
|
89
52
|
raise Dependabot::DependencyFileNotFound.new(
|
90
|
-
"*.(cs|vb|fs)proj
|
91
|
-
"No project file
|
53
|
+
"*.(cs|vb|fs)proj",
|
54
|
+
"No project file."
|
92
55
|
)
|
93
56
|
end
|
94
57
|
end
|
@@ -57,7 +57,12 @@ module Dependabot
|
|
57
57
|
try_update_projects(dependency) || try_update_json(dependency)
|
58
58
|
end
|
59
59
|
updated_files = dependency_files.filter_map do |f|
|
60
|
-
|
60
|
+
dependency_file_path = NativeDiscoveryJsonReader.dependency_file_path(
|
61
|
+
repo_contents_path: T.must(repo_contents_path),
|
62
|
+
dependency_file: f
|
63
|
+
)
|
64
|
+
dependency_file_path = File.join(repo_contents_path, dependency_file_path)
|
65
|
+
updated_content = File.read(dependency_file_path)
|
61
66
|
next if updated_content == f.content
|
62
67
|
|
63
68
|
normalized_content = normalize_content(f, updated_content)
|
@@ -92,7 +97,11 @@ module Dependabot
|
|
92
97
|
# run update for each project file
|
93
98
|
project_files.each do |project_file|
|
94
99
|
project_dependencies = project_dependencies(project_file)
|
95
|
-
|
100
|
+
dependency_file_path = NativeDiscoveryJsonReader.dependency_file_path(
|
101
|
+
repo_contents_path: T.must(repo_contents_path),
|
102
|
+
dependency_file: project_file
|
103
|
+
)
|
104
|
+
proj_path = dependency_file_path
|
96
105
|
|
97
106
|
next unless project_dependencies.any? { |dep| dep.name.casecmp?(dependency.name) }
|
98
107
|
|
@@ -119,7 +128,11 @@ module Dependabot
|
|
119
128
|
|
120
129
|
# We just need to feed the updater a project file, grab the first
|
121
130
|
project_file = T.must(project_files.first)
|
122
|
-
|
131
|
+
dependency_file_path = NativeDiscoveryJsonReader.dependency_file_path(
|
132
|
+
repo_contents_path: T.must(repo_contents_path),
|
133
|
+
dependency_file: project_file
|
134
|
+
)
|
135
|
+
proj_path = dependency_file_path
|
123
136
|
|
124
137
|
return false unless repo_contents_path
|
125
138
|
|
@@ -157,8 +170,11 @@ module Dependabot
|
|
157
170
|
|
158
171
|
sig { returns(T.nilable(NativeWorkspaceDiscovery)) }
|
159
172
|
def workspace
|
160
|
-
|
161
|
-
|
173
|
+
dependency_file_paths = dependency_files.map do |f|
|
174
|
+
NativeDiscoveryJsonReader.dependency_file_path(repo_contents_path: T.must(repo_contents_path),
|
175
|
+
dependency_file: f)
|
176
|
+
end
|
177
|
+
NativeDiscoveryJsonReader.load_discovery_for_dependency_file_paths(dependency_file_paths).workspace_discovery
|
162
178
|
end
|
163
179
|
|
164
180
|
sig { params(project_file: Dependabot::DependencyFile).returns(T::Array[String]) }
|
@@ -215,17 +231,6 @@ module Dependabot
|
|
215
231
|
end
|
216
232
|
# rubocop:enable Metrics/PerceivedComplexity
|
217
233
|
|
218
|
-
sig { params(dependency_file: Dependabot::DependencyFile).returns(String) }
|
219
|
-
def dependency_file_path(dependency_file)
|
220
|
-
if dependency_file.directory.start_with?(T.must(repo_contents_path))
|
221
|
-
File.join(dependency_file.directory, dependency_file.name)
|
222
|
-
else
|
223
|
-
file_directory = dependency_file.directory
|
224
|
-
file_directory = file_directory[1..-1] if file_directory.start_with?("/")
|
225
|
-
File.join(repo_contents_path || "", file_directory, dependency_file.name)
|
226
|
-
end
|
227
|
-
end
|
228
|
-
|
229
234
|
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
230
235
|
def project_files
|
231
236
|
dependency_files.select { |df| df.name.match?(/\.(cs|vb|fs)proj$/) }
|
@@ -41,7 +41,7 @@ module Dependabot
|
|
41
41
|
attr_reader :dependencies
|
42
42
|
|
43
43
|
sig { overridable.returns(Dependabot::FileParsers::Base::DependencySet) }
|
44
|
-
def dependency_set # rubocop:disable Metrics/PerceivedComplexity
|
44
|
+
def dependency_set # rubocop:disable Metrics/PerceivedComplexity
|
45
45
|
dependency_set = Dependabot::FileParsers::Base::DependencySet.new
|
46
46
|
|
47
47
|
file_name = Pathname.new(file_path).cleanpath.to_path
|
@@ -65,14 +65,7 @@ module Dependabot
|
|
65
65
|
# Exclude any dependencies which reference an item type
|
66
66
|
next if dependency.name.include?("@(")
|
67
67
|
|
68
|
-
|
69
|
-
if dependency.type == "PackagesConfig"
|
70
|
-
dir_name = File.dirname(file_name)
|
71
|
-
dependency_file_name = "packages.config"
|
72
|
-
dependency_file_name = File.join(dir_name, "packages.config") unless dir_name == "."
|
73
|
-
end
|
74
|
-
|
75
|
-
dependency_set << build_dependency(dependency_file_name, dependency)
|
68
|
+
dependency_set << build_dependency(file_name, dependency)
|
76
69
|
end
|
77
70
|
|
78
71
|
dependency_set
|