Skip to content

Commit

Permalink
Merge pull request #67 from macblazer/45-follow-rubocop-formatting-an…
Browse files Browse the repository at this point in the history
…d-run-rubocop-during-prs

Follow rubocop formatting
  • Loading branch information
macblazer committed Feb 8, 2024
2 parents 8a7a2cd + 421342a commit 230e06b
Show file tree
Hide file tree
Showing 22 changed files with 437 additions and 274 deletions.
1 change: 1 addition & 0 deletions .licenserc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,4 @@ header:
- "spec/fixtures/**"
- "LICENSE"
- "NOTICE"
- "exe/cyclonedx-cocoapods"
4 changes: 2 additions & 2 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,6 @@ Metrics/BlockLength:

# Allow some long methods because breaking them up doesn't help anything.
Metrics/MethodLength:
AllowedMethods: ['parse_options', 'add_to_bom']
AllowedMethods: ['parse_options', 'add_to_bom', 'append_all_pod_dependencies']
Metrics/AbcSize:
AllowedMethods: ['parse_options', 'add_to_bom']
AllowedMethods: ['parse_options', 'add_to_bom', 'source_for_pod']
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# frozen_string_literal: true

source "https://rubygems.org"
source 'https://rubygems.org'
gemspec
4 changes: 2 additions & 2 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

require "bundler/gem_tasks"
require "rspec/core/rake_task"
require 'bundler/gem_tasks'
require 'rspec/core/rake_task'

RSpec::Core::RakeTask.new(:spec)

Expand Down
6 changes: 3 additions & 3 deletions bin/console
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#!/usr/bin/env ruby
# frozen_string_literal: true

require "bundler/setup"
require "cyclonedx/cocoapods"
require 'bundler/setup'
require 'cyclonedx/cocoapods'

# You can add fixtures and/or initialization code here to make experimenting
# with your gem easier. You can also use a different console, if you like.
Expand All @@ -11,5 +11,5 @@ require "cyclonedx/cocoapods"
# require "pry"
# Pry.start

require "irb"
require 'irb'
IRB.start(__FILE__)
8 changes: 5 additions & 3 deletions cyclonedx-cocoapods.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ Gem::Specification.new do |spec|
spec.email = ['[email protected]', '[email protected]']

spec.summary = 'CycloneDX software bill-of-material (SBOM) generation utility'
spec.description = 'CycloneDX is a lightweight software bill-of-material (SBOM) specification designed for use in application security contexts and supply chain component analysis. This Gem generates CycloneDX BOMs from CocoaPods projects.'
spec.description = 'CycloneDX is a lightweight software bill-of-material (SBOM) specification designed for ' \
'use in application security contexts and supply chain component analysis. This Gem ' \
'generates CycloneDX BOMs from CocoaPods projects.'
spec.homepage = 'https://github.com/CycloneDX/cyclonedx-cocoapods'
spec.license = 'Apache-2.0'
spec.required_ruby_version = Gem::Requirement.new('>= 2.4.0')
Expand All @@ -18,7 +20,7 @@ Gem::Specification.new do |spec|
spec.metadata['source_code_uri'] = 'https://github.com/CycloneDX/cyclonedx-cocoapods.git'

# Specify which files should be added to the gem when it is released.
spec.files = Dir['lib/**/*.{rb,json}'] + %w{ exe/cyclonedx-cocoapods README.md CHANGELOG.md LICENSE NOTICE }
spec.files = Dir['lib/**/*.{rb,json}'] + %w[exe/cyclonedx-cocoapods README.md CHANGELOG.md LICENSE NOTICE]

spec.bindir = 'exe'
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
Expand All @@ -27,7 +29,7 @@ Gem::Specification.new do |spec|
spec.add_runtime_dependency 'cocoapods', ['>= 1.10.1', '< 2.0']
spec.add_runtime_dependency 'nokogiri', ['>= 1.11.2', '< 2.0']

spec.add_development_dependency 'equivalent-xml', '~> 0.6.0'
spec.add_development_dependency 'rake', '~> 13.0'
spec.add_development_dependency 'rspec', '~> 3.0'
spec.add_development_dependency 'equivalent-xml', '~> 0.6.0'
end
6 changes: 4 additions & 2 deletions exe/cyclonedx-cocoapods
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#!/usr/bin/env ruby
# frozen_string_literal: true

#
# This file is part of CycloneDX CocoaPods
#
Expand All @@ -18,6 +20,6 @@
# Copyright (c) OWASP Foundation. All Rights Reserved.
#

require "cyclonedx/cocoapods/cli_runner"
require 'cyclonedx/cocoapods/cli_runner'

