dependabot-nuget 0.287.0 → 0.289.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.
Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. data/helpers/lib/NuGetUpdater/.gitignore +1 -0
  3. data/helpers/lib/NuGetUpdater/Directory.Build.targets +17 -0
  4. data/helpers/lib/NuGetUpdater/Directory.Packages.props +26 -17
  5. data/helpers/lib/NuGetUpdater/NuGetProjects/NuGet.Packaging/NuGet.Packaging.csproj +0 -1
  6. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/DiscoverCommand.cs +7 -3
  7. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/RunCommand.cs +1 -1
  8. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Analyze.cs +3 -1
  9. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Discover.cs +88 -47
  10. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/AnalyzeWorker.cs +31 -16
  11. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/CompatabilityChecker.cs +1 -1
  12. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/RequirementArrayConverter.cs +39 -0
  13. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/VersionFinder.cs +1 -1
  14. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Clone/ShellGitCommandHandler.cs +1 -1
  15. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/DependencyDiscovery.props +7 -0
  16. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/DependencyDiscovery.targets +10 -0
  17. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DiscoveryWorker.cs +64 -53
  18. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DotNetToolsJsonDiscovery.cs +2 -2
  19. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/GlobalJsonDiscovery.cs +2 -2
  20. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/PackagesConfigDiscovery.cs +17 -5
  21. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/PackagesConfigDiscoveryResult.cs +3 -1
  22. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/ProjectDiscoveryResult.cs +3 -0
  23. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/SdkProjectDiscovery.cs +429 -12
  24. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/WorkspaceDiscoveryResult.cs +0 -1
  25. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/ExperimentsManager.cs +12 -2
  26. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/JsonBuildFile.cs +1 -1
  27. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/FrameworkChecker/CompatabilityChecker.cs +2 -2
  28. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/NuGetUpdater.Core.csproj +7 -2
  29. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/Job.cs +23 -0
  30. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/RunWorker.cs +43 -58
  31. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/TargetFrameworkReporter.targets +13 -0
  32. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/BindingRedirectManager.cs +13 -43
  33. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/DotNetToolsJsonUpdater.cs +4 -4
  34. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/GlobalJsonUpdater.cs +5 -5
  35. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/LockFileUpdater.cs +3 -10
  36. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackageReferenceUpdater.cs +40 -33
  37. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackagesConfigUpdater.cs +12 -11
  38. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdaterWorker.cs +16 -12
  39. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/CollectionExtensions.cs +17 -0
  40. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/ConsoleLogger.cs +1 -1
  41. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/DependencyConflictResolver.cs +19 -19
  42. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/ILogger.cs +11 -1
  43. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +74 -20
  44. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/NuGetHelper.cs +1 -17
  45. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/PathComparer.cs +31 -0
  46. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/PathHelper.cs +46 -10
  47. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/ProjectHelper.cs +96 -0
  48. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTests.cs +135 -3
  49. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTestBase.cs +71 -38
  50. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.PackagesConfig.cs +66 -4
  51. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Proj.cs +11 -5
  52. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Project.cs +808 -222
  53. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.cs +477 -97
  54. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/ExpectedDiscoveryResults.cs +5 -9
  55. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/SdkProjectDiscoveryTests.cs +494 -0
  56. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/MockNuGetPackage.cs +46 -1
  57. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/NuGetUpdater.Core.Test.csproj +0 -1
  58. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/RunWorkerTests.cs +401 -77
  59. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/SerializationTests.cs +35 -2
  60. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/UpdatedDependencyListTests.cs +60 -2
  61. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/TemporaryDirectory.cs +3 -2
  62. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/TestLogger.cs +1 -1
  63. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/BindingRedirectsTests.cs +1 -1
  64. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTestBase.cs +8 -4
  65. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackageReference.cs +40 -0
  66. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackagesConfig.cs +1 -1
  67. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/AssertEx.cs +1 -1
  68. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/LinuxOnlyAttribute.cs +12 -0
  69. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/MSBuildHelperTests.cs +8 -5
  70. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/PathHelperTests.cs +49 -3
  71. data/lib/dependabot/nuget/analysis/analysis_json_reader.rb +3 -1
  72. data/lib/dependabot/nuget/file_fetcher.rb +12 -393
  73. data/lib/dependabot/nuget/file_parser.rb +23 -54
  74. data/lib/dependabot/nuget/file_updater.rb +21 -16
  75. data/lib/dependabot/nuget/native_discovery/native_dependency_file_discovery.rb +2 -9
  76. data/lib/dependabot/nuget/native_discovery/native_discovery_json_reader.rb +183 -80
  77. data/lib/dependabot/nuget/native_discovery/native_project_discovery.rb +25 -3
  78. data/lib/dependabot/nuget/native_discovery/native_workspace_discovery.rb +1 -11
  79. data/lib/dependabot/nuget/native_helpers.rb +13 -4
  80. data/lib/dependabot/nuget/native_update_checker/native_update_checker.rb +17 -4
  81. metadata +15 -12
  82. data/helpers/lib/NuGetUpdater/NuGetProjects/Directory.Packages.props +0 -29
  83. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/RequirementConverter.cs +0 -17
  84. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DirectoryPackagesPropsDiscovery.cs +0 -69
  85. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DirectoryPackagesPropsDiscoveryResult.cs +0 -11
  86. data/lib/dependabot/nuget/file_fetcher/import_paths_finder.rb +0 -73
  87. data/lib/dependabot/nuget/file_fetcher/sln_project_paths_finder.rb +0 -60
  88. data/lib/dependabot/nuget/native_discovery/native_directory_packages_props_discovery.rb +0 -44
