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.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/helpers/lib/NuGetUpdater/Directory.Packages.props +19 -17
  3. data/helpers/lib/NuGetUpdater/NuGetProjects/NuGet.Packaging/NuGet.Packaging.csproj +0 -1
  4. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Analyze.cs +3 -1
  5. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Discover.cs +23 -3
  6. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/AnalyzeWorker.cs +30 -15
  7. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/CompatabilityChecker.cs +1 -1
  8. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/RequirementArrayConverter.cs +39 -0
  9. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/VersionFinder.cs +1 -1
  10. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Clone/ShellGitCommandHandler.cs +1 -1
  11. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DiscoveryWorker.cs +60 -66
  12. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DotNetToolsJsonDiscovery.cs +2 -2
  13. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/GlobalJsonDiscovery.cs +2 -2
  14. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/PackagesConfigDiscovery.cs +11 -3
  15. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/PackagesConfigDiscoveryResult.cs +1 -0
  16. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/ProjectDiscoveryResult.cs +2 -4
  17. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/SdkProjectDiscovery.cs +54 -11
  18. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/WorkspaceDiscoveryResult.cs +0 -1
  19. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/ExperimentsManager.cs +1 -2
  20. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/JsonBuildFile.cs +1 -1
  21. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/FrameworkChecker/CompatabilityChecker.cs +2 -2
  22. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/RunWorker.cs +43 -54
  23. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/BindingRedirectManager.cs +13 -43
  24. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/DotNetToolsJsonUpdater.cs +4 -4
  25. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/GlobalJsonUpdater.cs +5 -5
  26. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/LockFileUpdater.cs +2 -10
  27. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackageReferenceUpdater.cs +38 -33
  28. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackagesConfigUpdater.cs +12 -11
  29. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdaterWorker.cs +16 -12
  30. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/ConsoleLogger.cs +1 -1
  31. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/DependencyConflictResolver.cs +19 -19
  32. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/ILogger.cs +11 -1
  33. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +18 -17
  34. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/NuGetHelper.cs +1 -17
  35. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/PathHelper.cs +17 -9
  36. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/ProjectHelper.cs +96 -0
  37. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTests.cs +87 -5
  38. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTestBase.cs +2 -5
  39. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.PackagesConfig.cs +16 -0
  40. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Proj.cs +6 -0
  41. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Project.cs +147 -36
  42. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.cs +184 -48
  43. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/ExpectedDiscoveryResults.cs +5 -5
  44. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/SdkProjectDiscoveryTests.cs +32 -10
  45. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/RunWorkerTests.cs +400 -76
  46. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/SerializationTests.cs +2 -2
  47. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/UpdatedDependencyListTests.cs +60 -2
  48. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/TestLogger.cs +1 -1
  49. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/BindingRedirectsTests.cs +1 -1
  50. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTestBase.cs +4 -2
  51. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackageReference.cs +40 -0
  52. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackagesConfig.cs +1 -1
  53. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/AssertEx.cs +1 -1
  54. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/LinuxOnlyAttribute.cs +12 -0
  55. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/MSBuildHelperTests.cs +8 -5
  56. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/PathHelperTests.cs +47 -2
  57. data/lib/dependabot/nuget/analysis/analysis_json_reader.rb +3 -1
  58. data/lib/dependabot/nuget/file_fetcher.rb +12 -393
  59. data/lib/dependabot/nuget/file_parser.rb +23 -60
  60. data/lib/dependabot/nuget/file_updater.rb +21 -16
  61. data/lib/dependabot/nuget/native_discovery/native_dependency_file_discovery.rb +2 -9
  62. data/lib/dependabot/nuget/native_discovery/native_discovery_json_reader.rb +183 -77
  63. data/lib/dependabot/nuget/native_discovery/native_project_discovery.rb +25 -3
  64. data/lib/dependabot/nuget/native_discovery/native_workspace_discovery.rb +1 -8
  65. data/lib/dependabot/nuget/native_update_checker/native_update_checker.rb +17 -4
  66. metadata +8 -9
  67. data/helpers/lib/NuGetUpdater/NuGetProjects/Directory.Packages.props +0 -29
  68. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/RequirementConverter.cs +0 -17
  69. data/lib/dependabot/nuget/file_fetcher/import_paths_finder.rb +0 -73
  70. data/lib/dependabot/nuget/file_fetcher/sln_project_paths_finder.rb +0 -60
@@ -1,9 +1,10 @@
1
- # typed: strict
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/cache_manager"
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 a .proj file, .(cs|vb|fs)proj file, or a packages.config."
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
- fetched_files = [
61
- *project_files,
62
- *directory_build_files,
63
- *imported_property_files,
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
- # Return the fetched files
419
- fetched_files
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
- return [] unless repo_contents_path
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(String) }
63
- def job_file_path
64
- ENV.fetch("DEPENDABOT_JOB_PATH")
65
- end
66
-
67
- sig { returns(T::Array[Dependabot::DependencyFile]) }
68
- def proj_files
69
- projfile = /\.proj$/
70
-
71
- dependency_files.select do |df|
72
- df.name.match?(projfile)
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
- return if project_files.any? || proj_files.any?
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, *.proj",
91
- "No project file or *.proj!"
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
- updated_content = File.read(dependency_file_path(f))
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
- proj_path = dependency_file_path(project_file)
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
- proj_path = dependency_file_path(project_file)
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
- discovery_json_reader = NativeDiscoveryJsonReader.get_discovery_from_dependency_files(dependency_files)
161
- discovery_json_reader.workspace_discovery
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,Metrics/CyclomaticComplexity,Metrics/AbcSize
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
- dependency_file_name = file_name
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