class Dependabot::Cargo::FileParser
Constants
- DEPENDENCY_TYPES
Public Instance Methods
parse()
click to toggle source
# File lib/dependabot/cargo/file_parser.rb, line 23 def parse check_rust_workspace_root dependency_set = DependencySet.new dependency_set += manifest_dependencies dependency_set += lockfile_dependencies if lockfile dependencies = dependency_set.dependencies # TODO: Handle patched dependencies dependencies.reject! { |d| patched_dependencies.include?(d.name) } # TODO: Currently, Dependabot can't handle dependencies that have # multiple sources. Fix that! dependencies.reject do |dep| dep.requirements.map { |r| r.fetch(:source) }.uniq.count > 1 end end
Private Instance Methods
build_dependency(name, requirement, type, file)
click to toggle source
rubocop:enable Metrics/PerceivedComplexity
# File lib/dependabot/cargo/file_parser.rb, line 88 def build_dependency(name, requirement, type, file) Dependency.new( name: name, version: version_from_lockfile(name, requirement), package_manager: "cargo", requirements: [{ requirement: requirement_from_declaration(requirement), file: file.name, groups: [type], source: source_from_declaration(requirement) }] ) end
check_required_files()
click to toggle source
# File lib/dependabot/cargo/file_parser.rb, line 203 def check_required_files raise "No Cargo.toml!" unless get_original_file("Cargo.toml") end
check_rust_workspace_root()
click to toggle source
# File lib/dependabot/cargo/file_parser.rb, line 44 def check_rust_workspace_root cargo_toml = dependency_files.find { |f| f.name == "Cargo.toml" } workspace_root = parsed_file(cargo_toml).dig("package", "workspace") return unless workspace_root msg = "This project is part of a Rust workspace but is not the "\ "workspace root."\ if cargo_toml.directory != "/" msg += "Please update your settings so Dependabot points at the "\ "workspace root instead of #{cargo_toml.directory}." end raise Dependabot::DependencyFileNotEvaluatable, msg end
git_req?(declaration)
click to toggle source
# File lib/dependabot/cargo/file_parser.rb, line 184 def git_req?(declaration) source_from_declaration(declaration)&.fetch(:type, nil) == "git" end
git_source_details(declaration)
click to toggle source
# File lib/dependabot/cargo/file_parser.rb, line 188 def git_source_details(declaration) { type: "git", url: declaration["git"], branch: declaration["branch"], ref: declaration["tag"] || declaration["rev"] } end
lockfile()
click to toggle source
# File lib/dependabot/cargo/file_parser.rb, line 221 def lockfile @lockfile ||= get_original_file("Cargo.lock") end
lockfile_dependencies()
click to toggle source
# File lib/dependabot/cargo/file_parser.rb, line 102 def lockfile_dependencies dependency_set = DependencySet.new return dependency_set unless lockfile parsed_file(lockfile).fetch("package", []).each do |package_details| next unless package_details["source"] # TODO: This isn't quite right, as it will only give us one # version of each dependency (when in fact there are many) dependency_set << Dependency.new( name: package_details["name"], version: version_from_lockfile_details(package_details), package_manager: "cargo", requirements: [] ) end dependency_set end
manifest_dependencies()
click to toggle source
rubocop:disable Metrics/PerceivedComplexity
# File lib/dependabot/cargo/file_parser.rb, line 60 def manifest_dependencies dependency_set = DependencySet.new manifest_files.each do |file| DEPENDENCY_TYPES.each do |type| parsed_file(file).fetch(type, {}).each do |name, requirement| next unless name == name_from_declaration(name, requirement) next if lockfile && !version_from_lockfile(name, requirement) dependency_set << build_dependency(name, requirement, type, file) end parsed_file(file).fetch("target", {}).each do |_, t_details| t_details.fetch(type, {}).each do |name, requirement| next unless name == name_from_declaration(name, requirement) next if lockfile && !version_from_lockfile(name, requirement) dependency_set << build_dependency(name, requirement, type, file) end end end end dependency_set end
manifest_files()
click to toggle source
# File lib/dependabot/cargo/file_parser.rb, line 214 def manifest_files @manifest_files ||= dependency_files. select { |f| f.name.end_with?("Cargo.toml") }. reject(&:support_file?) end
name_from_declaration(name, declaration)
click to toggle source
# File lib/dependabot/cargo/file_parser.rb, line 139 def name_from_declaration(name, declaration) return name if declaration.is_a?(String) raise "Unexpected dependency declaration: #{declaration}" unless declaration.is_a?(Hash) declaration.fetch("package", name) end
parsed_file(file)
click to toggle source
# File lib/dependabot/cargo/file_parser.rb, line 207 def parsed_file(file) @parsed_file ||= {} @parsed_file[file.name] ||= TomlRB.parse(file.content) rescue TomlRB::ParseError, TomlRB::ValueOverwriteError raise Dependabot::DependencyFileNotParseable, file.path end
patched_dependencies()
click to toggle source
# File lib/dependabot/cargo/file_parser.rb, line 122 def patched_dependencies root_manifest = manifest_files.find { |f| f.name == "Cargo.toml" } return [] unless parsed_file(root_manifest)["patch"] parsed_file(root_manifest)["patch"].values.flat_map(&:keys) end
requirement_from_declaration(declaration)
click to toggle source
# File lib/dependabot/cargo/file_parser.rb, line 129 def requirement_from_declaration(declaration) if declaration.is_a?(String) return declaration == "" ? nil : declaration end raise "Unexpected dependency declaration: #{declaration}" unless declaration.is_a?(Hash) return declaration["version"] if declaration["version"].is_a?(String) && declaration["version"] != "" nil end
source_from_declaration(declaration)
click to toggle source
# File lib/dependabot/cargo/file_parser.rb, line 146 def source_from_declaration(declaration) return if declaration.is_a?(String) raise "Unexpected dependency declaration: #{declaration}" unless declaration.is_a?(Hash) return git_source_details(declaration) if declaration["git"] return { type: "path" } if declaration["path"] end
version_class()
click to toggle source
# File lib/dependabot/cargo/file_parser.rb, line 225 def version_class Cargo::Version end
version_from_lockfile(name, declaration)
click to toggle source
# File lib/dependabot/cargo/file_parser.rb, line 154 def version_from_lockfile(name, declaration) return unless lockfile candidate_packages = parsed_file(lockfile).fetch("package", []). select { |p| p["name"] == name } if (req = requirement_from_declaration(declaration)) req = Cargo::Requirement.new(req) candidate_packages = candidate_packages. select { |p| req.satisfied_by?(version_class.new(p["version"])) } end candidate_packages = candidate_packages. select do |p| git_req?(declaration) ^ !p["source"]&.start_with?("git+") end package = candidate_packages. max_by { |p| version_class.new(p["version"]) } return unless package version_from_lockfile_details(package) end
version_from_lockfile_details(package_details)
click to toggle source
# File lib/dependabot/cargo/file_parser.rb, line 197 def version_from_lockfile_details(package_details) return package_details["version"] unless package_details["source"]&.start_with?("git+") package_details["source"].split("#").last end