@@ -2,6 +2,8 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "dependabot/dependency"
5
+ require "dependabot/file_parsers/base/dependency_set"
6
+ require "dependabot/nuget/cache_manager"
5
7
  require "dependabot/nuget/native_discovery/native_workspace_discovery"
6
8
  require "json"
7
9
  require "sorbet-runtime"
@@ -12,114 +14,169 @@ module Dependabot
12
14
  extend T::Sig
13
15
 
14
16
  sig { returns(T::Hash[String, NativeDiscoveryJsonReader]) }
15
- def self.discovery_result_cache
16
- T.let(CacheManager.cache("discovery_json_cache"), T::Hash[String, NativeDiscoveryJsonReader])
17
+ def self.cache_directory_to_discovery_json_reader
18
+ CacheManager.cache("cache_directory_to_discovery_json_reader")
17
19
  end
18
20
 
19
- sig { returns(T::Hash[String, String]) }
20
- def self.discovery_path_cache
21
- T.let(CacheManager.cache("discovery_path_cache"), T::Hash[String, String])
21
+ sig { returns(T::Hash[String, NativeDiscoveryJsonReader]) }
22
+ def self.cache_dependency_file_paths_to_discovery_json_reader
23
+ CacheManager.cache("cache_dependency_file_paths_to_discovery_json_reader")
22
24
  end
23
25
 
24
- sig do
25
- params(
26
- dependency_files: T::Array[Dependabot::DependencyFile]
27
- ).returns(NativeDiscoveryJsonReader)
26
+ sig { returns(T::Hash[String, String]) }
27
+ def self.cache_dependency_file_paths_to_discovery_json_path
28
+ CacheManager.cache("cache_dependency_file_paths_to_discovery_json_path")
28
29
  end
29
- def self.get_discovery_from_dependency_files(dependency_files)
30
- key = create_cache_key(dependency_files)
31
- discovery_json = discovery_result_cache[key]
32
- raise "No discovery result for specified dependency files: #{key}" unless discovery_json
33
30
 
34
- discovery_json
31
+ sig { void }
32
+ def self.testonly_clear_caches
33
+ cache_directory_to_discovery_json_reader.clear
34
+ cache_dependency_file_paths_to_discovery_json_reader.clear
35
+ cache_dependency_file_paths_to_discovery_json_path.clear
35
36
  end
36
37
 
37
- sig do
38
- params(
39
- dependency_files: T::Array[Dependabot::DependencyFile],
40
- discovery: NativeDiscoveryJsonReader
41
- ).void
38
+ sig { void }
39
+ def self.testonly_clear_discovery_files
40
+ # this will get recreated when necessary
41
+ FileUtils.rm_rf(discovery_directory)
42
42
  end
