cyclonedx-cocoapods 1.1.0 → 1.1.2

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: a3c7ebcac0eb8ea04cf5b1aed4da3bdbe1cadc2acb33e1bc4ebec9f52ac9bad9
4
- data.tar.gz: bdc83e96c9b4750bf2135a85b30d384ae2096e4c0591d3db2f65434506f4c220
3
+ metadata.gz: d9413e8c99e608e82f87b4075e907eb9fd137fd9f67a2c00bb277cf5c7fc2e21
4
+ data.tar.gz: fd8be60d19ee1e2d84f53bbc16e66734eaffb9b2375f462219bd097fbdb7ef1c
5
5
  SHA512:
6
- metadata.gz: 94cdbbcb32c6d83dad78c383536dc484f08a040f5104318a3c2355b070fb915474e25027188bcaa8dfffc4222772525e4e051dfc8a1d673a08a31cd51f4d3cc2
7
- data.tar.gz: 1c0da4d2d356eb06207f889605e3c65ea0594821b7de130ebe5ce3d182917f87415fdc615d727f54f540b5a3c9c2b58d915117627b7b71c7a115045e799bc0c4
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'.freeze
30
- CDN_REPOSITORY = 'trunk'.freeze
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'.freeze
58
- HOMEPAGE_REFERENCE_TYPE = 'website'.freeze
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'.freeze
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,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  #
3
4
  # This file is part of CycloneDX CocoaPods
4
5
  #
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  #
2
4
  # This file is part of CycloneDX CocoaPods
3
5
  #
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  #
2
4
  # This file is part of CycloneDX CocoaPods
3
5
  #
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  #
2
4
  # This file is part of CycloneDX CocoaPods
3
5
  #
@@ -105,4 +107,4 @@ module CycloneDX
105
107
  end
106
108
  end
107
109
  end
108
- end
110
+ 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.each { |pod|
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 the edge case of having a Podfile with no pods used.
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,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  #
2
4
  # This file is part of CycloneDX CocoaPods
3
5
  #
@@ -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.0'
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.0
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: 2022-09-13 00:00:00.000000000 Z
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