cyclonedx-cocoapods 1.1.0 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +20 -0
- data/README.md +35 -0
- data/lib/cyclonedx/cocoapods/bom_builder.rb +8 -6
- data/lib/cyclonedx/cocoapods/cli_runner.rb +1 -0
- data/lib/cyclonedx/cocoapods/component.rb +2 -0
- data/lib/cyclonedx/cocoapods/license.rb +2 -0
- data/lib/cyclonedx/cocoapods/pod.rb +3 -1
- data/lib/cyclonedx/cocoapods/pod_attributes.rb +5 -3
- data/lib/cyclonedx/cocoapods/podfile_analyzer.rb +26 -4
- data/lib/cyclonedx/cocoapods/source.rb +2 -0
- data/lib/cyclonedx/cocoapods/version.rb +2 -5
- metadata +18 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d9413e8c99e608e82f87b4075e907eb9fd137fd9f67a2c00bb277cf5c7fc2e21
|
4
|
+
data.tar.gz: fd8be60d19ee1e2d84f53bbc16e66734eaffb9b2375f462219bd097fbdb7ef1c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8b1e44bed24cddcce4e550047b39c849167f60d4e3ac86006365a991e70de3de3634a9de0ef90df7e7a3f93a9c255b5df271526a3731b91739726cc400c23889
|
7
|
+
data.tar.gz: f8778db86758639e8c2888a0ccd67d9209d8dac2282e422d75c18a40831c3e89a8c0cac10d8392965b8a47c01341b197dc424912470bc300e06c355e76d76415
|
data/CHANGELOG.md
CHANGED
@@ -4,8 +4,28 @@ 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.2]
|
8
|
+
|
9
|
+
### Changed
|
10
|
+
- Updated gem dependency for cocoapods to be minimum v1.10.1 up to anything less than v2. ([Issue #51](https://github.com/CycloneDX/cyclonedx-cocoapods/issues/51)) [@macblazer](https://github.com/macblazer).
|
11
|
+
- Updated gem dependency for nokogiri to be minimum v1.11.2 up to anything less than v2. [@macblazer](https://github.com/macblazer).
|
12
|
+
- Updated README.md with a description of what happens with pods or Podfiles that use subspecs. ([Issue #52](https://github.com/CycloneDX/cyclonedx-cocoapods/issues/52)) [@macblazer](https://github.com/macblazer).
|
13
|
+
|
14
|
+
### Fixed
|
15
|
+
- Fixed parsing of a Podfile that uses CocoaPods plugins. ([PR #55](https://github.com/CycloneDX/cyclonedx-cocoapods/pull/55)) [@DwayneCoussement](https://github.com/DwayneCoussement).
|
16
|
+
|
17
|
+
## [1.1.1]
|
18
|
+
|
19
|
+
### Changed
|
20
|
+
- 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).
|
21
|
+
|
22
|
+
### Fixed
|
23
|
+
- 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).
|
24
|
+
- Analyzing a Podfile that has no pods defined in it no longer causes a crash [@macblazer](https://github.com/macblazer).
|
25
|
+
|
7
26
|
## [1.1.0]
|
8
27
|
|
28
|
+
### Added
|
9
29
|
- 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
30
|
|
11
31
|
## [1.0.0]
|
data/README.md
CHANGED
@@ -80,6 +80,41 @@ then these two commands were run in the checked out code directory.
|
|
80
80
|
% cyclonedx-cocoapods -n "kizitonwose/PodsUpdater" -v 1.0.3 -t application --output example_bom.xml
|
81
81
|
```
|
82
82
|
|
83
|
+
### A Note About CocoaPod Subspecs
|
84
|
+
|
85
|
+
Many CocoaPods make use of [subspec functionality](https://guides.cocoapods.org/syntax/podspec.html#subspec).
|
86
|
+
Podfiles can require whole pods, or just subspecs; pods themselves may require whole pods or subspecs of other
|
87
|
+
pods. In complex projects such as React Native apps this often results in a single pod being included as a
|
88
|
+
dependency multiple times as several of its subspecs are included individually.
|
89
|
+
|
90
|
+
*cyclonedx-cocoapods* works properly with this, and adds a dependency in the BOM output for each subspec that is
|
91
|
+
required by the Podfile and throughout the chain of dependencies. Each subspec will only appear once in the BOM
|
92
|
+
file. This gives you granular detail in the BOM of which subspecs of which pods are used. This is easiest seen
|
93
|
+
with an example.
|
94
|
+
|
95
|
+
The Podfile
|
96
|
+
```ruby
|
97
|
+
target 'SampleProject' do
|
98
|
+
pod 'SamplePod/firstsubspec'
|
99
|
+
pod 'SamplePod/secondsubspec'
|
100
|
+
end
|
101
|
+
```
|
102
|
+
|
103
|
+
If the SamplePod is at v2.1, running *cyclonedx-cocoapods* on this will output a BOM file with two `component`
|
104
|
+
dependencies:
|
105
|
+
- `pkg:cocoapods/SamplePod@2.1#firstsubspec` at `https://github.com/example/SamplePod`
|
106
|
+
- `pkg:cocoapods/SamplePod@2.1#secondsubspec` at `https://github.com/example/SamplePod`
|
107
|
+
|
108
|
+
[Dependency Track](https://dependencytrack.org) (DT) is a tool that many organizations use to help automate SBOM
|
109
|
+
related tasks. When uploading an SBOM that contains multiple subspecs from the same pod, or a single subspec
|
110
|
+
alongside the complete pod dependency, the initial upload will indicate a number of dependencies equal to the number
|
111
|
+
of `component` objects within the BOM. However, DT analysis then looks for unique repositories in use which will
|
112
|
+
merge all of the subspecs of a particular pod into a single entry. On later uploads to DT of the same or similar BOM
|
113
|
+
it will indicate just the number of unique repositories.
|
114
|
+
|
115
|
+
Uploading the above SamplePod BOM file to DT will initially see two dependencies. Later analysis by DT notices
|
116
|
+
that both dependencies resolve to the same repository, so DT will then only show a single dependency.
|
117
|
+
|
83
118
|
## Contributing
|
84
119
|
|
85
120
|
To set up for local development, make a fork of this repo, make a branch on your fork named after the issue or workflow you are improving, checkout your branch, then run `bundle install`.
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
#
|
2
4
|
# This file is part of CycloneDX CocoaPods
|
3
5
|
#
|
@@ -26,8 +28,8 @@ module CycloneDX
|
|
26
28
|
module CocoaPods
|
27
29
|
module Source
|
28
30
|
class CocoaPodsRepository
|
29
|
-
LEGACY_REPOSITORY = 'https://github.com/CocoaPods/Specs.git'
|
30
|
-
CDN_REPOSITORY = 'trunk'
|
31
|
+
LEGACY_REPOSITORY = 'https://github.com/CocoaPods/Specs.git'
|
32
|
+
CDN_REPOSITORY = 'trunk'
|
31
33
|
|
32
34
|
def source_qualifier
|
33
35
|
url == LEGACY_REPOSITORY || url == CDN_REPOSITORY ? {} : { repository_url: url }
|
@@ -54,8 +56,8 @@ module CycloneDX
|
|
54
56
|
end
|
55
57
|
|
56
58
|
class Pod
|
57
|
-
CHECKSUM_ALGORITHM = 'SHA-1'
|
58
|
-
HOMEPAGE_REFERENCE_TYPE = 'website'
|
59
|
+
CHECKSUM_ALGORITHM = 'SHA-1'
|
60
|
+
HOMEPAGE_REFERENCE_TYPE = 'website'
|
59
61
|
|
60
62
|
def purl
|
61
63
|
purl_name = CGI.escape(name.split('/').first)
|
@@ -115,7 +117,7 @@ module CycloneDX
|
|
115
117
|
end
|
116
118
|
|
117
119
|
class BOMBuilder
|
118
|
-
NAMESPACE = 'http://cyclonedx.org/schema/bom/1.4'
|
120
|
+
NAMESPACE = 'http://cyclonedx.org/schema/bom/1.4'
|
119
121
|
|
120
122
|
attr_reader :component, :pods
|
121
123
|
|
@@ -155,4 +157,4 @@ module CycloneDX
|
|
155
157
|
end
|
156
158
|
end
|
157
159
|
end
|
158
|
-
end
|
160
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
#
|
2
4
|
# This file is part of CycloneDX CocoaPods
|
3
5
|
#
|
@@ -33,11 +35,11 @@ module CycloneDX
|
|
33
35
|
|
34
36
|
def attributes_for(pod:)
|
35
37
|
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
|
38
|
+
raise SearchError, "No pod found named #{pod.name}; run 'pod repo update' and try again" if specification_sets.length == 0
|
39
|
+
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
40
|
|
39
41
|
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
|
42
|
+
raise SearchError, "Version #{pod.version} not found for pod #{pod.name}; run 'pod repo update' and try again" if paths.length == 0
|
41
43
|
|
42
44
|
::Pod::Specification.from_file(paths[0]).attributes_hash
|
43
45
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
#
|
3
4
|
# This file is part of CycloneDX CocoaPods
|
4
5
|
#
|
@@ -19,6 +20,7 @@
|
|
19
20
|
#
|
20
21
|
|
21
22
|
require 'cocoapods'
|
23
|
+
require 'cocoapods-core'
|
22
24
|
require 'logger'
|
23
25
|
|
24
26
|
require_relative 'pod'
|
@@ -35,6 +37,23 @@ module CycloneDX
|
|
35
37
|
@exclude_test_targets = exclude_test_targets
|
36
38
|
end
|
37
39
|
|
40
|
+
def load_plugins(podfile_path)
|
41
|
+
podfile_contents = File.read(podfile_path)
|
42
|
+
plugin_syntax = /\s*plugin\s+['"]([^'"]+)['"]/
|
43
|
+
plugin_names = podfile_contents.scan(plugin_syntax).flatten
|
44
|
+
|
45
|
+
plugin_names.each do |plugin_name|
|
46
|
+
@logger.debug("Loading plugin #{plugin_name}")
|
47
|
+
begin
|
48
|
+
plugin_spec = Gem::Specification.find_by_name(plugin_name)
|
49
|
+
plugin_spec.activate if plugin_spec
|
50
|
+
load(plugin_spec.gem_dir + '/lib/cocoapods_plugin.rb') if plugin_spec
|
51
|
+
rescue Gem::LoadError => e
|
52
|
+
@logger.warn("Failed to load plugin #{plugin_name}. #{e.message}")
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
38
57
|
def ensure_podfile_and_lock_are_present(options)
|
39
58
|
project_dir = Pathname.new(options[:path] || Dir.pwd)
|
40
59
|
raise PodfileParsingError, "#{options[:path]} is not a valid directory." unless File.directory?(project_dir)
|
@@ -47,7 +66,8 @@ module CycloneDX
|
|
47
66
|
|
48
67
|
lockfile = ::Pod::Lockfile.from_file(options[:podfile_lock_path])
|
49
68
|
verify_synced_sandbox(lockfile)
|
50
|
-
|
69
|
+
load_plugins(options[:podfile_path])
|
70
|
+
|
51
71
|
return ::Pod::Podfile.from_file(options[:podfile_path]), lockfile
|
52
72
|
end
|
53
73
|
|
@@ -88,7 +108,7 @@ module CycloneDX
|
|
88
108
|
pods_hash = { }
|
89
109
|
|
90
110
|
pods_used = lockfile.internal_data['PODS']
|
91
|
-
pods_used
|
111
|
+
pods_used&.each { |pod|
|
92
112
|
if pod.is_a?(String)
|
93
113
|
# Pods stored as String have no dependencies
|
94
114
|
pod_name = pod.split.first
|
@@ -109,11 +129,13 @@ module CycloneDX
|
|
109
129
|
original_number = 0
|
110
130
|
# Loop adding pod dependencies until we are not adding any more dependencies to the result
|
111
131
|
# This brings in all the transitive dependencies of every top level pod.
|
112
|
-
# Note this also handles
|
132
|
+
# Note this also handles two edge cases:
|
133
|
+
# 1. Having a Podfile with no pods used.
|
134
|
+
# 2. Having a pod that has a platform-specific dependency that is unused for this Podfile.
|
113
135
|
while result.length != original_number
|
114
136
|
original_number = result.length
|
115
137
|
pods_used.each { |pod_name|
|
116
|
-
result.push(*pods_cache[pod_name]) unless pods_cache[pod_name].empty?
|
138
|
+
result.push(*pods_cache[pod_name]) unless !pods_cache.key?(pod_name) || pods_cache[pod_name].empty?
|
117
139
|
}
|
118
140
|
result = result.uniq
|
119
141
|
pods_used = result
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
#
|
3
4
|
# This file is part of CycloneDX CocoaPods
|
4
5
|
#
|
@@ -20,10 +21,6 @@
|
|
20
21
|
|
21
22
|
module CycloneDX
|
22
23
|
module CocoaPods
|
23
|
-
VERSION = '1.1.
|
24
|
-
DEPENDENCIES = {
|
25
|
-
cocoapods: '~> 1.10.1',
|
26
|
-
nokogiri: '~> 1.11.2'
|
27
|
-
}
|
24
|
+
VERSION = '1.1.2'
|
28
25
|
end
|
29
26
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cyclonedx-cocoapods
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- José González
|
@@ -9,36 +9,48 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2023-06-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: cocoapods
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
requirements:
|
18
|
-
- - "
|
18
|
+
- - ">="
|
19
19
|
- !ruby/object:Gem::Version
|
20
20
|
version: 1.10.1
|
21
|
+
- - "<"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: '2.0'
|
21
24
|
type: :runtime
|
22
25
|
prerelease: false
|
23
26
|
version_requirements: !ruby/object:Gem::Requirement
|
24
27
|
requirements:
|
25
|
-
- - "
|
28
|
+
- - ">="
|
26
29
|
- !ruby/object:Gem::Version
|
27
30
|
version: 1.10.1
|
31
|
+
- - "<"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.0'
|
28
34
|
- !ruby/object:Gem::Dependency
|
29
35
|
name: nokogiri
|
30
36
|
requirement: !ruby/object:Gem::Requirement
|
31
37
|
requirements:
|
32
|
-
- - "
|
38
|
+
- - ">="
|
33
39
|
- !ruby/object:Gem::Version
|
34
40
|
version: 1.11.2
|
41
|
+
- - "<"
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '2.0'
|
35
44
|
type: :runtime
|
36
45
|
prerelease: false
|
37
46
|
version_requirements: !ruby/object:Gem::Requirement
|
38
47
|
requirements:
|
39
|
-
- - "
|
48
|
+
- - ">="
|
40
49
|
- !ruby/object:Gem::Version
|
41
50
|
version: 1.11.2
|
51
|
+
- - "<"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '2.0'
|
42
54
|
- !ruby/object:Gem::Dependency
|
43
55
|
name: rake
|
44
56
|
requirement: !ruby/object:Gem::Requirement
|