cyclonedx-cocoapods 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +23 -11
- data/lib/cyclonedx/cocoapods/cli_runner.rb +34 -109
- data/lib/cyclonedx/cocoapods/podfile_analyzer.rb +182 -0
- data/lib/cyclonedx/cocoapods/version.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a3c7ebcac0eb8ea04cf5b1aed4da3bdbe1cadc2acb33e1bc4ebec9f52ac9bad9
|
4
|
+
data.tar.gz: bdc83e96c9b4750bf2135a85b30d384ae2096e4c0591d3db2f65434506f4c220
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 94cdbbcb32c6d83dad78c383536dc484f08a040f5104318a3c2355b070fb915474e25027188bcaa8dfffc4222772525e4e051dfc8a1d673a08a31cd51f4d3cc2
|
7
|
+
data.tar.gz: 1c0da4d2d356eb06207f889605e3c65ea0594821b7de130ebe5ce3d182917f87415fdc615d727f54f540b5a3c9c2b58d915117627b7b71c7a115045e799bc0c4
|
data/CHANGELOG.md
CHANGED
@@ -4,6 +4,10 @@ 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.0]
|
8
|
+
|
9
|
+
- 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).
|
10
|
+
|
7
11
|
## [1.0.0]
|
8
12
|
|
9
13
|
### 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
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
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 '
|
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
|
-
|
45
|
-
|
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
|
-
|
66
|
-
|
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', '
|
71
|
+
options.on('--[no-]verbose', 'Show verbose debugging output') do |v|
|
70
72
|
parsedOptions[:verbose] = v
|
71
73
|
end
|
72
|
-
options.on('-
|
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', '
|
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, '
|
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('-
|
82
|
-
parsedOptions[:
|
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
|
-
|
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', '
|
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', "
|
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.
|
100
|
-
|
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
|
@@ -0,0 +1,182 @@
|
|
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 the edge case of having a Podfile with no pods used.
|
113
|
+
while result.length != original_number
|
114
|
+
original_number = result.length
|
115
|
+
pods_used.each { |pod_name|
|
116
|
+
result.push(*pods_cache[pod_name]) unless pods_cache[pod_name].empty?
|
117
|
+
}
|
118
|
+
result = result.uniq
|
119
|
+
pods_used = result
|
120
|
+
end
|
121
|
+
result
|
122
|
+
end
|
123
|
+
|
124
|
+
def create_list_of_included_pods(podfile, lockfile)
|
125
|
+
pods_cache = simple_hash_of_lockfile_pods(lockfile)
|
126
|
+
|
127
|
+
includedTargets = podfile.target_definition_list.select{ |target| include_target_named(target.label) }
|
128
|
+
includedTargetNames = includedTargets.map { |target| target.label }
|
129
|
+
@logger.debug "Including all pods for targets: #{includedTargetNames}"
|
130
|
+
|
131
|
+
topLevelDeps = includedTargets.map(&:dependencies).flatten.uniq
|
132
|
+
pods_used = topLevelDeps.map(&:name).uniq
|
133
|
+
pods_used = append_all_pod_dependencies(pods_used, pods_cache)
|
134
|
+
|
135
|
+
return pods_used.sort
|
136
|
+
end
|
137
|
+
|
138
|
+
|
139
|
+
def include_target_named(targetname)
|
140
|
+
!@exclude_test_targets || !targetname.downcase.include?('test')
|
141
|
+
end
|
142
|
+
|
143
|
+
|
144
|
+
def cocoapods_repository_source(podfile, lockfile, pod_name)
|
145
|
+
@source_manager ||= create_source_manager(podfile)
|
146
|
+
return Source::CocoaPodsRepository.searchable_source(url: lockfile.spec_repo(pod_name), source_manager: @source_manager)
|
147
|
+
end
|
148
|
+
|
149
|
+
|
150
|
+
def git_source(lockfile, pod_name)
|
151
|
+
checkout_options = lockfile.checkout_options_for_pod_named(pod_name)
|
152
|
+
url = checkout_options[:git]
|
153
|
+
[:tag, :branch, :commit].each do |type|
|
154
|
+
return Source::GitRepository.new(url: url, type: type, label: checkout_options[type]) if checkout_options[type]
|
155
|
+
end
|
156
|
+
return Source::GitRepository.new(url: url)
|
157
|
+
end
|
158
|
+
|
159
|
+
|
160
|
+
def source_for_pod(podfile, lockfile, pod_name)
|
161
|
+
root_name = pod_name.split('/').first
|
162
|
+
return cocoapods_repository_source(podfile, lockfile, root_name) unless lockfile.spec_repo(root_name).nil?
|
163
|
+
return git_source(lockfile, root_name) unless lockfile.checkout_options_for_pod_named(root_name).nil?
|
164
|
+
return Source::LocalPod.new(path: lockfile.to_hash['EXTERNAL SOURCES'][root_name][:path]) if lockfile.to_hash['EXTERNAL SOURCES'][root_name][:path]
|
165
|
+
return Source::Podspec.new(url: lockfile.to_hash['EXTERNAL SOURCES'][root_name][:podspec]) if lockfile.to_hash['EXTERNAL SOURCES'][root_name][:podspec]
|
166
|
+
return nil
|
167
|
+
end
|
168
|
+
|
169
|
+
|
170
|
+
def create_source_manager(podfile)
|
171
|
+
sourceManager = ::Pod::Source::Manager.new(::Pod::Config::instance.repos_dir)
|
172
|
+
@logger.debug "Parsing sources from #{podfile.defined_in_file}"
|
173
|
+
podfile.sources.each do |source|
|
174
|
+
@logger.debug "Ensuring #{source} is available for searches"
|
175
|
+
sourceManager.find_or_create_source_with_url(source)
|
176
|
+
end
|
177
|
+
@logger.debug "Source manager successfully created with all needed sources"
|
178
|
+
return sourceManager
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
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.
|
4
|
+
version: 1.1.0
|
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-
|
12
|
+
date: 2022-09-13 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
|