dependabot-nuget 0.238.0 → 0.240.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/dependabot/nuget/cache_manager.rb +2 -0
- data/lib/dependabot/nuget/file_fetcher.rb +63 -59
- data/lib/dependabot/nuget/file_parser/packages_config_parser.rb +0 -6
- data/lib/dependabot/nuget/file_parser/project_file_parser.rb +7 -22
- data/lib/dependabot/nuget/file_parser.rb +1 -1
- data/lib/dependabot/nuget/file_updater.rb +6 -2
- data/lib/dependabot/nuget/native_helpers.rb +7 -4
- data/lib/dependabot/nuget/nuget_client.rb +99 -0
- data/lib/dependabot/nuget/nuget_config_credential_helpers.rb +71 -0
- data/lib/dependabot/nuget/requirement.rb +6 -2
- data/lib/dependabot/nuget/update_checker/compatibility_checker.rb +2 -2
- data/lib/dependabot/nuget/update_checker/dependency_finder.rb +2 -2
- data/lib/dependabot/nuget/update_checker/nupkg_fetcher.rb +65 -88
- data/lib/dependabot/nuget/update_checker/nuspec_fetcher.rb +56 -59
- data/lib/dependabot/nuget/update_checker/property_updater.rb +2 -2
- data/lib/dependabot/nuget/update_checker/repository_finder.rb +43 -8
- data/lib/dependabot/nuget/update_checker/requirements_updater.rb +2 -2
- data/lib/dependabot/nuget/update_checker/tfm_comparer.rb +2 -2
- data/lib/dependabot/nuget/update_checker/tfm_finder.rb +2 -2
- data/lib/dependabot/nuget/update_checker/version_finder.rb +4 -42
- metadata +23 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7d8152c074be84d639b86fe67da074f558ca1509102a5a1e9e97c3411178a747
|
4
|
+
data.tar.gz: 6562552b5b89ddfc8c521aeb7a52cf17e2d918c230439f70281663d5e8e45811
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6d91dec9cd6d5db739507bfc91d6454b6f21426a60a2086bd7b944922d4fa123886dbb1037a94b712471deeb89d175c1b0f10a2b84aeb7f6810f3aeddb92eecb
|
7
|
+
data.tar.gz: 7dbe0cacc3ffaa2d9290e09da5026a94432b8f45b839c6db49905b40636188c0201b61f6650aa1a01fa36fe590672b3e0359b8d4139d1bfe26d98dac344b494a
|
@@ -3,6 +3,7 @@
|
|
3
3
|
|
4
4
|
require "dependabot/file_fetchers"
|
5
5
|
require "dependabot/file_fetchers/base"
|
6
|
+
require "dependabot/nuget/cache_manager"
|
6
7
|
require "set"
|
7
8
|
require "sorbet-runtime"
|
8
9
|
|
@@ -23,19 +24,17 @@ module Dependabot
|
|
23
24
|
return true if filenames.any? { |f| f.match?("^src$") }
|
24
25
|
return true if filenames.any? { |f| f.end_with?(".proj") }
|
25
26
|
|
26
|
-
filenames.any? { |name| name.match?(
|
27
|
+
filenames.any? { |name| name.match?(/\.[a-z]{2}proj$/) }
|
27
28
|
end
|
28
29
|
|
29
30
|
def self.required_files_message
|
30
31
|
"Repo must contain a .proj file, .(cs|vb|fs)proj file, or a packages.config."
|
31
32
|
end
|
32
33
|
|
33
|
-
# rubocop:disable Metrics/AbcSize
|
34
34
|
sig { override.returns(T::Array[DependencyFile]) }
|
35
35
|
def fetch_files
|
36
36
|
fetched_files = []
|
37
37
|
fetched_files += project_files
|
38
|
-
fetched_files += project_files.filter_map { |f| directory_packages_props_file_from_project_file(f) }
|
39
38
|
fetched_files += directory_build_files
|
40
39
|
fetched_files += imported_property_files
|
41
40
|
|
@@ -47,7 +46,7 @@ module Dependabot
|
|
47
46
|
|
48
47
|
# dedup files based on their absolute path
|
49
48
|
fetched_files = fetched_files.uniq do |fetched_file|
|
50
|
-
Pathname.new(
|
49
|
+
Pathname.new(fetched_file.directory).join(fetched_file.name).cleanpath.to_path
|
51
50
|
end
|
52
51
|
|
53
52
|
if project_files.none? && packages_config_files.none?
|
@@ -61,7 +60,6 @@ module Dependabot
|
|
61
60
|
|
62
61
|
fetched_files
|
63
62
|
end
|
64
|
-
# rubocop:enable Metrics/AbcSize
|
65
63
|
|
66
64
|
private
|
67
65
|
|
@@ -72,8 +70,9 @@ module Dependabot
|
|
72
70
|
project_files += csproj_file
|
73
71
|
project_files += vbproj_file
|
74
72
|
project_files += fsproj_file
|
75
|
-
|
76
73
|
project_files += sln_project_files
|
74
|
+
project_files += proj_files
|
75
|
+
project_files += project_files.filter_map { |f| directory_packages_props_file_from_project_file(f) }
|
77
76
|
project_files
|
78
77
|
end
|
79
78
|
rescue Octokit::NotFound, Gitlab::Error::NotFound
|
@@ -120,22 +119,15 @@ module Dependabot
|
|
120
119
|
@directory_build_files ||= fetch_directory_build_files
|
121
120
|
end
|
122
121
|
|
123
|
-
# rubocop:disable Metrics/AbcSize
|
124
122
|
def fetch_directory_build_files
|
125
123
|
attempted_dirs = []
|
126
124
|
directory_build_files = []
|
127
125
|
directory_path = Pathname.new(directory)
|
128
126
|
|
129
127
|
# find all build files (Directory.Build.props/.targets) relative to the given project file
|
130
|
-
project_files.map { |f|
|
128
|
+
project_files.map { |f| Pathname.new(f.directory).join(f.name).dirname }.uniq.each do |dir|
|
131
129
|
# Simulate MSBuild walking up the directory structure looking for a file
|
132
|
-
|
133
|
-
candidate_dir = dir.split("/").first(i + 1).join("/")
|
134
|
-
candidate_dir = "/#{candidate_dir}" unless candidate_dir.start_with?("/")
|
135
|
-
candidate_dir
|
136
|
-
end.reverse
|
137
|
-
|
138
|
-
possible_dirs.each do |possible_dir|
|
130
|
+
dir.descend.each do |possible_dir|
|
139
131
|
break if attempted_dirs.include?(possible_dir)
|
140
132
|
|
141
133
|
attempted_dirs << possible_dir
|
@@ -150,7 +142,6 @@ module Dependabot
|
|
150
142
|
|
151
143
|
directory_build_files
|
152
144
|
end
|
153
|
-
# rubocop:enable Metrics/AbcSize
|
154
145
|
|
155
146
|
def sln_project_files
|
156
147
|
return [] unless sln_files
|
@@ -196,18 +187,21 @@ module Dependabot
|
|
196
187
|
@fsproj_file ||= find_and_fetch_with_suffix(".fsproj")
|
197
188
|
end
|
198
189
|
|
190
|
+
def proj_files
|
191
|
+
@proj_files ||= find_and_fetch_with_suffix(".proj")
|
192
|
+
end
|
193
|
+
|
199
194
|
def directory_packages_props_file_from_project_file(project_file)
|
200
195
|
# walk up the tree from each project file stopping at the first `Directory.Packages.props` file found
|
201
196
|
# https://learn.microsoft.com/en-us/nuget/consume-packages/central-package-management#central-package-management-rules
|
202
197
|
|
203
198
|
found_directory_packages_props_file = nil
|
204
199
|
directory_path = Pathname.new(directory)
|
205
|
-
full_project_dir =
|
206
|
-
full_project_dir.
|
200
|
+
full_project_dir = Pathname.new(project_file.directory).join(project_file.name).dirname
|
201
|
+
full_project_dir.ascend.each do |base|
|
207
202
|
break if found_directory_packages_props_file
|
208
203
|
|
209
|
-
|
210
|
-
candidate_file_path = Pathname.new(base + "/Directory.Packages.props").cleanpath.to_path
|
204
|
+
candidate_file_path = Pathname.new(base).join("Directory.Packages.props").cleanpath.to_path
|
211
205
|
candidate_directory = Pathname.new(File.dirname(candidate_file_path))
|
212
206
|
relative_candidate_directory = candidate_directory.relative_path_from(directory_path)
|
213
207
|
candidate_file = repo_contents(dir: relative_candidate_directory).find do |f|
|
@@ -226,29 +220,32 @@ module Dependabot
|
|
226
220
|
def nuget_config_files
|
227
221
|
return @nuget_config_files if @nuget_config_files
|
228
222
|
|
229
|
-
@nuget_config_files = [
|
230
|
-
|
231
|
-
|
232
|
-
candidate_paths.each do |dir|
|
233
|
-
search_in_directory_and_parents(dir, visited_directories)
|
234
|
-
end
|
223
|
+
@nuget_config_files = [*project_files.map do |f|
|
224
|
+
named_file_up_tree_from_project_file(f, "nuget.config")
|
225
|
+
end].compact.uniq
|
235
226
|
@nuget_config_files
|
236
227
|
end
|
237
228
|
|
238
|
-
def
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
229
|
+
def named_file_up_tree_from_project_file(project_file, expected_file_name)
|
230
|
+
found_expected_file = nil
|
231
|
+
directory_path = Pathname.new(directory)
|
232
|
+
full_project_dir = Pathname.new(project_file.directory).join(project_file.name).dirname
|
233
|
+
full_project_dir.ascend.each do |base|
|
234
|
+
break if found_expected_file
|
235
|
+
|
236
|
+
candidate_file_path = Pathname.new(base).join(expected_file_name).cleanpath.to_path
|
237
|
+
candidate_directory = Pathname.new(File.dirname(candidate_file_path))
|
238
|
+
relative_candidate_directory = candidate_directory.relative_path_from(directory_path)
|
239
|
+
candidate_file = repo_contents(dir: relative_candidate_directory).find do |f|
|
240
|
+
f.name.casecmp?(expected_file_name)
|
241
|
+
end
|
242
|
+
if candidate_file
|
243
|
+
found_expected_file = fetch_file_from_host(File.join(relative_candidate_directory,
|
244
|
+
candidate_file.name))
|
249
245
|
end
|
250
|
-
dir = File.dirname(dir)
|
251
246
|
end
|
247
|
+
|
248
|
+
found_expected_file
|
252
249
|
end
|
253
250
|
|
254
251
|
def global_json
|
@@ -287,27 +284,34 @@ module Dependabot
|
|
287
284
|
end
|
288
285
|
|
289
286
|
def fetch_imported_property_files(file:, previously_fetched_files:)
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
file
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
287
|
+
file_id = file.directory + "/" + file.name
|
288
|
+
@fetched_files ||= {}
|
289
|
+
if @fetched_files[file_id]
|
290
|
+
@fetched_files[file_id]
|
291
|
+
else
|
292
|
+
paths =
|
293
|
+
ImportPathsFinder.new(project_file: file).import_paths +
|
294
|
+
ImportPathsFinder.new(project_file: file).project_reference_paths +
|
295
|
+
ImportPathsFinder.new(project_file: file).project_file_paths
|
296
|
+
|
297
|
+
paths.flat_map do |path|
|
298
|
+
next if previously_fetched_files.map(&:name).include?(path)
|
299
|
+
next if file.name == path
|
300
|
+
next if path.include?("$(")
|
301
|
+
|
302
|
+
fetched_file = fetch_file_from_host(path)
|
303
|
+
grandchild_property_files = fetch_imported_property_files(
|
304
|
+
file: fetched_file,
|
305
|
+
previously_fetched_files: previously_fetched_files + [file]
|
306
|
+
)
|
307
|
+
@fetched_files[file_id] = [fetched_file, *grandchild_property_files]
|
308
|
+
@fetched_files[file_id]
|
309
|
+
rescue Dependabot::DependencyFileNotFound
|
310
|
+
# Don't worry about missing files too much for now (at least
|
311
|
+
# until we start resolving properties)
|
312
|
+
nil
|
313
|
+
end.compact
|
314
|
+
end
|
311
315
|
end
|
312
316
|
end
|
313
317
|
end
|
@@ -26,16 +26,10 @@ module Dependabot
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def dependency_set
|
29
|
-
return parse_dependencies if CacheManager.caching_disabled?
|
30
|
-
|
31
29
|
key = "#{packages_config.name.downcase}::#{packages_config.content.hash}"
|
32
30
|
cache = PackagesConfigParser.dependency_set_cache
|
33
31
|
|
34
32
|
cache[key] ||= parse_dependencies
|
35
|
-
|
36
|
-
dependency_set = Dependabot::FileParsers::Base::DependencySet.new
|
37
|
-
dependency_set += cache[key]
|
38
|
-
dependency_set
|
39
33
|
end
|
40
34
|
|
41
35
|
private
|
@@ -7,13 +7,13 @@ require "dependabot/dependency"
|
|
7
7
|
require "dependabot/nuget/file_parser"
|
8
8
|
require "dependabot/nuget/update_checker"
|
9
9
|
require "dependabot/nuget/cache_manager"
|
10
|
+
require "dependabot/nuget/nuget_client"
|
10
11
|
|
11
12
|
# For details on how dotnet handles version constraints, see:
|
12
13
|
# https://docs.microsoft.com/en-us/nuget/reference/package-versioning
|
13
14
|
module Dependabot
|
14
15
|
module Nuget
|
15
16
|
class FileParser
|
16
|
-
# rubocop:disable Metrics/ClassLength
|
17
17
|
class ProjectFileParser
|
18
18
|
require "dependabot/file_parsers/base/dependency_set"
|
19
19
|
require_relative "property_value_finder"
|
@@ -50,16 +50,10 @@ module Dependabot
|
|
50
50
|
end
|
51
51
|
|
52
52
|
def dependency_set(project_file:)
|
53
|
-
return parse_dependencies(project_file) if CacheManager.caching_disabled?
|
54
|
-
|
55
53
|
key = "#{project_file.name.downcase}::#{project_file.content.hash}"
|
56
54
|
cache = ProjectFileParser.dependency_set_cache
|
57
55
|
|
58
56
|
cache[key] ||= parse_dependencies(project_file)
|
59
|
-
|
60
|
-
dependency_set = Dependabot::FileParsers::Base::DependencySet.new
|
61
|
-
dependency_set += cache[key]
|
62
|
-
dependency_set
|
63
57
|
end
|
64
58
|
|
65
59
|
def target_frameworks(project_file:)
|
@@ -78,6 +72,10 @@ module Dependabot
|
|
78
72
|
["net#{value[1..-1].delete('.')}"]
|
79
73
|
end
|
80
74
|
|
75
|
+
def nuget_configs
|
76
|
+
dependency_files.select { |f| f.name.match?(%r{(^|/)nuget\.config$}i) }
|
77
|
+
end
|
78
|
+
|
81
79
|
private
|
82
80
|
|
83
81
|
attr_reader :dependency_files, :credentials
|
@@ -281,7 +279,6 @@ module Dependabot
|
|
281
279
|
end
|
282
280
|
|
283
281
|
def dependency_has_search_results?(dependency)
|
284
|
-
nuget_configs = dependency_files.select { |f| f.name.casecmp?("nuget.config") }
|
285
282
|
dependency_urls = UpdateChecker::RepositoryFinder.new(
|
286
283
|
dependency: dependency,
|
287
284
|
credentials: credentials,
|
@@ -307,16 +304,9 @@ module Dependabot
|
|
307
304
|
end
|
308
305
|
|
309
306
|
def dependency_url_has_matching_result_v3?(dependency_name, dependency_url)
|
310
|
-
|
311
|
-
auth_header = dependency_url.fetch(:auth_header)
|
312
|
-
response = execute_search_for_dependency_url(url, auth_header)
|
313
|
-
return false unless response.status == 200
|
314
|
-
|
315
|
-
body = JSON.parse(response.body)
|
316
|
-
data = body["data"]
|
317
|
-
return false unless data.length.positive?
|
307
|
+
versions = NugetClient.get_package_versions_v3(dependency_name, dependency_url)
|
318
308
|
|
319
|
-
|
309
|
+
versions != nil
|
320
310
|
end
|
321
311
|
|
322
312
|
def dependency_url_has_matching_result_v2?(dependency_name, dependency_url)
|
@@ -490,10 +480,6 @@ module Dependabot
|
|
490
480
|
end
|
491
481
|
end
|
492
482
|
|
493
|
-
def nuget_configs
|
494
|
-
dependency_files.select { |f| f.name.match?(/nuget\.config$/i) }
|
495
|
-
end
|
496
|
-
|
497
483
|
def global_json
|
498
484
|
dependency_files.find { |f| f.name.casecmp("global.json").zero? }
|
499
485
|
end
|
@@ -502,7 +488,6 @@ module Dependabot
|
|
502
488
|
dependency_files.find { |f| f.name.casecmp(".config/dotnet-tools.json").zero? }
|
503
489
|
end
|
504
490
|
end
|
505
|
-
# rubocop:enable Metrics/ClassLength
|
506
491
|
end
|
507
492
|
end
|
508
493
|
end
|
@@ -62,7 +62,9 @@ module Dependabot
|
|
62
62
|
|
63
63
|
next unless project_dependencies.any? { |dep| dep.name.casecmp(dependency.name).zero? }
|
64
64
|
|
65
|
-
NativeHelpers.run_nuget_updater_tool(repo_contents_path, proj_path
|
65
|
+
NativeHelpers.run_nuget_updater_tool(repo_root: repo_contents_path, proj_path: proj_path,
|
66
|
+
dependency: dependency, is_transitive: !dependency.top_level?,
|
67
|
+
credentials: credentials)
|
66
68
|
update_ran = true
|
67
69
|
end
|
68
70
|
|
@@ -77,7 +79,9 @@ module Dependabot
|
|
77
79
|
project_file = project_files.first
|
78
80
|
proj_path = dependency_file_path(project_file)
|
79
81
|
|
80
|
-
NativeHelpers.run_nuget_updater_tool(repo_contents_path, proj_path
|
82
|
+
NativeHelpers.run_nuget_updater_tool(repo_root: repo_contents_path, proj_path: proj_path,
|
83
|
+
dependency: dependency, is_transitive: !dependency.top_level?,
|
84
|
+
credentials: credentials)
|
81
85
|
return true
|
82
86
|
end
|
83
87
|
|
@@ -1,6 +1,8 @@
|
|
1
1
|
# typed: true
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
+
require_relative "nuget_config_credential_helpers"
|
5
|
+
|
4
6
|
module Dependabot
|
5
7
|
module Nuget
|
6
8
|
module NativeHelpers
|
@@ -46,7 +48,7 @@ module Dependabot
|
|
46
48
|
end
|
47
49
|
|
48
50
|
# rubocop:disable Metrics/MethodLength
|
49
|
-
def self.run_nuget_updater_tool(repo_root
|
51
|
+
def self.run_nuget_updater_tool(repo_root:, proj_path:, dependency:, is_transitive:, credentials:)
|
50
52
|
exe_path = File.join(native_helpers_root, "NuGetUpdater", "NuGetUpdater.Cli")
|
51
53
|
command = [
|
52
54
|
exe_path,
|
@@ -84,9 +86,10 @@ module Dependabot
|
|
84
86
|
|
85
87
|
puts "running NuGet updater:\n" + command
|
86
88
|
|
87
|
-
|
88
|
-
|
89
|
-
|
89
|
+
NuGetConfigCredentialHelpers.patch_nuget_config_for_action(credentials) do
|
90
|
+
output = SharedHelpers.run_shell_command(command, fingerprint: fingerprint)
|
91
|
+
puts output
|
92
|
+
end
|
90
93
|
end
|
91
94
|
# rubocop:enable Metrics/MethodLength
|
92
95
|
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# typed: true
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "dependabot/nuget/cache_manager"
|
5
|
+
require "dependabot/nuget/update_checker/repository_finder"
|
6
|
+
|
7
|
+
module Dependabot
|
8
|
+
module Nuget
|
9
|
+
class NugetClient
|
10
|
+
def self.get_package_versions_v3(dependency_name, repository_details)
|
11
|
+
# Use the registration URL if possible because it is fast and correct
|
12
|
+
if repository_details[:registration_url]
|
13
|
+
get_versions_from_registration_v3(repository_details)
|
14
|
+
# use the search API if not because it is slow but correct
|
15
|
+
elsif repository_details[:search_url]
|
16
|
+
get_versions_from_search_url_v3(repository_details, dependency_name)
|
17
|
+
# Otherwise, use the versions URL (fast but wrong because it includes unlisted versions)
|
18
|
+
elsif repository_details[:versions_url]
|
19
|
+
get_versions_from_versions_url_v3(repository_details)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private_class_method def self.get_versions_from_versions_url_v3(repository_details)
|
24
|
+
body = execute_search_for_dependency_url(repository_details[:versions_url], repository_details)
|
25
|
+
body&.fetch("versions")
|
26
|
+
end
|
27
|
+
|
28
|
+
private_class_method def self.get_versions_from_registration_v3(repository_details)
|
29
|
+
url = repository_details[:registration_url]
|
30
|
+
body = execute_search_for_dependency_url(url, repository_details)
|
31
|
+
|
32
|
+
return unless body
|
33
|
+
|
34
|
+
pages = body.fetch("items")
|
35
|
+
versions = Set.new
|
36
|
+
pages.each do |page|
|
37
|
+
items = page["items"]
|
38
|
+
if items
|
39
|
+
# inlined entries
|
40
|
+
items.each do |item|
|
41
|
+
catalog_entry = item["catalogEntry"]
|
42
|
+
if catalog_entry["listed"] == true
|
43
|
+
vers = catalog_entry["version"]
|
44
|
+
versions << vers
|
45
|
+
end
|
46
|
+
end
|
47
|
+
else
|
48
|
+
# paged entries
|
49
|
+
page_url = page["@id"]
|
50
|
+
page_body = execute_search_for_dependency_url(page_url, repository_details)
|
51
|
+
items = page_body.fetch("items")
|
52
|
+
items.each do |item|
|
53
|
+
catalog_entry = item.fetch("catalogEntry")
|
54
|
+
versions << catalog_entry.fetch("version") if catalog_entry["listed"] == true
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
versions
|
60
|
+
end
|
61
|
+
|
62
|
+
private_class_method def self.get_versions_from_search_url_v3(repository_details, dependency_name)
|
63
|
+
search_url = repository_details[:search_url]
|
64
|
+
body = execute_search_for_dependency_url(search_url, repository_details)
|
65
|
+
|
66
|
+
body&.fetch("data")
|
67
|
+
&.find { |d| d.fetch("id").casecmp(dependency_name.downcase).zero? }
|
68
|
+
&.fetch("versions")
|
69
|
+
&.map { |d| d.fetch("version") }
|
70
|
+
end
|
71
|
+
|
72
|
+
private_class_method def self.execute_search_for_dependency_url(url, repository_details)
|
73
|
+
cache = CacheManager.cache("dependency_url_search_cache")
|
74
|
+
cache[url] ||= Dependabot::RegistryClient.get(
|
75
|
+
url: url,
|
76
|
+
headers: repository_details[:auth_header]
|
77
|
+
)
|
78
|
+
|
79
|
+
response = cache[url]
|
80
|
+
|
81
|
+
return unless response.status == 200
|
82
|
+
|
83
|
+
body = remove_wrapping_zero_width_chars(response.body)
|
84
|
+
JSON.parse(body)
|
85
|
+
rescue Excon::Error::Timeout, Excon::Error::Socket
|
86
|
+
repo_url = repository_details[:repository_url]
|
87
|
+
raise if repo_url == Dependabot::Nuget::UpdateChecker::RepositoryFinder::DEFAULT_REPOSITORY_URL
|
88
|
+
|
89
|
+
raise PrivateSourceTimedOut, repo_url
|
90
|
+
end
|
91
|
+
|
92
|
+
private_class_method def self.remove_wrapping_zero_width_chars(string)
|
93
|
+
string.force_encoding("UTF-8").encode
|
94
|
+
.gsub(/\A[\u200B-\u200D\uFEFF]/, "")
|
95
|
+
.gsub(/[\u200B-\u200D\uFEFF]\Z/, "")
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# typed: true
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Dependabot
|
5
|
+
module Nuget
|
6
|
+
module NuGetConfigCredentialHelpers
|
7
|
+
def self.user_nuget_config_path
|
8
|
+
home_directory = Dir.home
|
9
|
+
File.join(home_directory, ".nuget", "NuGet", "NuGet.Config")
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.temporary_nuget_config_path
|
13
|
+
user_nuget_config_path + "_ORIGINAL"
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.add_credentials_to_nuget_config(credentials)
|
17
|
+
return unless File.exist?(user_nuget_config_path)
|
18
|
+
|
19
|
+
nuget_credentials = credentials.select { |cred| cred["type"] == "nuget_feed" }
|
20
|
+
return if nuget_credentials.empty?
|
21
|
+
|
22
|
+
File.rename(user_nuget_config_path, temporary_nuget_config_path)
|
23
|
+
|
24
|
+
package_sources = []
|
25
|
+
package_source_credentials = []
|
26
|
+
nuget_credentials.each_with_index do |c, i|
|
27
|
+
source_name = "nuget_source_#{i + 1}"
|
28
|
+
package_sources << " <add key=\"#{source_name}\" value=\"#{c['url']}\" />"
|
29
|
+
next unless c["token"]
|
30
|
+
|
31
|
+
package_source_credentials << " <#{source_name}>"
|
32
|
+
package_source_credentials << " <add key=\"Username\" value=\"user\" />"
|
33
|
+
package_source_credentials << " <add key=\"ClearTextPassword\" value=\"#{c['token']}\" />"
|
34
|
+
package_source_credentials << " </#{source_name}>"
|
35
|
+
end
|
36
|
+
|
37
|
+
nuget_config = <<~NUGET_XML
|
38
|
+
<?xml version="1.0" encoding="utf-8"?>
|
39
|
+
<configuration>
|
40
|
+
<packageSources>
|
41
|
+
#{package_sources.join("\n")}
|
42
|
+
</packageSources>
|
43
|
+
<packageSourceCredentials>
|
44
|
+
#{package_source_credentials.join("\n")}
|
45
|
+
</packageSourceCredentials>
|
46
|
+
</configuration>
|
47
|
+
NUGET_XML
|
48
|
+
File.write(user_nuget_config_path, nuget_config)
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.restore_user_nuget_config
|
52
|
+
return unless File.exist?(temporary_nuget_config_path)
|
53
|
+
|
54
|
+
File.delete(user_nuget_config_path)
|
55
|
+
File.rename(temporary_nuget_config_path, user_nuget_config_path)
|
56
|
+
end
|
57
|
+
|
58
|
+
# rubocop:disable Lint/SuppressedException
|
59
|
+
def self.patch_nuget_config_for_action(credentials, &_block)
|
60
|
+
add_credentials_to_nuget_config(credentials)
|
61
|
+
begin
|
62
|
+
yield
|
63
|
+
rescue StandardError
|
64
|
+
ensure
|
65
|
+
restore_user_nuget_config
|
66
|
+
end
|
67
|
+
end
|
68
|
+
# rubocop:enable Lint/SuppressedException
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -1,6 +1,9 @@
|
|
1
1
|
# typed: true
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
+
require "sorbet-runtime"
|
5
|
+
|
6
|
+
require "dependabot/requirement"
|
4
7
|
require "dependabot/utils"
|
5
8
|
require "dependabot/nuget/version"
|
6
9
|
|
@@ -8,7 +11,7 @@ require "dependabot/nuget/version"
|
|
8
11
|
# https://docs.microsoft.com/en-us/nuget/reference/package-versioning
|
9
12
|
module Dependabot
|
10
13
|
module Nuget
|
11
|
-
class Requirement <
|
14
|
+
class Requirement < Dependabot::Requirement
|
12
15
|
def self.parse(obj)
|
13
16
|
return ["=", Nuget::Version.new(obj.to_s)] if obj.is_a?(Gem::Version)
|
14
17
|
|
@@ -19,12 +22,13 @@ module Dependabot
|
|
19
22
|
|
20
23
|
return DefaultRequirement if matches[1] == ">=" && matches[2] == "0"
|
21
24
|
|
22
|
-
[matches[1] || "=", Nuget::Version.new(matches[2])]
|
25
|
+
[matches[1] || "=", Nuget::Version.new(T.must(matches[2]))]
|
23
26
|
end
|
24
27
|
|
25
28
|
# For consistency with other languages, we define a requirements array.
|
26
29
|
# Dotnet doesn't have an `OR` separator for requirements, so it always
|
27
30
|
# contains a single element.
|
31
|
+
sig { override.params(requirement_string: T.nilable(String)).returns(T::Array[Requirement]) }
|
28
32
|
def self.requirements_array(requirement_string)
|
29
33
|
[new(requirement_string)]
|
30
34
|
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
# typed: true
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require "dependabot/
|
4
|
+
require "dependabot/update_checkers/base"
|
5
5
|
|
6
6
|
module Dependabot
|
7
7
|
module Nuget
|
8
|
-
class UpdateChecker
|
8
|
+
class UpdateChecker < Dependabot::UpdateCheckers::Base
|
9
9
|
class CompatibilityChecker
|
10
10
|
require_relative "nuspec_fetcher"
|
11
11
|
require_relative "nupkg_fetcher"
|
@@ -4,12 +4,12 @@
|
|
4
4
|
require "nokogiri"
|
5
5
|
require "zip"
|
6
6
|
require "stringio"
|
7
|
-
require "dependabot/
|
7
|
+
require "dependabot/update_checkers/base"
|
8
8
|
require "dependabot/nuget/version"
|
9
9
|
|
10
10
|
module Dependabot
|
11
11
|
module Nuget
|
12
|
-
class UpdateChecker
|
12
|
+
class UpdateChecker < Dependabot::UpdateCheckers::Base
|
13
13
|
class DependencyFinder
|
14
14
|
require_relative "requirements_updater"
|
15
15
|
require_relative "nuspec_fetcher"
|