43
- def self.set_discovery_from_dependency_files(dependency_files:, discovery:)
44
- key = create_cache_key(dependency_files)
45
- discovery_result_cache[key] = discovery
43
+
44
+ sig { params(error_if_missing: T::Boolean).void }
45
+ def self.debug_report_discovery_files(error_if_missing:)
46
+ if File.exist?(discovery_map_file_path)
47
+ Dependabot.logger.info("Discovery map file (#{discovery_map_file_path}) contents: " \
48
+ "#{File.read(discovery_map_file_path)}")
49
+ Dependabot.logger.info("Discovery files: #{Dir.glob(File.join(discovery_directory, '*'))}")
50
+ elsif error_if_missing
51
+ Dependabot.logger.error("discovery map file missing")
52
+ end
46
53
  end
47
54
 
55
+ # Runs NuGet dependency discovery in the given directory and returns a new instance of NativeDiscoveryJsonReader.
56
+ # The location of the resultant JSON file is saved.
48
57
  sig do
49
58
  params(
50
- dependency_files: T::Array[Dependabot::DependencyFile]
51
- ).returns(String)
59
+ repo_contents_path: String,
60
+ directory: String,
61
+ credentials: T::Array[Dependabot::Credential]
62
+ ).returns(NativeDiscoveryJsonReader)
52
63
  end
53
- def self.get_discovery_file_path_from_dependency_files(dependency_files)
54
- key = create_cache_key(dependency_files)
55
- discovery_path = discovery_path_cache[key]
56
- raise "No discovery path found for specified dependency files: #{key}" unless discovery_path
64
+ def self.run_discovery_in_directory(repo_contents_path:, directory:, credentials:)
65
+ # run discovery
66
+ job_file_path = ENV.fetch("DEPENDABOT_JOB_PATH")
67
+ discovery_json_path = discovery_file_path_from_workspace_path(directory)
68
+ unless File.exist?(discovery_json_path)
69
+ NativeHelpers.run_nuget_discover_tool(job_path: job_file_path,
70
+ repo_root: repo_contents_path,
71
+ workspace_path: directory,
72
+ output_path: discovery_json_path,
73
+ credentials: credentials)
57
74
 
58
- discovery_path
75
+ Dependabot.logger.info("Discovery JSON content: #{File.read(discovery_json_path)}")
76
+ end
77
+ load_discovery_for_directory(repo_contents_path: repo_contents_path, directory: directory)
59
78
  end
60
79
 
61
- sig do
62
- params(
63
- dependency_files: T::Array[Dependabot::DependencyFile]
64
- ).returns(String)
65
- end
66
- def self.create_discovery_file_path_from_dependency_files(dependency_files)
67
- discovery_key = create_cache_key(dependency_files)
68
- if discovery_path_cache[discovery_key]
69
- raise "Discovery file path already exists for the given dependency files: #{discovery_key}"
80
+ # Loads NuGet dependency discovery for the given directory and returns a new instance of
81
+ # NativeDiscoveryJsonReader and caches the resultant object.
82
+ sig { params(repo_contents_path: String, directory: String).returns(NativeDiscoveryJsonReader) }
83
+ def self.load_discovery_for_directory(repo_contents_path:, directory:)
84
+ cache_directory_to_discovery_json_reader[directory] ||= begin
85
+ discovery_json_reader = discovery_json_reader(repo_contents_path: repo_contents_path,
86
+ workspace_path: directory)
87
+ cache_directory_to_discovery_json_reader[directory] = discovery_json_reader
88
+ dependency_file_cache_key = cache_key_from_dependency_file_paths(discovery_json_reader.dependency_file_paths)
89
+ cache_dependency_file_paths_to_discovery_json_reader[dependency_file_cache_key] = discovery_json_reader
90
+ discovery_file_path = discovery_file_path_from_workspace_path(directory)
91
+ cache_dependency_file_paths_to_discovery_json_path[dependency_file_cache_key] = discovery_file_path
92
+
93
+ discovery_json_reader
70
94
  end
