class Dependabot::Composer::FileParser
Constants
- DEPENDENCY_GROUP_KEYS
Public Instance Methods
parse()
click to toggle source
# File lib/dependabot/composer/file_parser.rb, line 28 def parse dependency_set = DependencySet.new dependency_set += manifest_dependencies dependency_set += lockfile_dependencies dependency_set.dependencies end
Private Instance Methods
build_lockfile_dependency(name, version, keys)
click to toggle source
rubocop:enable Metrics/PerceivedComplexity
# File lib/dependabot/composer/file_parser.rb, line 109 def build_lockfile_dependency(name, version, keys) Dependency.new( name: name, version: version, requirements: [], package_manager: "composer", subdependency_metadata: [{ production: keys.fetch(:group) != "development" }] ) end
build_manifest_dependency(name, req, keys)
click to toggle source
# File lib/dependabot/composer/file_parser.rb, line 63 def build_manifest_dependency(name, req, keys) Dependency.new( name: name, version: dependency_version(name: name, type: keys[:group]), requirements: [{ requirement: req, file: "composer.json", source: dependency_source( name: name, type: keys[:group], requirement: req ), groups: [keys[:group]] }], package_manager: "composer" ) end
check_required_files()
click to toggle source
# File lib/dependabot/composer/file_parser.rb, line 185 def check_required_files raise "No composer.json!" unless get_original_file("composer.json") end
composer_json()
click to toggle source
# File lib/dependabot/composer/file_parser.rb, line 203 def composer_json @composer_json ||= get_original_file("composer.json") end
dependency_source(name:, type:, requirement:)
click to toggle source
# File lib/dependabot/composer/file_parser.rb, line 133 def dependency_source(name:, type:, requirement:) return unless lockfile package_details = lockfile_details(name: name, type: type) return unless package_details if package_details["source"].nil? && package_details.dig("dist", "type") == "path" return { type: "path" } end git_dependency_details(package_details, requirement) end
dependency_version(name:, type:)
click to toggle source
# File lib/dependabot/composer/file_parser.rb, line 121 def dependency_version(name:, type:) return unless lockfile package = lockfile_details(name: name, type: type) return unless package version = package.fetch("version")&.to_s&.sub(/^v?/, "") return version unless version&.start_with?("dev-") package.dig("source", "reference") end
git_dependency_details(package_details, requirement)
click to toggle source
# File lib/dependabot/composer/file_parser.rb, line 147 def git_dependency_details(package_details, requirement) return unless package_details.dig("source", "type") == "git" branch = if requirement.start_with?("dev-") requirement. sub(/^dev-/, ""). sub(/\s+as\s.*/, ""). split("#").first elsif package_details.fetch("version")&.to_s&.start_with?("dev-") package_details.fetch("version")&.to_s&.sub(/^dev-/, "") end details = { type: "git", url: package_details.dig("source", "url") } return details unless branch details.merge(branch: branch, ref: nil) end
lockfile()
click to toggle source
# File lib/dependabot/composer/file_parser.rb, line 207 def lockfile @lockfile ||= get_original_file("composer.lock") end
lockfile_dependencies()
click to toggle source
rubocop:disable Metrics/PerceivedComplexity
# File lib/dependabot/composer/file_parser.rb, line 82 def lockfile_dependencies dependencies = DependencySet.new return dependencies unless lockfile DEPENDENCY_GROUP_KEYS.each do |keys| key = keys.fetch(:lockfile) next unless parsed_lockfile[key].is_a?(Array) parsed_lockfile[key].each do |details| name = details["name"] next unless name.is_a?(String) && package?(name) version = details["version"]&.to_s&.sub(/^v?/, "") next unless version.is_a?(String) next unless version.match?(/^\d/) || version.match?(/^[0-9a-f]{40}$/) dependencies << build_lockfile_dependency(name, version, keys) end end dependencies end
lockfile_details(name:, type:)
click to toggle source
# File lib/dependabot/composer/file_parser.rb, line 166 def lockfile_details(name:, type:) key = lockfile_key(type) parsed_lockfile.fetch(key, []).find { |d| d["name"] == name } end
lockfile_key(type)
click to toggle source
# File lib/dependabot/composer/file_parser.rb, line 171 def lockfile_key(type) case type when "runtime" then "packages" when "development" then "packages-dev" else raise "unknown type #{type}" end end
manifest_dependencies()
click to toggle source
# File lib/dependabot/composer/file_parser.rb, line 37 def manifest_dependencies dependencies = DependencySet.new DEPENDENCY_GROUP_KEYS.each do |keys| next unless parsed_composer_json[keys[:manifest]].is_a?(Hash) parsed_composer_json[keys[:manifest]].each do |name, req| next unless package?(name) if lockfile version = dependency_version(name: name, type: keys[:group]) # Ignore dependency versions which don't appear in the # composer.lock or are non-numeric and not a git SHA, since they # can't be compared later in the process. next unless version&.match?(/^\d/) || version&.match?(/^[0-9a-f]{40}$/) end dependencies << build_manifest_dependency(name, req, keys) end end dependencies end
package?(name)
click to toggle source
# File lib/dependabot/composer/file_parser.rb, line 179 def package?(name) # Filter out php, ext-, composer-plugin-api, and other special # packages which don't behave as normal name.split("/").count == 2 end
parsed_composer_json()
click to toggle source
# File lib/dependabot/composer/file_parser.rb, line 197 def parsed_composer_json @parsed_composer_json ||= JSON.parse(composer_json.content) rescue JSON::ParserError raise Dependabot::DependencyFileNotParseable, composer_json.path end
parsed_lockfile()
click to toggle source
# File lib/dependabot/composer/file_parser.rb, line 189 def parsed_lockfile return unless lockfile @parsed_lockfile ||= JSON.parse(lockfile.content) rescue JSON::ParserError raise Dependabot::DependencyFileNotParseable, lockfile.path end