dependabot-nuget 0.289.0 → 0.291.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/helpers/lib/NuGetUpdater/Directory.Packages.props +1 -1
  3. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/AnalyzeCommand.cs +7 -3
  4. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/RunCommand.cs +1 -1
  5. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Analyze.cs +26 -1
  6. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Discover.cs +2 -1
  7. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Run.cs +0 -6
  8. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Update.cs +1 -1
  9. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/AnalyzeWorker.cs +6 -1
  10. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/CompatabilityChecker.cs +24 -9
  11. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/DependencyFinder.cs +2 -0
  12. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/NuGetContext.cs +0 -13
  13. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/RequirementConverter.cs +17 -0
  14. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DiscoveryWorker.cs +44 -5
  15. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/PackagesConfigDiscovery.cs +2 -2
  16. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/ProjectDiscoveryResult.cs +2 -0
  17. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/SdkProjectDiscovery.cs +19 -11
  18. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/ErrorType.cs +1 -0
  19. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/ExperimentsManager.cs +3 -0
  20. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/Advisory.cs +13 -0
  21. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/AllowedUpdate.cs +18 -1
  22. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/CommitOptions.cs +8 -0
  23. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/Condition.cs +19 -0
  24. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/DependencyGroup.cs +8 -0
  25. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/GroupPullRequest.cs +9 -0
  26. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/Job.cs +13 -10
  27. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/PullRequest.cs +11 -0
  28. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/RequirementsUpdateStrategy.cs +15 -0
  29. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/RunWorker.cs +24 -4
  30. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/VersionConverter.cs +19 -0
  31. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/BindingRedirectManager.cs +2 -1
  32. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/LockFileUpdater.cs +3 -2
  33. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackageReferenceUpdater.cs +43 -18
  34. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackagesConfigUpdater.cs +13 -12
  35. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdaterWorker.cs +1 -1
  36. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/JsonHelper.cs +2 -0
  37. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +40 -14
  38. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/NuGetHelper.cs +2 -2
  39. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/ProcessExtensions.cs +45 -7
  40. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/ProjectHelper.cs +2 -2
  41. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTestBase.cs +5 -2
  42. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.DotNetToolsJson.cs +45 -1
  43. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.GlobalJson.cs +35 -1
  44. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Project.cs +0 -4
  45. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.cs +41 -0
  46. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/ExpectedDiscoveryResults.cs +1 -0
  47. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/SdkProjectDiscoveryTests.cs +1 -1
  48. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/MockNuGetPackage.cs +2 -1
  49. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/MiscellaneousTests.cs +85 -0
  50. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/RunWorkerTests.cs +7 -31
  51. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/SerializationTests.cs +340 -0
  52. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/TemporaryDirectory.cs +18 -7
  53. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/PackagesConfigUpdaterTests.cs +24 -0
  54. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTestBase.cs +0 -12
  55. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.DotNetTools.cs +84 -0
  56. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.GlobalJson.cs +66 -0
  57. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackageReference.cs +55 -0
  58. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackagesConfig.cs +0 -6
  59. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/MSBuildHelperTests.cs +785 -755
  60. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/PathHelperTests.cs +2 -2
  61. data/lib/dependabot/nuget/analysis/analysis_json_reader.rb +1 -1
  62. data/lib/dependabot/nuget/analysis/dependency_analysis.rb +3 -3
  63. data/lib/dependabot/nuget/discovery/dependency_details.rb +10 -3
  64. data/lib/dependabot/nuget/discovery/dependency_file_discovery.rb +8 -12
  65. data/lib/dependabot/nuget/discovery/discovery_json_reader.rb +214 -29
  66. data/lib/dependabot/nuget/discovery/project_discovery.rb +41 -8
  67. data/lib/dependabot/nuget/discovery/workspace_discovery.rb +14 -19
  68. data/lib/dependabot/nuget/file_fetcher.rb +3 -3
  69. data/lib/dependabot/nuget/file_parser.rb +92 -3
  70. data/lib/dependabot/nuget/file_updater.rb +13 -13
  71. data/lib/dependabot/nuget/language.rb +82 -0
  72. data/lib/dependabot/nuget/native_helpers.rb +37 -5
  73. data/lib/dependabot/nuget/package_manager.rb +51 -0
  74. data/lib/dependabot/nuget/update_checker/requirements_updater.rb +23 -27
  75. data/lib/dependabot/nuget/update_checker.rb +116 -190
  76. metadata +20 -29
  77. data/lib/dependabot/nuget/discovery/directory_packages_props_discovery.rb +0 -43
  78. data/lib/dependabot/nuget/http_response_helpers.rb +0 -19
  79. data/lib/dependabot/nuget/native_discovery/native_dependency_details.rb +0 -102
  80. data/lib/dependabot/nuget/native_discovery/native_dependency_file_discovery.rb +0 -122
  81. data/lib/dependabot/nuget/native_discovery/native_discovery_json_reader.rb +0 -277
  82. data/lib/dependabot/nuget/native_discovery/native_evaluation_details.rb +0 -63
  83. data/lib/dependabot/nuget/native_discovery/native_project_discovery.rb +0 -104
  84. data/lib/dependabot/nuget/native_discovery/native_property_details.rb +0 -43
  85. data/lib/dependabot/nuget/native_discovery/native_workspace_discovery.rb +0 -61
  86. data/lib/dependabot/nuget/native_update_checker/native_requirements_updater.rb +0 -105
  87. data/lib/dependabot/nuget/native_update_checker/native_update_checker.rb +0 -214
  88. data/lib/dependabot/nuget/nuget_client.rb +0 -223
  89. data/lib/dependabot/nuget/update_checker/compatibility_checker.rb +0 -116
  90. data/lib/dependabot/nuget/update_checker/dependency_finder.rb +0 -297
  91. data/lib/dependabot/nuget/update_checker/nupkg_fetcher.rb +0 -221
  92. data/lib/dependabot/nuget/update_checker/nuspec_fetcher.rb +0 -110
  93. data/lib/dependabot/nuget/update_checker/property_updater.rb +0 -196
  94. data/lib/dependabot/nuget/update_checker/repository_finder.rb +0 -466
  95. data/lib/dependabot/nuget/update_checker/tfm_comparer.rb +0 -34
  96. data/lib/dependabot/nuget/update_checker/tfm_finder.rb +0 -30
  97. data/lib/dependabot/nuget/update_checker/version_finder.rb +0 -449
