dependabot-nuget 0.250.0 → 0.252.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. data/helpers/lib/NuGetUpdater/Directory.Common.props +1 -0
  3. data/helpers/lib/NuGetUpdater/Directory.Packages.props +26 -0
  4. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/DiscoverCommand.cs +35 -0
  5. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/NuGetUpdater.Cli.csproj +1 -1
  6. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Program.cs +4 -7
  7. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Discover.cs +251 -0
  8. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/NuGetUpdater.Cli.Test.csproj +3 -3
  9. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Dependency.cs +56 -1
  10. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/DependencyType.cs +1 -1
  11. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DirectoryPackagesPropsDiscovery.cs +69 -0
  12. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DirectoryPackagesPropsDiscoveryResult.cs +11 -0
  13. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DiscoveryWorker.cs +217 -0
  14. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DotNetToolsJsonDiscovery.cs +30 -0
  15. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DotNetToolsJsonDiscoveryResult.cs +10 -0
  16. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/GlobalJsonDiscovery.cs +30 -0
  17. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/GlobalJsonDiscoveryResult.cs +10 -0
  18. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/IDiscoveryResult.cs +14 -0
  19. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/PackagesConfigDiscovery.cs +29 -0
  20. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/PackagesConfigDiscoveryResult.cs +10 -0
  21. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/ProjectDiscoveryResult.cs +13 -0
  22. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/SdkProjectDiscovery.cs +127 -0
  23. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/WorkspaceDiscoveryResult.cs +13 -0
  24. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/EvaluationResult.cs +8 -0
  25. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/EvaluationResultType.cs +9 -0
  26. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/BuildFile.cs +6 -8
  27. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/DotNetToolsJsonBuildFile.cs +4 -7
  28. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/GlobalJsonBuildFile.cs +24 -17
  29. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/JsonBuildFile.cs +2 -2
  30. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/PackagesConfigBuildFile.cs +8 -13
  31. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/ProjectBuildFile.cs +100 -19
  32. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/XmlBuildFile.cs +2 -2
  33. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/NuGetUpdater.Core.csproj +6 -6
  34. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Property.cs +6 -0
  35. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/DotNetToolsJsonUpdater.cs +23 -36
  36. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/GlobalJsonUpdater.cs +5 -10
  37. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/SdkPackageUpdater.cs +16 -21
  38. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdaterWorker.cs +4 -19
  39. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/HashSetExtensions.cs +14 -0
  40. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/ImmutableArrayExtensions.cs +18 -0
  41. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/JsonHelper.cs +0 -1
  42. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +121 -67
  43. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/NuGetHelper.cs +27 -4
  44. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTestBase.cs +117 -0
  45. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.DotNetToolsJson.cs +91 -0
  46. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.GlobalJson.cs +71 -0
  47. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.PackagesConfig.cs +59 -0
  48. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Project.cs +380 -0
  49. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.cs +306 -0
  50. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/ExpectedDiscoveryResults.cs +36 -0
  51. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Files/DotNetToolsJsonBuildFileTests.cs +1 -2
  52. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Files/GlobalJsonBuildFileTests.cs +2 -3
  53. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Files/PackagesConfigBuildFileTests.cs +4 -6
  54. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Files/ProjectBuildFileTests.cs +6 -5
  55. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/NuGetUpdater.Core.Test.csproj +4 -3
  56. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/TemporaryDirectory.cs +38 -6
  57. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTestBase.cs +12 -40
  58. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.Sdk.cs +30 -0
  59. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/AssertEx.cs +272 -0
  60. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/DiffUtil.cs +266 -0
  61. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/MSBuildHelperTests.cs +195 -152
  62. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/SdkPackageUpdaterHelperTests.cs +7 -11
  63. data/lib/dependabot/nuget/discovery/dependency_details.rb +95 -0
  64. data/lib/dependabot/nuget/discovery/dependency_file_discovery.rb +126 -0
  65. data/lib/dependabot/nuget/discovery/directory_packages_props_discovery.rb +43 -0
  66. data/lib/dependabot/nuget/discovery/discovery_json_reader.rb +83 -0
  67. data/lib/dependabot/nuget/discovery/evaluation_details.rb +63 -0
  68. data/lib/dependabot/nuget/discovery/project_discovery.rb +71 -0
  69. data/lib/dependabot/nuget/discovery/property_details.rb +43 -0
  70. data/lib/dependabot/nuget/discovery/workspace_discovery.rb +66 -0
  71. data/lib/dependabot/nuget/file_parser.rb +19 -128
  72. data/lib/dependabot/nuget/file_updater.rb +28 -60
  73. data/lib/dependabot/nuget/native_helpers.rb +55 -0
  74. data/lib/dependabot/nuget/update_checker/compatibility_checker.rb +3 -8
  75. data/lib/dependabot/nuget/update_checker/dependency_finder.rb +1 -0
  76. data/lib/dependabot/nuget/update_checker/property_updater.rb +1 -0
  77. data/lib/dependabot/nuget/update_checker/tfm_finder.rb +17 -152
  78. data/lib/dependabot/nuget/update_checker/version_finder.rb +1 -6
  79. data/lib/dependabot/nuget/update_checker.rb +4 -1
  80. metadata +43 -11
  81. data/lib/dependabot/nuget/file_parser/dotnet_tools_json_parser.rb +0 -71
  82. data/lib/dependabot/nuget/file_parser/global_json_parser.rb +0 -68
  83. data/lib/dependabot/nuget/file_parser/packages_config_parser.rb +0 -92
  84. data/lib/dependabot/nuget/file_parser/project_file_parser.rb +0 -620
  85. data/lib/dependabot/nuget/file_parser/property_value_finder.rb +0 -225
  86. data/lib/dependabot/nuget/file_updater/property_value_updater.rb +0 -81