95
+ end
71
96
 
72
- discovery_counter_cache = T.let(CacheManager.cache("discovery_counter_cache"), T::Hash[String, Integer])
73
- counter_key = "counter"
74
- current_counter = discovery_counter_cache[counter_key] || 0
75
- current_counter += 1
76
- discovery_counter_cache[counter_key] = current_counter
77
- incremeted_discovery_file_path = File.join(temp_directory, "discovery.#{current_counter}.json")
78
- discovery_path_cache[discovery_key] = incremeted_discovery_file_path
79
- incremeted_discovery_file_path
97
+ # Retrieves the cached NativeDiscoveryJsonReader object for the given dependency file paths.
98
+ sig { params(dependency_file_paths: T::Array[String]).returns(NativeDiscoveryJsonReader) }
99
+ def self.load_discovery_for_dependency_file_paths(dependency_file_paths)
100
+ dependency_file_cache_key = cache_key_from_dependency_file_paths(dependency_file_paths)
101
+ T.must(cache_dependency_file_paths_to_discovery_json_reader[dependency_file_cache_key])
80
102
  end
81
103
 
82
- # this is a test-only method
83
- sig do
84
- params(
85
- dependency_files: T::Array[Dependabot::DependencyFile]
86
- ).void
104
+ # Retrieves the cached location of the discovery JSON file for the given dependency file paths.
105
+ sig { params(dependency_file_paths: T::Array[String]).returns(String) }
106
+ def self.get_discovery_json_path_for_dependency_file_paths(dependency_file_paths)
107
+ dependency_file_cache_key = cache_key_from_dependency_file_paths(dependency_file_paths)
108
+ T.must(cache_dependency_file_paths_to_discovery_json_path[dependency_file_cache_key])
87
109
  end
88
- def self.clear_discovery_file_path_from_cache(dependency_files)
89
- key = create_cache_key(dependency_files)
90
- discovery_file_path = discovery_path_cache[key]
91
- File.delete(discovery_file_path) if discovery_file_path && File.exist?(discovery_file_path)
92
- discovery_path_cache.delete(key)
110
+
111
+ sig { params(repo_contents_path: String, dependency_file: Dependabot::DependencyFile).returns(String) }
112
+ def self.dependency_file_path(repo_contents_path:, dependency_file:)
113
+ dep_file_path = Pathname.new(File.join(dependency_file.directory, dependency_file.name)).cleanpath.to_path
114
+ dep_file_path.delete_prefix("#{repo_contents_path}/")
93
115
  end
94
116
 
95
- sig do
96
- params(
97
- dependency_files: T::Array[Dependabot::DependencyFile]
98
- ).returns(String)
117
+ sig { returns(String) }
118
+ def self.discovery_map_file_path
119
+ File.join(discovery_directory, "discovery_map.json")
99
120
  end
100
- def self.create_cache_key(dependency_files)
101
- dependency_files.map { |d| d.to_h.except("content") }.to_s
121
+
122
+ sig { params(workspace_path: String).returns(String) }
123
+ def self.discovery_file_path_from_workspace_path(workspace_path)
124
+ # Given an update directory (also known as a workspace path), this function returns the path where the discovery
125
+ # JSON file is located. This function is called both by methods that need to write the discovery JSON file and
126
+ # by methods that need to read the discovery JSON file. This function is also called by multiple processes so
127
+ # we need a way to retain the data. This is accomplished by the following steps:
128
+ # 1. Check a well-known file for a mapping of workspace_path => discovery file path. If found, return it.
129
+ # 2. If the path is not found, generate a new path, save it to the well-known file, and return the value.
130
+ discovery_map_contents = File.exist?(discovery_map_file_path) ? File.read(discovery_map_file_path) : "{}"
131
+ discovery_map = T.let(JSON.parse(discovery_map_contents), T::Hash[String, String])
132
+
133
+ discovery_json_path = discovery_map[workspace_path]
134
+ if discovery_json_path
135
+ Dependabot.logger.info("Discovery JSON path for workspace path [#{workspace_path}] found in file " \
136
+ "[#{discovery_map_file_path}] at location [#{discovery_json_path}]")
137
+ return discovery_json_path
138
+ end
139
+
140
+ # no discovery JSON path found; generate a new one, but first find a suitable location
141
+ discovery_json_counter = 1
142
+ new_discovery_json_path = ""
143
+ loop do
144
+ new_discovery_json_path = File.join(discovery_directory, "discovery.#{discovery_json_counter}.json")
145
+ break unless File.exist?(new_discovery_json_path)
146
+
147
+ discovery_json_counter += 1
148
+ end
149
+
150
+ discovery_map[workspace_path] = new_discovery_json_path
151
+
152
+ File.write(discovery_map_file_path, discovery_map.to_json)
153
+ Dependabot.logger.info("Discovery JSON path for workspace path [#{workspace_path}] created for file " \
154
+ "[#{discovery_map_file_path}] at location [#{new_discovery_json_path}]")
155
+ new_discovery_json_path
102
156
  end