@@ -1,102 +0,0 @@
1
- # typed: strong
2
- # frozen_string_literal: true
3
-
4
- require "dependabot/nuget/native_discovery/native_evaluation_details"
5
- require "sorbet-runtime"
6
-
7
- module Dependabot
8
- module Nuget
9
- class NativeDependencyDetails
10
- extend T::Sig
11
-
12
- sig { params(json: T::Hash[String, T.untyped]).returns(NativeDependencyDetails) }
13
- def self.from_json(json)
14
- name = T.let(json.fetch("Name"), String)
15
- version = T.let(json.fetch("Version"), T.nilable(String))
16
- type = T.let(json.fetch("Type"), String)
17
- evaluation = NativeEvaluationDetails
18
- .from_json(T.let(json.fetch("EvaluationResult"), T.nilable(T::Hash[String, T.untyped])))
19
- target_frameworks = T.let(json.fetch("TargetFrameworks"), T.nilable(T::Array[String]))
20
- is_dev_dependency = T.let(json.fetch("IsDevDependency"), T::Boolean)
21
- is_direct = T.let(json.fetch("IsDirect"), T::Boolean)
22
- is_transitive = T.let(json.fetch("IsTransitive"), T::Boolean)
23
- is_override = T.let(json.fetch("IsOverride"), T::Boolean)
24
- is_update = T.let(json.fetch("IsUpdate"), T::Boolean)
25
- info_url = T.let(json.fetch("InfoUrl"), T.nilable(String))
26
-
27
- NativeDependencyDetails.new(name: name,
28
- version: version,
29
- type: type,
30
- evaluation: evaluation,
31
- target_frameworks: target_frameworks,
32
- is_dev_dependency: is_dev_dependency,
33
- is_direct: is_direct,
34
- is_transitive: is_transitive,
35
- is_override: is_override,
36
- is_update: is_update,
37
- info_url: info_url)
38
- end
39
-
40
- sig do
41
- params(name: String,
42
- version: T.nilable(String),
43
- type: String,
44
- evaluation: T.nilable(NativeEvaluationDetails),
45
- target_frameworks: T.nilable(T::Array[String]),
46
- is_dev_dependency: T::Boolean,
47
- is_direct: T::Boolean,
48
- is_transitive: T::Boolean,
49
- is_override: T::Boolean,
50
- is_update: T::Boolean,
51
- info_url: T.nilable(String)).void
52
- end
53
- def initialize(name:, version:, type:, evaluation:, target_frameworks:, is_dev_dependency:, is_direct:,
54
- is_transitive:, is_override:, is_update:, info_url:)
55
- @name = name
56
- @version = version
57
- @type = type
58
- @evaluation = evaluation
59
- @target_frameworks = target_frameworks
60
- @is_dev_dependency = is_dev_dependency
61
- @is_direct = is_direct
62
- @is_transitive = is_transitive
63
- @is_override = is_override
64
- @is_update = is_update
65
- @info_url = info_url
66
- end
67
-
68
- sig { returns(String) }
69
- attr_reader :name
70
-
71
- sig { returns(T.nilable(String)) }
72
- attr_reader :version
73
-
74
- sig { returns(String) }
75
- attr_reader :type
76
-
77
- sig { returns(T.nilable(NativeEvaluationDetails)) }
78
- attr_reader :evaluation
79
-
80
- sig { returns(T.nilable(T::Array[String])) }
81
- attr_reader :target_frameworks
82
-
83
- sig { returns(T::Boolean) }
84
- attr_reader :is_dev_dependency
85
-
86
- sig { returns(T::Boolean) }
87
- attr_reader :is_direct
88
-
89
- sig { returns(T::Boolean) }
90
- attr_reader :is_transitive
91
-
92
- sig { returns(T::Boolean) }
93
- attr_reader :is_override
94
-
95
- sig { returns(T::Boolean) }
96
- attr_reader :is_update
97
-
98
- sig { returns(T.nilable(String)) }
99
- attr_reader :info_url
100
- end
101
- end
102
- end
@@ -1,122 +0,0 @@
1
- # typed: strong
2
- # frozen_string_literal: true
3
-
4
- require "dependabot/nuget/native_discovery/native_dependency_details"
5
- require "sorbet-runtime"
6
-
7
- module Dependabot
8
- module Nuget
9
- class NativeDependencyFileDiscovery
10
- extend T::Sig
11
-
12
- sig do
13
- params(json: T.nilable(T::Hash[String, T.untyped]),
14
- directory: String).returns(T.nilable(NativeDependencyFileDiscovery))
15
- end
16
- def self.from_json(json, directory)
17
- return nil if json.nil?
18
-
19
- file_path = File.join(directory, T.let(json.fetch("FilePath"), String))
20
- dependencies = T.let(json.fetch("Dependencies"), T::Array[T::Hash[String, T.untyped]]).map do |dep|
21
- NativeDependencyDetails.from_json(dep)
22
- end
23
-
24
- NativeDependencyFileDiscovery.new(file_path: file_path,
25
- dependencies: dependencies)
26
- end
27
-
28
- sig do
29
- params(file_path: String,
30
- dependencies: T::Array[NativeDependencyDetails]).void
31
- end
32
- def initialize(file_path:, dependencies:)
33
- @file_path = file_path
34
- @dependencies = dependencies
35
- end
36
-
37
- sig { returns(String) }
38
- attr_reader :file_path
39
-
40
- sig { returns(T::Array[NativeDependencyDetails]) }
41
- attr_reader :dependencies
42
-
43
- sig { overridable.returns(Dependabot::FileParsers::Base::DependencySet) }
44
- def dependency_set # rubocop:disable Metrics/PerceivedComplexity
45
- dependency_set = Dependabot::FileParsers::Base::DependencySet.new
46
-
47
- file_name = Pathname.new(file_path).cleanpath.to_path
48
- dependencies.each do |dependency|
49
- next if dependency.name.casecmp("Microsoft.NET.Sdk")&.zero?
50
-
51
- # If the version string was evaluated it must have been successfully resolved
52
- if dependency.evaluation && dependency.evaluation&.result_type != "Success"
53
- logger.warn "Dependency '#{dependency.name}' excluded due to unparsable version: #{dependency.version}"
54
- next
55
- end
56
-
57
- # Exclude any dependencies using version ranges or wildcards
58
- next if dependency.version&.include?(",") ||
59
- dependency.version&.include?("*")
60
-
61
- # Exclude any dependencies specified using interpolation
62
- next if dependency.name.include?("%(") ||
63
- dependency.version&.include?("%(")
64
-
65
- # Exclude any dependencies which reference an item type
66
- next if dependency.name.include?("@(")
67
-
68
- dependency_set << build_dependency(file_name, dependency)
69
- end
70
-
71
- dependency_set
72
- end
73
-
74
- private
75
-
76
- sig { returns(::Logger) }
77
- def logger
78
- Dependabot.logger
79
- end
80
-
81
- sig { params(file_name: String, dependency_details: NativeDependencyDetails).returns(Dependabot::Dependency) }
82
- def build_dependency(file_name, dependency_details)
83
- requirement = build_requirement(file_name, dependency_details)
84
- requirements = requirement.nil? ? [] : [requirement]
85
-
86
- version = dependency_details.version&.gsub(/[\(\)\[\]]/, "")&.strip
87
- version = nil if version&.empty?
88
-
89
- Dependency.new(
90
- name: dependency_details.name,
91
- version: version,
92
- package_manager: "nuget",
93
- requirements: requirements
94
- )
95
- end
96
-
97
- sig do
98
- params(file_name: String, dependency_details: NativeDependencyDetails)
99
- .returns(T.nilable(T::Hash[Symbol, T.untyped]))
100
- end
101
- def build_requirement(file_name, dependency_details)
102
- return if dependency_details.is_transitive
103
-
104
- version = dependency_details.version
105
- version = nil if version&.empty?
106
-
107
- requirement = {
108
- requirement: version,
109
- file: file_name,
110
- groups: [dependency_details.is_dev_dependency ? "devDependencies" : "dependencies"],
111
- source: nil
112
- }
113
-
114
- property_name = dependency_details.evaluation&.root_property_name
115
- return requirement unless property_name
116
-
117
- requirement[:metadata] = { property_name: property_name }
118
- requirement
119
- end
120
- end
121
- end
122
- end
@@ -1,277 +0,0 @@
1
- # typed: strong
2
- # frozen_string_literal: true
3
-
4
- require "dependabot/dependency"
5
- require "dependabot/file_parsers/base/dependency_set"
6
- require "dependabot/nuget/cache_manager"
7
- require "dependabot/nuget/native_discovery/native_workspace_discovery"
8
- require "json"
9
- require "sorbet-runtime"
10
-
11
- module Dependabot
12
- module Nuget
13
- class NativeDiscoveryJsonReader
14
- extend T::Sig
15
-
16
- sig { returns(T::Hash[String, NativeDiscoveryJsonReader]) }
17
- def self.cache_directory_to_discovery_json_reader
18
- CacheManager.cache("cache_directory_to_discovery_json_reader")
19
- end
20
-
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")
24
- end
25
-
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")
29
- end
30
-
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
36
- end
37
-
38
- sig { void }
39
- def self.testonly_clear_discovery_files
40
- # this will get recreated when necessary
41
- FileUtils.rm_rf(discovery_directory)
42
- end
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
53
- end
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.
57
- sig do
58
- params(
59
- repo_contents_path: String,
60
- directory: String,
61
- credentials: T::Array[Dependabot::Credential]
62
- ).returns(NativeDiscoveryJsonReader)
63
- end
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)
74
-
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)
78
- end
79
-
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
94
- end
95
- end
96
-
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])
102
- end
103
-
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])
109
- end
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}/")
115
- end
116
-
117
- sig { returns(String) }
118
- def self.discovery_map_file_path
119
- File.join(discovery_directory, "discovery_map.json")
120
- end
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
156
- end
157
-
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(",")
161
- end
162
-
163
- sig { returns(String) }
164
- def self.discovery_directory
165
- t = File.join(Dir.home, ".dependabot")
166
- FileUtils.mkdir_p(t)
167
- t
168
- end
169
-
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,
176
- type: "file",
177
- content: File.read(discovery_file_path)
178
- )
179
- NativeDiscoveryJsonReader.new(repo_contents_path: repo_contents_path, discovery_json: discovery_json)
180
- end
181
-
182
- sig { returns(T.nilable(NativeWorkspaceDiscovery)) }
183
- attr_reader :workspace_discovery
184
-
185
- sig { returns(Dependabot::FileParsers::Base::DependencySet) }
186
- attr_reader :dependency_set
187
-
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
194
- @discovery_json = discovery_json
195
- @workspace_discovery = T.let(read_workspace_discovery, T.nilable(Dependabot::Nuget::NativeWorkspaceDiscovery))
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])
198
- end
199
-
200
- private
201
-
202
- sig { returns(String) }
203
- attr_reader :repo_contents_path
204
-
205
- sig { returns(DependencyFile) }
206
- attr_reader :discovery_json
207
-
208
- sig { returns(T.nilable(NativeWorkspaceDiscovery)) }
209
- def read_workspace_discovery
210
- return nil unless discovery_json.content
211
-
212
- parsed_json = T.let(JSON.parse(T.must(discovery_json.content)), T::Hash[String, T.untyped])
213
- NativeWorkspaceDiscovery.from_json(parsed_json)
214
- rescue JSON::ParserError
215
- raise Dependabot::DependencyFileNotParseable, discovery_json.path
216
- end
217
-
218
- sig { returns(Dependabot::FileParsers::Base::DependencySet) }
219
- def read_dependency_set
220
- dependency_set = Dependabot::FileParsers::Base::DependencySet.new
221
- return dependency_set unless workspace_discovery
222
-
223
- workspace_result = T.must(workspace_discovery)
224
- workspace_result.projects.each do |project|
225
- dependency_set += project.dependency_set
226
- end
227
- if workspace_result.dotnet_tools_json
228
- dependency_set += T.must(workspace_result.dotnet_tools_json).dependency_set
229
- end
230
- dependency_set += T.must(workspace_result.global_json).dependency_set if workspace_result.global_json
231
-
232
- dependency_set
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
275
- end
276
- end
277
- end
@@ -1,63 +0,0 @@
1
- # typed: strong
2
- # frozen_string_literal: true
3
-
4
- require "sorbet-runtime"
5
-
6
- module Dependabot
7
- module Nuget
8
- class NativeEvaluationDetails
9
- extend T::Sig
10
-
11
- sig { params(json: T.nilable(T::Hash[String, T.untyped])).returns(T.nilable(NativeEvaluationDetails)) }
12
- def self.from_json(json)
13
- return nil if json.nil?
14
-
15
- result_type = T.let(json.fetch("ResultType"), String)
16
- original_value = T.let(json.fetch("OriginalValue"), String)
17
- evaluated_value = T.let(json.fetch("EvaluatedValue"), String)
18
- root_property_name = T.let(json.fetch("RootPropertyName", nil), T.nilable(String))
19
- error_message = T.let(json.fetch("ErrorMessage", nil), T.nilable(String))
20
-
21
- NativeEvaluationDetails.new(result_type: result_type,
22
- original_value: original_value,
23
- evaluated_value: evaluated_value,
24
- root_property_name: root_property_name,
25
- error_message: error_message)
26
- end
27
-
28
- sig do
29
- params(result_type: String,
30
- original_value: String,
31
- evaluated_value: String,
32
- root_property_name: T.nilable(String),
33
- error_message: T.nilable(String)).void
34
- end
35
- def initialize(result_type:,
36
- original_value:,
37
- evaluated_value:,
38
- root_property_name:,
39
- error_message:)
40
- @result_type = result_type
41
- @original_value = original_value
42
- @evaluated_value = evaluated_value
43
- @root_property_name = root_property_name
44
- @error_message = error_message
45
- end
46
-
47
- sig { returns(String) }
48
- attr_reader :result_type
49
-
50
- sig { returns(String) }
51
- attr_reader :original_value
52
-
53
- sig { returns(String) }
54
- attr_reader :evaluated_value
55
-
56
- sig { returns(T.nilable(String)) }
57
- attr_reader :root_property_name
58
-
59
- sig { returns(T.nilable(String)) }
60
- attr_reader :error_message
61
- end
62
- end
63
- end
@@ -1,104 +0,0 @@
1
- # typed: strong
2
- # frozen_string_literal: true
3
-
4
- require "dependabot/nuget/native_discovery/native_dependency_details"
5
- require "dependabot/nuget/native_discovery/native_property_details"
6
- require "sorbet-runtime"
7
-
8
- module Dependabot
9
- module Nuget
10
- class NativeProjectDiscovery < NativeDependencyFileDiscovery
11
- extend T::Sig
12
-
13
- # rubocop:disable Metrics/AbcSize
14
- sig do
15
- override.params(json: T.nilable(T::Hash[String, T.untyped]),
16
- directory: String).returns(T.nilable(NativeProjectDiscovery))
17
- end
18
- def self.from_json(json, directory)
19
- return nil if json.nil?
20
-
21
- file_path = File.join(directory, T.let(json.fetch("FilePath"), String))
22
- properties = T.let(json.fetch("Properties"), T::Array[T::Hash[String, T.untyped]]).map do |prop|
23
- NativePropertyDetails.from_json(prop)
24
- end
25
- target_frameworks = T.let(json.fetch("TargetFrameworks"), T::Array[String])
26
- referenced_project_paths = T.let(json.fetch("ReferencedProjectPaths"), T::Array[String])
27
- dependencies = T.let(json.fetch("Dependencies"), T::Array[T::Hash[String, T.untyped]]).filter_map do |dep|
28
- details = NativeDependencyDetails.from_json(dep)
29
- next unless details.version # can't do anything without a version
30
-
31
- version = T.must(details.version)
32
- next unless version.length.positive? # can't do anything with an empty version
33
-
34
- next if version.include? "," # can't do anything with a range
35
-
36
- next if version.include? "*" # can't do anything with a wildcard
37
-
38
- details
39
- end
40
- imported_files = T.let(json.fetch("ImportedFiles"), T::Array[String])
41
- additional_files = T.let(json.fetch("AdditionalFiles"), T::Array[String])
42
-
43
- NativeProjectDiscovery.new(file_path: file_path,
44
- properties: properties,
45
- target_frameworks: target_frameworks,
46
- referenced_project_paths: referenced_project_paths,
47
- dependencies: dependencies,
48
- imported_files: imported_files,
49
- additional_files: additional_files)
50
- end
51
- # rubocop:enable Metrics/AbcSize
52
-
53
- sig do
54
- params(file_path: String,
55
- properties: T::Array[NativePropertyDetails],
56
- target_frameworks: T::Array[String],
57
- referenced_project_paths: T::Array[String],
58
- dependencies: T::Array[NativeDependencyDetails],
59
- imported_files: T::Array[String],
60
- additional_files: T::Array[String]).void
61
- end
62
- def initialize(file_path:,
63
- properties:,
64
- target_frameworks:,
65
- referenced_project_paths:,
66
- dependencies:,
67
- imported_files:,
68
- additional_files:)
69
- super(file_path: file_path, dependencies: dependencies)
70
- @properties = properties
71
- @target_frameworks = target_frameworks
72
- @referenced_project_paths = referenced_project_paths
73
- @imported_files = imported_files
74
- @additional_files = additional_files
75
- end
76
-
77
- sig { returns(T::Array[NativePropertyDetails]) }
78
- attr_reader :properties
79
-
80
- sig { returns(T::Array[String]) }
81
- attr_reader :target_frameworks
82
-
83
- sig { returns(T::Array[String]) }
84
- attr_reader :referenced_project_paths
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
-
92
- sig { override.returns(Dependabot::FileParsers::Base::DependencySet) }
93
- def dependency_set
94
- if target_frameworks.empty? && file_path.end_with?("proj")
95
- Dependabot.logger.warn("Excluding project file '#{file_path}' due to unresolvable target framework")
96
- dependency_set = Dependabot::FileParsers::Base::DependencySet.new
97
- return dependency_set
98
- end
99
-
100
- super
101
- end
102
- end
103
- end
104
- end