CycloneDX::CocoaPods::CLIRunner.new().run
CycloneDX::CocoaPods::CLIRunner.new.run
18 changes: 12 additions & 6 deletions lib/cyclonedx/cocoapods/cli_runner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,17 @@ def setup_logger(verbose: true)
end

def write_bom_to_file(bom:, options:)
bom_file_path = prep_for_bom_write(options)

begin
File.write(bom_file_path, bom)
@logger.info "BOM written to #{bom_file_path}"
rescue StandardError
raise BOMOutputError, "Unable to write the BOM to #{bom_file_path}"
end
end

def prep_for_bom_write(options)
bom_file_path = Pathname.new(options[:bom_file_path] || './bom.xml').expand_path
bom_dir = bom_file_path.dirname

Expand All @@ -168,12 +179,7 @@ def write_bom_to_file(bom:, options:)
raise BOMOutputError, "Unable to create the BOM output directory at #{bom_dir}"
end

begin
File.write(bom_file_path, bom)
@logger.info "BOM written to #{bom_file_path}"
rescue StandardError
raise BOMOutputError, "Unable to write the BOM to #{bom_file_path}"
end
bom_file_path
end
end
end
Expand Down
16 changes: 11 additions & 5 deletions lib/cyclonedx/cocoapods/component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,19 @@ class Component

attr_reader :group, :name, :version, :type

def initialize(group: nil, name:, version:, type:)
raise ArgumentError, "Group, if specified, must be non empty" if !group.nil? && group.to_s.strip.empty?
raise ArgumentError, "Name must be non empty" if name.nil? || name.to_s.strip.empty?
def initialize(name:, version:, type:, group: nil)
raise ArgumentError, 'Group, if specified, must be non empty' if !group.nil? && group.to_s.strip.empty?
raise ArgumentError, 'Name must be non empty' if name.nil? || name.to_s.strip.empty?

Gem::Version.new(version) # To check that the version string is well formed
raise ArgumentError, "#{type} is not valid component type (#{VALID_COMPONENT_TYPES.join('|')})" unless VALID_COMPONENT_TYPES.include?(type)
unless VALID_COMPONENT_TYPES.include?(type)
raise ArgumentError, "#{type} is not valid component type (#{VALID_COMPONENT_TYPES.join('|')})"
end

@group, @name, @version, @type = group, name, version, type
@group = group
@name = name
@version = version
@type = type
end
end
end
Expand Down
10 changes: 4 additions & 6 deletions lib/cyclonedx/cocoapods/license.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,13 @@ module CocoaPods
class Pod
class License
SPDX_LICENSES = JSON.parse(File.read("#{__dir__}/spdx-licenses.json")).freeze
IDENTIFIER_TYPES = [:id, :name].freeze
IDENTIFIER_TYPES = %i[id name].freeze

attr_reader :identifier
attr_reader :identifier_type
attr_accessor :text
attr_accessor :url
attr_reader :identifier, :identifier_type
attr_accessor :text, :url

def initialize(identifier:)
raise ArgumentError, "License identifier must be non empty" if identifier.nil? || identifier.to_s.strip.empty?
raise ArgumentError, 'License identifier must be non empty' if identifier.nil? || identifier.to_s.strip.empty?

@identifier = SPDX_LICENSES.find { |license_id| license_id.downcase == identifier.to_s.downcase }
@identifier_type = @identifier.nil? ? :name : :id
Expand Down
78 changes: 47 additions & 31 deletions lib/cyclonedx/cocoapods/pod.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,26 +25,40 @@
module CycloneDX
module CocoaPods
class Pod
attr_reader :name # xs:normalizedString
attr_reader :version # xs:normalizedString
attr_reader :source # Anything responding to :source_qualifier
attr_reader :homepage # xs:anyURI - https://cyclonedx.org/docs/1.4/#type_externalReference
attr_reader :checksum # https://cyclonedx.org/docs/1.4/#type_hashValue (We only use SHA-1 hashes - length == 40)
attr_reader :author # xs:normalizedString
attr_reader :description # xs:normalizedString
attr_reader :license # https://cyclonedx.org/docs/1.4/#type_licenseType
# We don't currently support several licenses or license expressions https://spdx.github.io/spdx-spec/appendix-IV-SPDX-license-expressions/
# xs:normalizedString
attr_reader :name
# xs:normalizedString
attr_reader :version
# Anything responding to :source_qualifier
attr_reader :source
# xs:anyURI - https://cyclonedx.org/docs/1.4/xml/#type_externalReference
attr_reader :homepage
# https://cyclonedx.org/docs/1.4/xml/#type_hashValue (We only use SHA-1 hashes - length == 40)
attr_reader :checksum
# xs:normalizedString
attr_reader :author
# xs:normalizedString
attr_reader :description
# https://cyclonedx.org/docs/1.4/xml/#type_licenseType
# We don't currently support several licenses or license expressions https://spdx.github.io/spdx-spec/appendix-IV-SPDX-license-expressions/
attr_reader :license