103
157
 
104
- sig { returns(String) }
105
- def self.temp_directory
106
- File.join(Dir.tmpdir, ".dependabot")
158
+ sig { params(dependency_file_paths: T::Array[String]).returns(String) }
159
+ def self.cache_key_from_dependency_file_paths(dependency_file_paths)
160
+ dependency_file_paths.sort.join(",")
107
161
  end
108
162
 
109
- sig do
110
- params(
111
- discovery_json_path: String
112
- ).returns(T.nilable(DependencyFile))
163
+ sig { returns(String) }
164
+ def self.discovery_directory
165
+ t = File.join(Dir.home, ".dependabot")
166
+ FileUtils.mkdir_p(t)
167
+ t
113
168
  end
114
- def self.discovery_json_from_path(discovery_json_path)
115
- return unless File.exist?(discovery_json_path)
116
169
 
117
- DependencyFile.new(
118
- name: Pathname.new(discovery_json_path).cleanpath.to_path,
119
- directory: temp_directory,
170
+ sig { params(repo_contents_path: String, workspace_path: String).returns(NativeDiscoveryJsonReader) }
171
+ def self.discovery_json_reader(repo_contents_path:, workspace_path:)
172
+ discovery_file_path = discovery_file_path_from_workspace_path(workspace_path)
173
+ discovery_json = DependencyFile.new(
174
+ name: Pathname.new(discovery_file_path).cleanpath.to_path,
175
+ directory: discovery_directory,
120
176
  type: "file",
121
- content: File.read(discovery_json_path)
177
+ content: File.read(discovery_file_path)
122
178
  )
179
+ NativeDiscoveryJsonReader.new(repo_contents_path: repo_contents_path, discovery_json: discovery_json)
123
180
  end
124
181
 
125
182
  sig { returns(T.nilable(NativeWorkspaceDiscovery)) }
@@ -128,15 +185,23 @@ module Dependabot
128
185
  sig { returns(Dependabot::FileParsers::Base::DependencySet) }
129
186
  attr_reader :dependency_set
130
187
 
131
- sig { params(discovery_json: DependencyFile).void }
132
- def initialize(discovery_json:)
188
+ sig { returns(T::Array[String]) }
189
+ attr_reader :dependency_file_paths
190
+
191
+ sig { params(repo_contents_path: String, discovery_json: DependencyFile).void }
192
+ def initialize(repo_contents_path:, discovery_json:)
193
+ @repo_contents_path = repo_contents_path
133
194
  @discovery_json = discovery_json
134
195
  @workspace_discovery = T.let(read_workspace_discovery, T.nilable(Dependabot::Nuget::NativeWorkspaceDiscovery))
135
196
  @dependency_set = T.let(read_dependency_set, Dependabot::FileParsers::Base::DependencySet)
197
+ @dependency_file_paths = T.let(read_dependency_file_paths, T::Array[String])
136
198
  end
137
199
 
138
200
  private
139
201
 
202
+ sig { returns(String) }
203
+ attr_reader :repo_contents_path
204
+
140
205
  sig { returns(DependencyFile) }
141
206
  attr_reader :discovery_json
142
207
 
@@ -159,9 +224,6 @@ module Dependabot
159
224
  workspace_result.projects.each do |project|
160
225
  dependency_set += project.dependency_set
161
226
  end
162
- if workspace_result.directory_packages_props
163
- dependency_set += T.must(workspace_result.directory_packages_props).dependency_set
164
- end
165
227
  if workspace_result.dotnet_tools_json
166
228
  dependency_set += T.must(workspace_result.dotnet_tools_json).dependency_set
167
229
  end
@@ -169,6 +231,47 @@ module Dependabot
169
231
 
170
232
  dependency_set
171
233
  end
234
+
235
+ sig { returns(T::Array[String]) }
236
+ def read_dependency_file_paths
237
+ dependency_file_paths = T.let([], T::Array[T.nilable(String)])
238
+ dependency_file_paths << dependency_file_path_from_repo_path("global.json") if workspace_discovery&.global_json
239
+ if workspace_discovery&.dotnet_tools_json
240
+ dependency_file_paths << dependency_file_path_from_repo_path(".config/dotnet-tools.json")
241
+ end
242
+
243
+ projects = workspace_discovery&.projects || []
244
+ projects.each do |project|
245
+ dependency_file_paths << dependency_file_path_from_repo_path(project.file_path)
246
+ dependency_file_paths += project.imported_files.map do |f|
247
+ dependency_file_path_from_project_path(project.file_path, f)
248
+ end
249
+ dependency_file_paths += project.additional_files.map do |f|
250
+ dependency_file_path_from_project_path(project.file_path, f)
251
+ end
252
+ end
253
+
254
+ deduped_dependency_file_paths = T.let(Set.new(dependency_file_paths.compact), T::Set[String])
255
+ result = deduped_dependency_file_paths.sort
256
+ result
257
+ end
258
+
259
+ sig { params(path_parts: String).returns(T.nilable(String)) }
260
+ def dependency_file_path_from_repo_path(*path_parts)
261
+ path_parts = path_parts.map { |p| p.delete_prefix("/").delete_suffix("/") }
262
+ normalized_repo_path = Pathname.new(path_parts.join("/")).cleanpath.to_path.delete_prefix("/")
263
+ full_path = Pathname.new(File.join(repo_contents_path, normalized_repo_path)).cleanpath.to_path
264
+ return unless File.exist?(full_path)
265
+
266
+ normalized_repo_path = "/#{normalized_repo_path}" unless normalized_repo_path.start_with?("/")
267
+ normalized_repo_path
268
+ end
269
+
270
+ sig { params(project_path: String, relative_file_path: String).returns(T.nilable(String)) }
271
+ def dependency_file_path_from_project_path(project_path, relative_file_path)
272
+ project_directory = File.dirname(project_path)
273
+ dependency_file_path_from_repo_path(project_directory, relative_file_path)
274
+ end
172
275
  end
173
276
  end
174
277
  end
@@ -10,6 +10,7 @@ module Dependabot
10
10
  class NativeProjectDiscovery < NativeDependencyFileDiscovery
11
11
  extend T::Sig
12
12
 
13
+ # rubocop:disable Metrics/AbcSize
13
14
  sig do
14
15
  override.params(json: T.nilable(T::Hash[String, T.untyped]),
15
16
  directory: String).returns(T.nilable(NativeProjectDiscovery))
@@ -36,26 +37,41 @@ module Dependabot
36
37
 
37
38
  details
38
39
  end
40
+ imported_files = T.let(json.fetch("ImportedFiles"), T::Array[String])
41
+ additional_files = T.let(json.fetch("AdditionalFiles"), T::Array[String])
39
42
 
40
43
  NativeProjectDiscovery.new(file_path: file_path,
41
44
  properties: properties,
42
45
  target_frameworks: target_frameworks,
43
46
  referenced_project_paths: referenced_project_paths,
44
- dependencies: dependencies)
47
+ dependencies: dependencies,
48
+ imported_files: imported_files,
49
+ additional_files: additional_files)
45
50
  end
