cyclonedx-cocoapods 1.0.0 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e656666b5b0297c98ddebe571a31e68ada3ff7fa9a048fc10f4f824fee1982c8
4
- data.tar.gz: d398292e90265bf460874a2db759fb20a7d596067c4aa35afdb07d942aead192
3
+ metadata.gz: 4185f4f9ba77e7307a2f2a93ca2d96412775a6fa1a9d863b0955e0ccde099214
4
+ data.tar.gz: 4df386bef89ea9bb2bc7bfd9299a582faec48e8887f7443acd2cfb321947c0fd
5
5
  SHA512:
6
- metadata.gz: 1d7e28f6e783cc643d6563671412747c57ed8f26c49fdb34df1bc708662e6369027444f3ef2a4b0be84e1429538d12f80017a7ea61be0b5612210ae272ee00fa
7
- data.tar.gz: 2e99db6f7a0f502190ace2511e954b6c43439eb21b5b13509165590ea3075b30ea8ee9fdb7f88a5986ae767c487abb941d6d5548e91448edc11784a377dec25b
6
+ metadata.gz: 847962664a8e0d9eca4ee42d2560151de4f56fbdcb3524ff1ad208f6cac0bc5b234d879f09cccdcaddf6df81096bdb89ea26923e2195e2127334276bfb32b856
7
+ data.tar.gz: 799ca49eb4e2dd2caf9c93cd211692a364091ef8366895fe6595d109d8b455bf222c607e19b16bd410e927d7099a29a2d1dfad8b0f9d84b837705f7e7b448bb1
data/CHANGELOG.md CHANGED
@@ -4,6 +4,20 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
5
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [1.1.1]
8
+
9
+ ### Changed
10
+ - Better error messaging when a problem is encountered while gathering pod information ([Issue #48](https://github.com/CycloneDX/cyclonedx-cocoapods/issues/48)) [@macblazer](https://github.com/macblazer).
11
+
12
+ ### Fixed
13
+ - Including a pod that has a platform-specific dependency for an unused platform no longer causes a crash ([Issue #46](https://github.com/CycloneDX/cyclonedx-cocoapods/issues/46)) [@macblazer](https://github.com/macblazer).
14
+ - Analyzing a Podfile that has no pods defined in it no longer causes a crash [@macblazer](https://github.com/macblazer).
15
+
16
+ ## [1.1.0]
17
+
18
+ ### Added
19
+ - Can now eliminate Podfile targets that include "test" in their name ([Issue #43](https://github.com/CycloneDX/cyclonedx-cocoapods/issues/43)) [@macblazer](https://github.com/macblazer).
20
+
7
21
  ## [1.0.0]
8
22
 
9
23
  ### Added
data/README.md CHANGED
@@ -9,7 +9,7 @@
9
9
 
10
10
  # CycloneDX CocoaPods (Objective-C/Swift)
11
11
 
12
- The CycloneDX CocoaPods Gem creates a valid CycloneDX software bill-of-material document from all project dependencies. CycloneDX is a lightweight BoM specification that is easily created, human readable, and simple to parse.
12
+ The CycloneDX CocoaPods Gem creates a valid CycloneDX software bill-of-material document from all [CocoaPods](https://cocoapods.org/) project dependencies. CycloneDX is a lightweight BoM specification that is easily created, human readable, and simple to parse.
13
13
 
14
14
  ## Installation
15
15
 
@@ -36,18 +36,30 @@ Building from source requires Ruby 2.4.0 or newer.
36
36
  You can use the [CycloneDX CLI](https://github.com/CycloneDX/cyclonedx-cli#convert-command) to convert between multiple BOM formats or specification versions.
37
37
 
38
38
  ## Usage
39
- Usage: `cyclonedx-cocoapods` [options]
40
-
41
- --[no-]verbose Run verbosely
42
- -p, --path path (Optional) Path to CocoaPods project directory, current directory if missing
43
- -o, --output bom_file_path (Optional) Path to output the bom.xml file to
44
- -b, --bom-version bom_version (Optional) Version of the generated BOM, 1 if not provided
45
- -g, --group group (Optional) Group of the component for which the BOM is generated
46
- -n, --name name (Optional, if specified version and type are also required) Name of the component for which the BOM is generated
47
- -v, --version version (Optional) Version of the component for which the BOM is generated
48
- -t, --type type (Optional) Type of the component for which the BOM is generated (one of application|framework|library|container|operating-system|device|firmware|file)
39
+ ```
40
+ Generates a BOM with the given parameters. BOM component metadata is only generated if the component's name, version, and type are provided using the --name, --version, and --type parameters.
41
+ [version <version_number>]
42
+
43
+ USAGE
44
+ cyclonedx-cocoapods [options]
45
+
46
+ OPTIONS
47
+ --[no-]verbose Show verbose debugging output
49
48
  -h, --help Show help message
50
49
 
50
+ BOM Generation
51
+ -p, --path path Path to CocoaPods project directory (default: current directory)
52
+ -o, --output bom_file_path Path to output the bom.xml file to (default: "bom.xml")
53
+ -b, --bom-version bom_version Version of the generated BOM (default: "1")
54
+ -x, --exclude-test-targets Eliminate Podfile targets whose name contains the word "test"
55
+
56
+ Component Metadata
57
+ -n, --name name (If specified version and type are also required) Name of the component for which the BOM is generated
58
+ -v, --version version Version of the component for which the BOM is generated
59
+ -t, --type type Type of the component for which the BOM is generated (one of application|framework|library|container|operating-system|device|firmware|file)
60
+ -g, --group group Group of the component for which the BOM is generated
61
+ ```
62
+
51
63
  **Output:** BoM file at specified location, `./bom.xml` if not specified
52
64
 
53
65
  ### Example
@@ -18,19 +18,15 @@
18
18
  # Copyright (c) OWASP Foundation. All Rights Reserved.
19
19
  #
20
20
 
21
- require 'optparse'
22
21
  require 'logger'
23
- require 'cocoapods'
22
+ require 'optparse'
24
23
 
25
- require_relative 'component'
26
- require_relative 'pod'
27
- require_relative 'pod_attributes'
28
- require_relative 'source'
29
24
  require_relative 'bom_builder'
25
+ require_relative 'component'
26
+ require_relative 'podfile_analyzer'
30
27
 
31
28
  module CycloneDX
32
29
  module CocoaPods
33
- class PodfileParsingError < StandardError; end
34
30
  class BOMOutputError < StandardError; end
35
31
 
36
32
  class CLIRunner
@@ -41,10 +37,10 @@ module CycloneDX
41
37
  setup_logger(verbose: options[:verbose])
42
38
  @logger.debug "Running cyclonedx-cocoapods with options: #{options}"
43
39
 
44
- podfile, lockfile = ensure_podfile_and_lock_are_present(options)
45
- pods = parse_pods(podfile, lockfile)
46
-
47
- populate_pods_with_additional_info(pods)
40
+ analyzer = PodfileAnalyzer.new(logger: @logger, exclude_test_targets: options[:exclude_test_targets])
41
+ podfile, lockfile = analyzer.ensure_podfile_and_lock_are_present(options)
42
+ pods = analyzer.parse_pods(podfile, lockfile)
43
+ analyzer.populate_pods_with_additional_info(pods)
48
44
 
49
45
  bom = BOMBuilder.new(component: component_from_options(options), pods: pods).bom(version: options[:bom_version] || 1)
50
46
  write_bom_to_file(bom: bom, options: options)
@@ -57,34 +53,48 @@ module CycloneDX
57
53
 
58
54
  private
59
55
 
56
+
60
57
  def parseOptions
61
58
  parsedOptions = {}
62
59
  component_types = Component::VALID_COMPONENT_TYPES
63
60
  OptionParser.new do |options|
64
61
  options.banner = <<~BANNER
65
- Usage: cyclonedx-cocoapods [options]
66
- Generates a BOM with the given parameters. BOM component metadata is only generated if the component's name and version are provided using the --name and --version parameters.
62
+ Generates a BOM with the given parameters. BOM component metadata is only generated if the component's name, version, and type are provided using the --name, --version, and --type parameters.
63
+ [version #{CycloneDX::CocoaPods::VERSION}]
64
+
65
+ USAGE
66
+ cyclonedx-cocoapods [options]
67
+
68
+ OPTIONS
67
69
  BANNER
68
70
 
69
- options.on('--[no-]verbose', 'Run verbosely') do |v|
71
+ options.on('--[no-]verbose', 'Show verbose debugging output') do |v|
70
72
  parsedOptions[:verbose] = v
71
73
  end
72
- options.on('-p', '--path path', '(Optional) Path to CocoaPods project directory, current directory if missing') do |path|
74
+ options.on('-h', '--help', 'Show help message') do
75
+ puts options
76
+ exit
77
+ end
78
+
79
+ options.separator("\n BOM Generation")
80
+ options.on('-p', '--path path', 'Path to CocoaPods project directory (default: current directory)') do |path|
73
81
  parsedOptions[:path] = path
74
82
  end
75
- options.on('-o', '--output bom_file_path', '(Optional) Path to output the bom.xml file to') do |bom_file_path|
83
+ options.on('-o', '--output bom_file_path', 'Path to output the bom.xml file to (default: "bom.xml")') do |bom_file_path|
76
84
  parsedOptions[:bom_file_path] = bom_file_path
77
85
  end
78
- options.on('-b', '--bom-version bom_version', Integer, '(Optional) Version of the generated BOM, 1 if not provided') do |version|
86
+ options.on('-b', '--bom-version bom_version', Integer, 'Version of the generated BOM (default: "1")') do |version|
79
87
  parsedOptions[:bom_version] = version
80
88
  end
81
- options.on('-g', '--group group', '(Optional) Group of the component for which the BOM is generated') do |group|
82
- parsedOptions[:group] = group
89
+ options.on('-x', '--exclude-test-targets', 'Eliminate Podfile targets whose name contains the word "test"') do |exclude|
90
+ parsedOptions[:exclude_test_targets] = exclude
83
91
  end
84
- options.on('-n', '--name name', '(Optional, if specified version and type are also required) Name of the component for which the BOM is generated') do |name|
92
+
93
+ options.separator("\n Component Metadata\n")
94
+ options.on('-n', '--name name', '(If specified version and type are also required) Name of the component for which the BOM is generated') do |name|
85
95
  parsedOptions[:name] = name
86
96
  end
87
- options.on('-v', '--version version', '(Optional) Version of the component for which the BOM is generated') do |version|
97
+ options.on('-v', '--version version', 'Version of the component for which the BOM is generated') do |version|
88
98
  begin
89
99
  Gem::Version.new(version)
90
100
  parsedOptions[:version] = version
@@ -92,13 +102,12 @@ module CycloneDX
92
102
  raise OptionParser::InvalidArgument, e.message
93
103
  end
94
104
  end
95
- options.on('-t', '--type type', "(Optional) Type of the component for which the BOM is generated (one of #{component_types.join('|')})") do |type|
105
+ options.on('-t', '--type type', "Type of the component for which the BOM is generated (one of #{component_types.join('|')})") do |type|
96
106
  raise OptionParser::InvalidArgument, "Invalid value for component's type (#{type}). It must be one of #{component_types.join('|')}" unless component_types.include?(type)
97
107
  parsedOptions[:type] = type
98
108
  end
99
- options.on_tail('-h', '--help', 'Show help message') do
100
- puts options
101
- exit
109
+ options.on('-g', '--group group', 'Group of the component for which the BOM is generated') do |group|
110
+ parsedOptions[:group] = group
102
111
  end
103
112
  end.parse!
104
113
 
@@ -118,90 +127,6 @@ module CycloneDX
118
127
  end
119
128
 
120
129
 
121
- def ensure_podfile_and_lock_are_present(options)
122
- project_dir = Pathname.new(options[:path] || Dir.pwd)
123
- raise PodfileParsingError, "#{options[:path]} is not a valid directory." unless File.directory?(project_dir)
124
- options[:podfile_path] = project_dir + 'Podfile'
125
- raise PodfileParsingError, "Missing Podfile in #{project_dir}. Please use the --path option if not running from the CocoaPods project directory." unless File.exist?(options[:podfile_path])
126
- options[:podfile_lock_path] = project_dir + 'Podfile.lock'
127
- raise PodfileParsingError, "Missing Podfile.lock, please run 'pod install' before generating BOM" unless File.exist?(options[:podfile_lock_path])
128
-
129
- initialize_cocoapods_config(project_dir)
130
-
131
- lockfile = ::Pod::Lockfile.from_file(options[:podfile_lock_path])
132
- verify_synced_sandbox(lockfile)
133
-
134
- return ::Pod::Podfile.from_file(options[:podfile_path]), lockfile
135
- end
136
-
137
-
138
- def initialize_cocoapods_config(project_dir)
139
- ::Pod::Config.instance.installation_root = project_dir
140
- end
141
-
142
-
143
- def verify_synced_sandbox(lockfile)
144
- manifestFile = ::Pod::Config.instance.sandbox.manifest
145
- raise PodfileParsingError, "Missing Manifest.lock, please run 'pod install' before generating BOM" if manifestFile.nil?
146
- raise PodfileParsingError, "The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation." unless lockfile == manifestFile
147
- end
148
-
149
-
150
- def cocoapods_repository_source(podfile, lockfile, pod_name)
151
- @source_manager ||= create_source_manager(podfile)
152
- return Source::CocoaPodsRepository.searchable_source(url: lockfile.spec_repo(pod_name), source_manager: @source_manager)
153
- end
154
-
155
-
156
- def git_source(lockfile, pod_name)
157
- checkout_options = lockfile.checkout_options_for_pod_named(pod_name)
158
- url = checkout_options[:git]
159
- [:tag, :branch, :commit].each do |type|
160
- return Source::GitRepository.new(url: url, type: type, label: checkout_options[type]) if checkout_options[type]
161
- end
162
- return Source::GitRepository.new(url: url)
163
- end
164
-
165
-
166
- def source_for_pod(podfile, lockfile, pod_name)
167
- root_name = pod_name.split('/').first
168
- return cocoapods_repository_source(podfile, lockfile, root_name) unless lockfile.spec_repo(root_name).nil?
169
- return git_source(lockfile, root_name) unless lockfile.checkout_options_for_pod_named(root_name).nil?
170
- return Source::LocalPod.new(path: lockfile.to_hash['EXTERNAL SOURCES'][root_name][:path]) if lockfile.to_hash['EXTERNAL SOURCES'][root_name][:path]
171
- return Source::Podspec.new(url: lockfile.to_hash['EXTERNAL SOURCES'][root_name][:podspec]) if lockfile.to_hash['EXTERNAL SOURCES'][root_name][:podspec]
172
- return nil
173
- end
174
-
175
-
176
- def parse_pods(podfile, lockfile)
177
- @logger.debug "Parsing pods from #{podfile.defined_in_file}"
178
- return lockfile.pod_names.map do |name|
179
- Pod.new(name: name, version: lockfile.version(name), source: source_for_pod(podfile, lockfile, name), checksum: lockfile.checksum(name))
180
- end
181
- end
182
-
183
-
184
- def create_source_manager(podfile)
185
- sourceManager = ::Pod::Source::Manager.new(::Pod::Config::instance.repos_dir)
186
- @logger.debug "Parsing sources from #{podfile.defined_in_file}"
187
- podfile.sources.each do |source|
188
- @logger.debug "Ensuring #{source} is available for searches"
189
- sourceManager.find_or_create_source_with_url(source)
190
- end
191
- @logger.debug "Source manager successfully created with all needed sources"
192
- return sourceManager
193
- end
194
-
195
-
196
- def populate_pods_with_additional_info(pods)
197
- pods.each do |pod|
198
- @logger.debug "Completing information for #{pod.name}"
199
- pod.complete_information_from_source
200
- end
201
- return pods
202
- end
203
-
204
-
205
130
  def write_bom_to_file(bom:, options:)
206
131
  bom_file_path = Pathname.new(options[:bom_file_path] || './bom.xml').expand_path
207
132
  bom_dir = bom_file_path.dirname
@@ -33,11 +33,11 @@ module CycloneDX
33
33
 
34
34
  def attributes_for(pod:)
35
35
  specification_sets = @source_manager.search_by_name("^#{Regexp.escape(pod.root_name)}$")
36
- raise SearchError, "No pod found named #{pod.name}" if specification_sets.length == 0
37
- raise SearchError, "More than one pod found named #{pod.name}" if specification_sets.length > 1
36
+ raise SearchError, "No pod found named #{pod.name}; run 'pod repo update' and try again" if specification_sets.length == 0
37
+ 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
38
38
 
39
39
  paths = specification_sets[0].specification_paths_for_version(pod.version)
40
- raise SearchError, "Version #{pod.version} not found for pod #{pod.name}" if paths.length == 0
40
+ raise SearchError, "Version #{pod.version} not found for pod #{pod.name}; run 'pod repo update' and try again" if paths.length == 0
41
41
 
42
42
  ::Pod::Specification.from_file(paths[0]).attributes_hash
43
43
  end
@@ -0,0 +1,184 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # This file is part of CycloneDX CocoaPods
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the “License”);
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an “AS IS” BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+ # SPDX-License-Identifier: Apache-2.0
18
+ # Copyright (c) OWASP Foundation. All Rights Reserved.
19
+ #
20
+
21
+ require 'cocoapods'
22
+ require 'logger'
23
+
24
+ require_relative 'pod'
25
+ require_relative 'pod_attributes'
26
+ require_relative 'source'
27
+
28
+ module CycloneDX
29
+ module CocoaPods
30
+ class PodfileParsingError < StandardError; end
31
+
32
+ class PodfileAnalyzer
33
+ def initialize(logger:, exclude_test_targets: false)
34
+ @logger = logger
35
+ @exclude_test_targets = exclude_test_targets
36
+ end
37
+
38
+ def ensure_podfile_and_lock_are_present(options)
39
+ project_dir = Pathname.new(options[:path] || Dir.pwd)
40
+ raise PodfileParsingError, "#{options[:path]} is not a valid directory." unless File.directory?(project_dir)
41
+ options[:podfile_path] = project_dir + 'Podfile'
42
+ raise PodfileParsingError, "Missing Podfile in #{project_dir}. Please use the --path option if not running from the CocoaPods project directory." unless File.exist?(options[:podfile_path])
43
+ options[:podfile_lock_path] = project_dir + 'Podfile.lock'
44
+ raise PodfileParsingError, "Missing Podfile.lock, please run 'pod install' before generating BOM" unless File.exist?(options[:podfile_lock_path])
45
+
46
+ initialize_cocoapods_config(project_dir)
47
+
48
+ lockfile = ::Pod::Lockfile.from_file(options[:podfile_lock_path])
49
+ verify_synced_sandbox(lockfile)
50
+
51
+ return ::Pod::Podfile.from_file(options[:podfile_path]), lockfile
52
+ end
53
+
54
+
55
+ def parse_pods(podfile, lockfile)
56
+ @logger.debug "Parsing pods from #{podfile.defined_in_file}"
57
+ included_pods = create_list_of_included_pods(podfile, lockfile)
58
+ return lockfile.pod_names.select { |name| included_pods.include?(name) }.map do |name|
59
+ Pod.new(name: name, version: lockfile.version(name), source: source_for_pod(podfile, lockfile, name), checksum: lockfile.checksum(name))
60
+ end
61
+ end
62
+
63
+
64
+ def populate_pods_with_additional_info(pods)
65
+ pods.each do |pod|
66
+ @logger.debug "Completing information for #{pod.name}"
67
+ pod.complete_information_from_source
68
+ end
69
+ return pods
70
+ end
71
+
72
+
73
+ private
74
+
75
+
76
+ def initialize_cocoapods_config(project_dir)
77
+ ::Pod::Config.instance.installation_root = project_dir
78
+ end
79
+
80
+
81
+ def verify_synced_sandbox(lockfile)
82
+ manifestFile = ::Pod::Config.instance.sandbox.manifest
83
+ raise PodfileParsingError, "Missing Manifest.lock, please run 'pod install' before generating BOM" if manifestFile.nil?
84
+ raise PodfileParsingError, "The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation." unless lockfile == manifestFile
85
+ end
86
+
87
+ def simple_hash_of_lockfile_pods(lockfile)
88
+ pods_hash = { }
89
+
90
+ pods_used = lockfile.internal_data['PODS']
91
+ pods_used&.each { |pod|
92
+ if pod.is_a?(String)
93
+ # Pods stored as String have no dependencies
94
+ pod_name = pod.split.first
95
+ pods_hash[pod_name] = []
96
+ else
97
+ # Pods stored as a hash have pod name and dependencies.
98
+ pod.each { |pod, dependencies|
99
+ pod_name = pod.split.first
100
+ pods_hash[pod_name] = dependencies.map { |d| d.split.first }
101
+ }
102
+ end
103
+ }
104
+ pods_hash
105
+ end
106
+
107
+ def append_all_pod_dependencies(pods_used, pods_cache)
108
+ result = pods_used
109
+ original_number = 0
110
+ # Loop adding pod dependencies until we are not adding any more dependencies to the result
111
+ # This brings in all the transitive dependencies of every top level pod.
112
+ # Note this also handles two edge cases:
113
+ # 1. Having a Podfile with no pods used.
114
+ # 2. Having a pod that has a platform-specific dependency that is unused for this Podfile.
115
+ while result.length != original_number
116
+ original_number = result.length
117
+ pods_used.each { |pod_name|
118
+ result.push(*pods_cache[pod_name]) unless !pods_cache.key?(pod_name) || pods_cache[pod_name].empty?
119
+ }
120
+ result = result.uniq
121
+ pods_used = result
122
+ end
123
+ result
124
+ end
125
+
126
+ def create_list_of_included_pods(podfile, lockfile)
127
+ pods_cache = simple_hash_of_lockfile_pods(lockfile)
128
+
129
+ includedTargets = podfile.target_definition_list.select{ |target| include_target_named(target.label) }
130
+ includedTargetNames = includedTargets.map { |target| target.label }
131
+ @logger.debug "Including all pods for targets: #{includedTargetNames}"
132
+
133
+ topLevelDeps = includedTargets.map(&:dependencies).flatten.uniq
134
+ pods_used = topLevelDeps.map(&:name).uniq
135
+ pods_used = append_all_pod_dependencies(pods_used, pods_cache)
136
+
137
+ return pods_used.sort
138
+ end
139
+
140
+
141
+ def include_target_named(targetname)
142
+ !@exclude_test_targets || !targetname.downcase.include?('test')
143
+ end
144
+
145
+
146
+ def cocoapods_repository_source(podfile, lockfile, pod_name)
147
+ @source_manager ||= create_source_manager(podfile)
148
+ return Source::CocoaPodsRepository.searchable_source(url: lockfile.spec_repo(pod_name), source_manager: @source_manager)
149
+ end
150
+
151
+
152
+ def git_source(lockfile, pod_name)
153
+ checkout_options = lockfile.checkout_options_for_pod_named(pod_name)
154
+ url = checkout_options[:git]
155
+ [:tag, :branch, :commit].each do |type|
156
+ return Source::GitRepository.new(url: url, type: type, label: checkout_options[type]) if checkout_options[type]
157
+ end
158
+ return Source::GitRepository.new(url: url)
159
+ end
160
+
161
+
162
+ def source_for_pod(podfile, lockfile, pod_name)
163
+ root_name = pod_name.split('/').first
164
+ return cocoapods_repository_source(podfile, lockfile, root_name) unless lockfile.spec_repo(root_name).nil?
165
+ return git_source(lockfile, root_name) unless lockfile.checkout_options_for_pod_named(root_name).nil?
166
+ return Source::LocalPod.new(path: lockfile.to_hash['EXTERNAL SOURCES'][root_name][:path]) if lockfile.to_hash['EXTERNAL SOURCES'][root_name][:path]
167
+ return Source::Podspec.new(url: lockfile.to_hash['EXTERNAL SOURCES'][root_name][:podspec]) if lockfile.to_hash['EXTERNAL SOURCES'][root_name][:podspec]
168
+ return nil
169
+ end
170
+
171
+
172
+ def create_source_manager(podfile)
173
+ sourceManager = ::Pod::Source::Manager.new(::Pod::Config::instance.repos_dir)
174
+ @logger.debug "Parsing sources from #{podfile.defined_in_file}"
175
+ podfile.sources.each do |source|
176
+ @logger.debug "Ensuring #{source} is available for searches"
177
+ sourceManager.find_or_create_source_with_url(source)
178
+ end
179
+ @logger.debug "Source manager successfully created with all needed sources"
180
+ return sourceManager
181
+ end
182
+ end
183
+ end
184
+ end
@@ -20,7 +20,7 @@
20
20
 
21
21
  module CycloneDX
22
22
  module CocoaPods
23
- VERSION = '1.0.0'
23
+ VERSION = '1.1.1'
24
24
  DEPENDENCIES = {
25
25
  cocoapods: '~> 1.10.1',
26
26
  nokogiri: '~> 1.11.2'
metadata CHANGED
@@ -1,14 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cyclonedx-cocoapods
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - José González
8
+ - Kyle Hammond
8
9
  autorequire:
9
10
  bindir: exe
10
11
  cert_chain: []
11
- date: 2022-08-12 00:00:00.000000000 Z
12
+ date: 2022-10-12 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: cocoapods
@@ -85,6 +86,7 @@ description: CycloneDX is a lightweight software bill-of-material (SBOM) specifi
85
86
  This Gem generates CycloneDX BOMs from CocoaPods projects.
86
87
  email:
87
88
  - jose.gonzalez@openinput.com
89
+ - kyle.hammond@jamf.com
88
90
  executables:
89
91
  - cyclonedx-cocoapods
90
92
  extensions: []
@@ -101,6 +103,7 @@ files:
101
103
  - lib/cyclonedx/cocoapods/license.rb
102
104
  - lib/cyclonedx/cocoapods/pod.rb
103
105
  - lib/cyclonedx/cocoapods/pod_attributes.rb
106
+ - lib/cyclonedx/cocoapods/podfile_analyzer.rb
104
107
  - lib/cyclonedx/cocoapods/source.rb
105
108
  - lib/cyclonedx/cocoapods/spdx-licenses.json
106
109
  - lib/cyclonedx/cocoapods/version.rb