def initialize(name:, version:, source: nil, checksum: nil)
raise ArgumentError, "Name must be non empty" if name.nil? || name.to_s.empty?
raise ArgumentError, 'Name must be non empty' if name.nil? || name.to_s.empty?
raise ArgumentError, "Name shouldn't contain spaces" if name.to_s.include?(' ')
raise ArgumentError, "Name shouldn't start with a dot" if name.to_s.start_with?('.')

# `pod create` also enforces no plus sign, but more than 500 public pods have a plus in the root name.
# https://github.com/CocoaPods/CocoaPods/blob/9461b346aeb8cba6df71fd4e71661688138ec21b/lib/cocoapods/command/lib/create.rb#L35

Gem::Version.new(version) # To check that the version string is well formed
raise ArgumentError, "Invalid pod source" unless source.nil? || source.respond_to?(:source_qualifier)
raise ArgumentError, 'Invalid pod source' unless source.nil? || source.respond_to?(:source_qualifier)
raise ArgumentError, "#{checksum} is not valid SHA-1 hash" unless checksum.nil? || checksum =~ /[a-fA-F0-9]{40}/
@name, @version, @source, @checksum = name.to_s, version, source, checksum

@name = name.to_s
@version = version
@source = source
@checksum = checksum
end

def root_name
Expand All @@ -61,23 +75,21 @@ def populate(attributes)
end

def to_s
"Pod<#{name}, #{version.to_s}>"
"Pod<#{name}, #{version}>"
end

private

def populate_author(attributes)
authors = attributes[:author] || attributes[:authors]
case authors
when String
@author = authors
when Array
@author = authors.join(', ')
when Hash
@author = authors.map { |name, email| "#{name} <#{email}>" }.join(', ')
else
@author = nil
end
@author = case authors
when String
authors
when Array
authors.join(', ')
when Hash
authors.map { |name, email| "#{name} <#{email}>" }.join(', ')
end
end

def populate_description(attributes)
Expand All @@ -89,19 +101,23 @@ def populate_license(attributes)
when String
@license = License.new(identifier: attributes[:license])
when Hash
attributes[:license].transform_keys!(&:to_sym)
identifier = attributes[:license][:type]
unless identifier.nil? || identifier.to_s.strip.empty?
@license = License.new(identifier: identifier)
@license.text = attributes[:license][:text]
else
@license = nil
end
populate_hashed_license(attributes)
else
@license = nil
end
end

def populate_hashed_license(attributes)
attributes[:license].transform_keys!(&:to_sym)
identifier = attributes[:license][:type]
if identifier.nil? || identifier.to_s.strip.empty?
@license = nil
else
@license = License.new(identifier: identifier)
@license.text = attributes[:license][:text]
end
end

def populate_homepage(attributes)
@homepage = attributes[:homepage]
end
Expand Down
25 changes: 20 additions & 5 deletions lib/cyclonedx/cocoapods/pod_attributes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,35 @@ class CocoaPodsRepository
def self.searchable_source(url:, source_manager:)
source = CocoaPodsRepository.new(url: url)
source.source_manager = source_manager
return source
source
end

def attributes_for(pod:)
specification_sets = @source_manager.search_by_name("^#{Regexp.escape(pod.root_name)}$")
raise SearchError, "No pod found named #{pod.name}; run 'pod repo update' and try again" if specification_sets.length == 0
raise SearchError, "More than one pod found named #{pod.name}; a pod in a private spec repo should not have the same name as a public pod" if specification_sets.length > 1
validate_spec_sets(specification_sets, pod)

paths = specification_sets[0].specification_paths_for_version(pod.version)
raise SearchError, "Version #{pod.version} not found for pod #{pod.name}; run 'pod repo update' and try again" if paths.length == 0
if paths.empty?
raise SearchError,
"Version #{pod.version} not found for pod #{pod.name}; run 'pod repo update' and try again"
end

::Pod::Specification.from_file(paths[0]).attributes_hash
end

private

def validate_spec_sets(specification_sets, pod)
if specification_sets.empty?
raise SearchError,
"No pod found named #{pod.name}; run 'pod repo update' and try again"
end
return unless specification_sets.length > 1

raise SearchError,
"More than one pod found named #{pod.name}; a pod in a private spec repo " \
'should not have the same name as a public pod'
end
end

class GitRepository
Expand All @@ -64,7 +80,6 @@ def attributes_for(pod:)
end
end


class Pod
def complete_information_from_source
populate(source.attributes_for(pod: self))
Expand Down
Loading

0 comments on commit 230e06b

Please sign in to comment.