51
+ # rubocop:enable Metrics/AbcSize
46
52
 
47
53
  sig do
48
54
  params(file_path: String,
49
55
  properties: T::Array[NativePropertyDetails],
50
56
  target_frameworks: T::Array[String],
51
57
  referenced_project_paths: T::Array[String],
52
- dependencies: T::Array[NativeDependencyDetails]).void
58
+ dependencies: T::Array[NativeDependencyDetails],
59
+ imported_files: T::Array[String],
60
+ additional_files: T::Array[String]).void
53
61
  end
54
- def initialize(file_path:, properties:, target_frameworks:, referenced_project_paths:, dependencies:)
62
+ def initialize(file_path:,
63
+ properties:,
64
+ target_frameworks:,
65
+ referenced_project_paths:,
66
+ dependencies:,
67
+ imported_files:,
68
+ additional_files:)
55
69
  super(file_path: file_path, dependencies: dependencies)
56
70
  @properties = properties
57
71
  @target_frameworks = target_frameworks
58
72
  @referenced_project_paths = referenced_project_paths
73
+ @imported_files = imported_files
74
+ @additional_files = additional_files
59
75
  end
60
76
 
61
77
  sig { returns(T::Array[NativePropertyDetails]) }
@@ -67,6 +83,12 @@ module Dependabot
67
83
  sig { returns(T::Array[String]) }