@@ -1,225 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- require "sorbet-runtime"
5
-
6
- require "dependabot/nuget/file_fetcher/import_paths_finder"
7
- require "dependabot/nuget/file_parser"
8
-
9
- # For docs, see:
10
- # - https://docs.microsoft.com/en-us/visualstudio/msbuild/msbuild-properties
11
- # - https://docs.microsoft.com/en-us/visualstudio/msbuild/customize-your-build
12
- module Dependabot
13
- module Nuget
14
- class FileParser
15
- class PropertyValueFinder
16
- extend T::Sig
17
-
18
- PROPERTY_REGEX = /\$\((?<property>.*?)\)/
19
-
20
- sig { params(dependency_files: T::Array[Dependabot::DependencyFile]).void }
21
- def initialize(dependency_files:)
22
- @dependency_files = dependency_files
23
- end
24
-
25
- sig do
26
- params(property_name: String,
27
- callsite_file: Dependabot::DependencyFile,
28
- stack: T::Array[[String, String]])
29
- .returns(T.nilable(T::Hash[T.untyped, T.untyped]))
30
- end
31
- def property_details(property_name:, callsite_file:, stack: [])
32
- stack += [[property_name, callsite_file.name]]
33
- return if property_name.include?("(")
34
-
35
- node_details = deep_find_prop_node(
36
- property: property_name,
37
- file: callsite_file
38
- )
39
-
40
- node_details ||=
41
- find_property_in_directory_build_targets(
42
- property: property_name,
43
- callsite_file: callsite_file
44
- )
45
-
46
- node_details ||=
47
- find_property_in_directory_build_props(
48
- property: property_name,
49
- callsite_file: callsite_file
50
- )
51
-
52
- node_details ||=
53
- find_property_in_directory_packages_props(
54
- property: property_name,
55
- callsite_file: callsite_file
56
- )
57
-
58
- node_details ||=
59
- find_property_in_packages_props(property: property_name)
60
-
61
- return unless node_details
62
- return node_details unless PROPERTY_REGEX.match?(node_details[:value])
63
-
64
- check_next_level_of_stack(node_details, stack)
65
- end
66
-
67
- sig do
68
- params(node_details: T.untyped,
69
- stack: T::Array[[String, String]])
70
- .returns(T.nilable(T::Hash[T.untyped, T.untyped]))
71
- end
72
- def check_next_level_of_stack(node_details, stack)
73
- property_name = node_details.fetch(:value)
74
- .match(PROPERTY_REGEX)
75
- .named_captures.fetch("property")
76
- callsite_file = dependency_files
77
- .find { |f| f.name == node_details.fetch(:file) }
78
- return unless callsite_file
79
-
80
- raise "Circular reference!" if stack.include?([property_name, callsite_file.name])
81
-
82
- property_details(
83
- property_name: property_name,
84
- callsite_file: callsite_file,
85
- stack: stack
86
- )
87
- end
88
-
89
- private
90
-
91
- sig { returns(T::Array[Dependabot::DependencyFile]) }
92
- attr_reader :dependency_files
93
-
94
- sig do
95
- params(property: String,
96
- file: Dependabot::DependencyFile)
97
- .returns(T.nilable(T::Hash[Symbol, T.untyped]))
98
- end
99
- def deep_find_prop_node(property:, file:)
100
- doc = Nokogiri::XML(file.content)
101
- doc.remove_namespaces!
102
- node = doc.at_xpath(property_xpath(property))
103
-
104
- # If we found a value for the property, return it
105
- return node_details(file: file, node: node, property: property) if node
106
-
107
- # Otherwise, we need to look in an imported file
108
- import_path_finder =
109
- Nuget::FileFetcher::ImportPathsFinder
110
- .new(project_file: file)
111
-
112
- import_paths = [
113
- *import_path_finder.import_paths,
114
- *import_path_finder.project_reference_paths
115
- ]
116
-
117
- file = import_paths
118
- .filter_map { |p| dependency_files.find { |f| f.name == p } }
119
- .find { |f| deep_find_prop_node(property: property, file: f) }
120
-
121
- return unless file
122
-
123
- deep_find_prop_node(property: property, file: file)
124
- end
125
-
126
- sig do
127
- params(property: String, callsite_file: Dependabot::DependencyFile)
128
- .returns(T.nilable(T::Hash[Symbol, T.untyped]))
129
- end
130
- def find_property_in_directory_build_targets(property:, callsite_file:)
131
- find_property_in_up_tree_files(property: property, callsite_file: callsite_file,
132
- expected_file_name: "Directory.Build.targets")
133
- end
134
-
135
- sig do
136
- params(property: String, callsite_file: Dependabot::DependencyFile)
137
- .returns(T.nilable(T::Hash[Symbol, T.untyped]))
138
- end
139
- def find_property_in_directory_build_props(property:, callsite_file:)
140
- find_property_in_up_tree_files(property: property, callsite_file: callsite_file,
141
- expected_file_name: "Directory.Build.props")
142
- end
143
-
144
- sig do
145
- params(property: String, callsite_file: Dependabot::DependencyFile)
146
- .returns(T.nilable(T::Hash[Symbol, T.untyped]))
147
- end
148
- def find_property_in_directory_packages_props(property:, callsite_file:)
149
- find_property_in_up_tree_files(property: property, callsite_file: callsite_file,
150
- expected_file_name: "Directory.Packages.props")
151
- end
152
-
153
- sig { params(property: String).returns(T.nilable(T::Hash[Symbol, T.untyped])) }
154
- def find_property_in_packages_props(property:)
155
- file = packages_props_file
156
- return unless file
157
-
158
- deep_find_prop_node(property: property, file: file)
159
- end
160
-
161
- sig do
162
- params(property: String,
163
- callsite_file: Dependabot::DependencyFile,
164
- expected_file_name: String)
165
- .returns(T.untyped)
166
- end
167
- def find_property_in_up_tree_files(property:, callsite_file:, expected_file_name:)
168
- files = up_tree_files_for_project(callsite_file, expected_file_name)
169
- return if files.empty?
170
-
171
- # first file where we were able to find the node
172
- files.reduce(T.let(nil, T.nilable(String))) do |acc, file|
173
- acc || deep_find_prop_node(property: property, file: file)
174
- end
175
- end
176
-
177
- sig do
178
- params(project_file: DependencyFile, expected_file_name: String).returns(T::Array[Dependabot::DependencyFile])
179
- end
180
- def up_tree_files_for_project(project_file, expected_file_name)
181
- dir = File.dirname(project_file.name)
182
-
183
- # Simulate MSBuild walking up the directory structure looking for a file
184
- possible_paths = dir.split("/").map.with_index do |_, i|
185
- base = dir.split("/").first(i + 1).join("/")
186
- Pathname.new(base + "/#{expected_file_name}").cleanpath.to_path
187
- end.reverse + [expected_file_name]
188
-
189
- paths =
190
- possible_paths.uniq
191
- .select { |p| dependency_files.find { |f| f.name.casecmp(p)&.zero? } }
192
-
193
- dependency_files.select { |f| paths.include?(f.name) }
194
- end
195
-
196
- sig { returns(T.nilable(Dependabot::DependencyFile)) }
197
- def packages_props_file
198
- dependency_files.find { |f| f.name.casecmp("Packages.props")&.zero? }
199
- end
200
-
201
- sig { params(property_name: String).returns(String) }
202
- def property_xpath(property_name)
203
- # only return properties that don't have a `Condition` attribute or the `Condition` attribute is checking for
204
- # an empty string, e.g., Condition="$(SomeProperty) == ''"
205
- %{/Project/PropertyGroup/#{property_name}[not(@Condition) or @Condition="$(#{property_name}) == ''"]}
206
- end
207
-
208
- sig do
209
- params(file: DependencyFile,
210
- node: Nokogiri::XML::Node,
211
- property: String)
212
- .returns(T::Hash[Symbol, T.untyped])
213
- end
214
- def node_details(file:, node:, property:)
215
- {
216
- file: file.name,
217
- node: node,
218
- value: node.content.strip,
219
- root_property_name: property
220
- }
221
- end
222
- end
223
- end
224
- end
225
- end
@@ -1,81 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- require "nokogiri"
5
- require "sorbet-runtime"
6
-
7
- require "dependabot/dependency_file"
8
- require "dependabot/nuget/file_updater"
9
- require "dependabot/nuget/file_parser/property_value_finder"
10
-
11
- module Dependabot
12
- module Nuget
13
- class FileUpdater
14
- class PropertyValueUpdater
15
- extend T::Sig
16
-
17
- sig { params(dependency_files: T::Array[Dependabot::DependencyFile]).void }
18
- def initialize(dependency_files:)
19
- @dependency_files = dependency_files
20
- end
21
-
22
- sig do
23
- params(property_name: String,
24
- updated_value: String,
25
- callsite_file: Dependabot::DependencyFile)
26
- .returns(T::Array[Dependabot::DependencyFile])
27
- end
28
- def update_files_for_property_change(property_name:, updated_value:,
29
- callsite_file:)
30
- declaration_details =
31
- property_value_finder.property_details(
32
- property_name: property_name,
33
- callsite_file: callsite_file
34
- )
35
- throw "Unable to locate property details" unless declaration_details
36
-
37
- declaration_filename = declaration_details.fetch(:file)
38
- declaration_file = dependency_files.find do |f|
39
- declaration_filename == f.name
40
- end
41
- throw "Unable to locate declaration file" unless declaration_file
42
-
43
- content = T.must(declaration_file.content)
44
- node = declaration_details.fetch(:node)
45
-
46
- updated_content = content.sub(
47
- %r{(<#{Regexp.quote(node.name)}(?:\s[^>]*)?>)
48
- \s*#{Regexp.quote(node.content)}\s*
49
- </#{Regexp.quote(node.name)}>}xm,
50
- '\1' + "#{updated_value}</#{node.name}>"
51
- )
52
-
53
- files = dependency_files.dup
54
- file_index = T.must(files.index(declaration_file))
55
- files[file_index] =
56
- update_file(file: declaration_file, content: updated_content)
57
- files
58
- end
59
-
60
- private
61
-
62
- sig { returns(T::Array[DependencyFile]) }
63
- attr_reader :dependency_files
64
-
65
- sig { returns(FileParser::PropertyValueFinder) }
66
- def property_value_finder
67
- @property_value_finder ||=
68
- T.let(FileParser::PropertyValueFinder
69
- .new(dependency_files: dependency_files), T.nilable(FileParser::PropertyValueFinder))
70
- end
71
-
72
- sig { params(file: DependencyFile, content: String).returns(DependencyFile) }
73
- def update_file(file:, content:)
74
- updated_file = file.dup
75
- updated_file.content = content
76
- updated_file
77
- end
78
- end
79
- end
80
- end
81
- end