68
84
  attr_reader :referenced_project_paths
69
85
 
86
+ sig { returns(T::Array[String]) }
87
+ attr_reader :imported_files
88
+
89
+ sig { returns(T::Array[String]) }
90
+ attr_reader :additional_files
91
+
70
92
  sig { override.returns(Dependabot::FileParsers::Base::DependencySet) }
71
93
  def dependency_set
72
94
  if target_frameworks.empty? && file_path.end_with?("proj")
@@ -2,7 +2,6 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "dependabot/nuget/native_discovery/native_dependency_file_discovery"
5
- require "dependabot/nuget/native_discovery/native_directory_packages_props_discovery"
6
5
  require "dependabot/nuget/native_discovery/native_project_discovery"
7
6
  require "dependabot/nuget/native_helpers"
8
7
  require "sorbet-runtime"
@@ -21,9 +20,6 @@ module Dependabot
21
20
  projects = T.let(json.fetch("Projects"), T::Array[T::Hash[String, T.untyped]]).filter_map do |project|
22
21
  NativeProjectDiscovery.from_json(project, path)
23
22
  end
24
- directory_packages_props = NativeDirectoryPackagesPropsDiscovery
25
- .from_json(T.let(json.fetch("DirectoryPackagesProps"),
26
- T.nilable(T::Hash[String, T.untyped])), path)
27
23
  global_json = NativeDependencyFileDiscovery
28
24
  .from_json(T.let(json.fetch("GlobalJson"), T.nilable(T::Hash[String, T.untyped])), path)
29
25
  dotnet_tools_json = NativeDependencyFileDiscovery
@@ -32,7 +28,6 @@ module Dependabot
32
28
 
33
29
  NativeWorkspaceDiscovery.new(path: path,
34
30
  projects: projects,
35
- directory_packages_props: directory_packages_props,
36
31
  global_json: global_json,
37
32
  dotnet_tools_json: dotnet_tools_json)
38
33
  end
@@ -40,14 +35,12 @@ module Dependabot
40
35
  sig do
41
36
  params(path: String,
42
37
  projects: T::Array[NativeProjectDiscovery],
43
- directory_packages_props: T.nilable(NativeDirectoryPackagesPropsDiscovery),
44
38
  global_json: T.nilable(NativeDependencyFileDiscovery),
45
39
  dotnet_tools_json: T.nilable(NativeDependencyFileDiscovery)).void
46
40
  end
47
- def initialize(path:, projects:, directory_packages_props:, global_json:, dotnet_tools_json:)
41
+ def initialize(path:, projects:, global_json:, dotnet_tools_json:)
48
42
  @path = path
49
43
  @projects = projects
50
- @directory_packages_props = directory_packages_props
51
44
  @global_json = global_json
52
45
  @dotnet_tools_json = dotnet_tools_json
53
46
  end
@@ -58,9 +51,6 @@ module Dependabot
58
51
  sig { returns(T::Array[NativeProjectDiscovery]) }
59
52
  attr_reader :projects
60
53
 
61
- sig { returns(T.nilable(NativeDirectoryPackagesPropsDiscovery)) }
62
- attr_reader :directory_packages_props
63
-
64
54
  sig { returns(T.nilable(NativeDependencyFileDiscovery)) }
65
55
  attr_reader :global_json
66
56
 
@@ -54,13 +54,20 @@ module Dependabot
54
54
  end
55
55
 
56
56
  sig do
57
- params(repo_root: String, workspace_path: String, output_path: String).returns([String, String])
57
+ params(
58
+ job_path: String,
59
+ repo_root: String,
60
+ workspace_path: String,
61
+ output_path: String
62
+ ).returns([String, String])
58
63
  end
59
- def self.get_nuget_discover_tool_command(repo_root:, workspace_path:, output_path:)
64
+ def self.get_nuget_discover_tool_command(job_path:, repo_root:, workspace_path:, output_path:)
60
65
  exe_path = File.join(native_helpers_root, "NuGetUpdater", "NuGetUpdater.Cli")
61
66
  command_parts = [
62
67
  exe_path,
63
68
  "discover",
69
+ "--job-path",
70
+ job_path,
64
71
  "--repo-root",
65
72
  repo_root,
66
73
  "--workspace",
@@ -87,14 +94,16 @@ module Dependabot
87
94
 
88
95
  sig do
89
96
  params(
97
+ job_path: String,
90
98
  repo_root: String,
91
99
  workspace_path: String,
92
100
  output_path: String,
93
101
  credentials: T::Array[Dependabot::Credential]
94
102
  ).void
95
103
  end
96
- def self.run_nuget_discover_tool(repo_root:, workspace_path:, output_path:, credentials:)
97
- (command, fingerprint) = get_nuget_discover_tool_command(repo_root: repo_root,
104
+ def self.run_nuget_discover_tool(job_path:, repo_root:, workspace_path:, output_path:, credentials:)
105
+ (command, fingerprint) = get_nuget_discover_tool_command(job_path: job_path,
106
+ repo_root: repo_root,
98
107
  workspace_path: workspace_path,
99
108
  output_path: output_path)
100
109
 
@@ -89,12 +89,26 @@ module Dependabot
89
89
 
90
90
  sig { returns(String) }
91
91
  def dependency_file_path
92
- File.join(NativeDiscoveryJsonReader.temp_directory, "dependency", "#{dependency.name}.json")
92
+ d = File.join(Dir.tmpdir, "dependency")
93
+ FileUtils.mkdir_p(d)
94
+ File.join(d, "#{dependency.name}.json")
95
+ end
96
+
97
+ sig { returns(T::Array[String]) }
98
+ def dependency_file_paths
99
+ dependency_files.map do |file|
100
+ NativeDiscoveryJsonReader.dependency_file_path(
101
+ repo_contents_path: T.must(repo_contents_path),
102
+ dependency_file: file
103
+ )
104
+ end
93
105
  end
94
106
 
95
107
  sig { returns(AnalysisJsonReader) }
96
108
  def request_analysis
97
- discovery_file_path = NativeDiscoveryJsonReader.get_discovery_file_path_from_dependency_files(dependency_files)
109
+ discovery_file_path = NativeDiscoveryJsonReader.get_discovery_json_path_for_dependency_file_paths(
110
+ dependency_file_paths
111
+ )
98
112
  analysis_folder_path = AnalysisJsonReader.temp_directory
99
113
 
100
114
  write_dependency_info
@@ -140,8 +154,7 @@ module Dependabot
140
154
 
141
155
  sig { returns(Dependabot::FileParsers::Base::DependencySet) }
142
156
  def discovered_dependencies
143
- discovery_json_reader = NativeDiscoveryJsonReader.get_discovery_from_dependency_files(dependency_files)
144
- discovery_json_reader.dependency_set
157
+ NativeDiscoveryJsonReader.load_discovery_for_dependency_file_paths(dependency_file_paths).dependency_set
145
158
  end
146
159
 
147
160
  sig { override.returns(T::Boolean) }