cocoapods-dykit 0.5.2 → 0.5.3

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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/lib/pod/command.rb +2 -0
  3. data/lib/pod/command/dyinstall.rb +51 -0
  4. data/lib/pod/command/dyupdate.rb +106 -0
  5. data/lib/pod/command/fmwk.rb +4 -0
  6. data/lib/pod/command/lib/dylint.rb +1 -0
  7. data/lib/pod/gem_version.rb +1 -1
  8. data/lib/pod/installer.rb +715 -0
  9. data/lib/pod/installer/analyzer.rb +934 -0
  10. data/lib/pod/installer/analyzer/analysis_result.rb +57 -0
  11. data/lib/pod/installer/analyzer/locking_dependency_analyzer.rb +95 -0
  12. data/lib/pod/installer/analyzer/pod_variant.rb +68 -0
  13. data/lib/pod/installer/analyzer/pod_variant_set.rb +157 -0
  14. data/lib/pod/installer/analyzer/podfile_dependency_cache.rb +54 -0
  15. data/lib/pod/installer/analyzer/sandbox_analyzer.rb +251 -0
  16. data/lib/pod/installer/analyzer/specs_state.rb +84 -0
  17. data/lib/pod/installer/analyzer/target_inspection_result.rb +45 -0
  18. data/lib/pod/installer/analyzer/target_inspector.rb +254 -0
  19. data/lib/pod/installer/installation_options.rb +158 -0
  20. data/lib/pod/installer/pod_source_installer.rb +214 -0
  21. data/lib/pod/installer/pod_source_preparer.rb +77 -0
  22. data/lib/pod/installer/podfile_validator.rb +139 -0
  23. data/lib/pod/installer/post_install_hooks_context.rb +107 -0
  24. data/lib/pod/installer/pre_install_hooks_context.rb +42 -0
  25. data/lib/pod/installer/source_provider_hooks_context.rb +32 -0
  26. data/lib/pod/installer/user_project_integrator.rb +253 -0
  27. data/lib/pod/installer/user_project_integrator/target_integrator.rb +462 -0
  28. data/lib/pod/installer/user_project_integrator/target_integrator/xcconfig_integrator.rb +146 -0
  29. data/lib/pod/installer/xcode.rb +8 -0
  30. data/lib/pod/installer/xcode/pods_project_generator.rb +353 -0
  31. data/lib/pod/installer/xcode/pods_project_generator/aggregate_target_installer.rb +172 -0
  32. data/lib/pod/installer/xcode/pods_project_generator/file_references_installer.rb +367 -0
  33. data/lib/pod/installer/xcode/pods_project_generator/pod_target_installer.rb +718 -0
  34. data/lib/pod/installer/xcode/pods_project_generator/pod_target_integrator.rb +111 -0
  35. data/lib/pod/installer/xcode/pods_project_generator/target_installer.rb +265 -0
  36. data/lib/pod/installer/xcode/target_validator.rb +141 -0
  37. data/lib/pod/resolver.rb +632 -0
  38. metadata +34 -2
@@ -0,0 +1,57 @@
1
+ module Pod
2
+ class DyInstaller
3
+ class Analyzer
4
+ class AnalysisResult
5
+ # @return [SpecsState] the states of the Podfile specs.
6
+ #
7
+ attr_accessor :podfile_state
8
+
9
+ # @return [Hash{TargetDefinition => Array<Specification>}] the
10
+ # specifications grouped by target.
11
+ #
12
+ attr_accessor :specs_by_target
13
+
14
+ # @return [Hash{Source => Array<Specification>}] the
15
+ # specifications grouped by spec repo source.
16
+ #
17
+ attr_accessor :specs_by_source
18
+
19
+ # @return [Array<Specification>] the specifications of the resolved
20
+ # version of Pods that should be installed.
21
+ #
22
+ attr_accessor :specifications
23
+
24
+ # @return [SpecsState] the states of the {Sandbox} respect the resolved
25
+ # specifications.
26
+ #
27
+ attr_accessor :sandbox_state
28
+
29
+ # @return [Array<AggregateTarget>] The aggregate targets created for each
30
+ # {TargetDefinition} from the {Podfile}.
31
+ #
32
+ attr_accessor :targets
33
+
34
+ # @return [Hash{TargetDefinition => Array<TargetInspectionResult>}] the
35
+ # results of inspecting the user targets
36
+ #
37
+ attr_accessor :target_inspections
38
+
39
+ # @return [PodfileDependencyCache] the cache of all dependencies in the
40
+ # podfile.
41
+ #
42
+ attr_accessor :podfile_dependency_cache
43
+
44
+ # @return [Hash{String=>Symbol}] A hash representing all the user build
45
+ # configurations across all integration targets. Each key
46
+ # corresponds to the name of a configuration and its value to
47
+ # its type (`:debug` or `:release`).
48
+ #
49
+ def all_user_build_configurations
50
+ targets.reduce({}) do |result, target|
51
+ result.merge(target.user_build_configurations)
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,95 @@
1
+ require 'molinillo/dependency_graph'
2
+
3
+ module Pod
4
+ class DyInstaller
5
+ class Analyzer
6
+ # Generates dependencies that require the specific version of the Pods
7
+ # that haven't changed in the {Lockfile}.
8
+ module LockingDependencyAnalyzer
9
+ # Generates dependencies that require the specific version of the Pods
10
+ # that haven't changed in the {Lockfile}.
11
+ #
12
+ # These dependencies are passed to the {Resolver}, unless the installer
13
+ # is in update mode, to prevent it from upgrading the Pods that weren't
14
+ # changed in the {Podfile}.
15
+ #
16
+ # @param [Lockfile] lockfile the lockfile containing dependency constraints
17
+ #
18
+ # @param [Array<String>] pods_to_update
19
+ # List of pod names which needs to be updated because installer is
20
+ # in update mode for these pods. Pods in this list and all their recursive dependencies
21
+ # will not be included in generated dependency graph
22
+ #
23
+ # @param [Array<String>] pods_to_unlock
24
+ # List of pod names whose version constraints will be removed from the generated dependency graph.
25
+ # Recursive dependencies of the pods won't be affected. This is currently used to force local pods
26
+ # to be evaluated again whenever checksum of the specification of the local pods changes.
27
+ #
28
+ # @return [Molinillo::DependencyGraph<Dependency>] the dependencies
29
+ # generated by the lockfile that prevent the resolver to update
30
+ # a Pod.
31
+ #
32
+ def self.generate_version_locking_dependencies(lockfile, pods_to_update, pods_to_unlock = [])
33
+ dependency_graph = Molinillo::DependencyGraph.new
34
+
35
+ if lockfile
36
+ explicit_dependencies = lockfile.dependencies
37
+ explicit_dependencies.each do |dependency|
38
+ dependency_graph.add_vertex(dependency.name, dependency, true)
39
+ end
40
+
41
+ pods = lockfile.to_hash['PODS'] || []
42
+ pods.each do |pod|
43
+ add_to_dependency_graph(pod, [], dependency_graph, pods_to_unlock)
44
+ end
45
+
46
+ pods_to_update = pods_to_update.flat_map do |u|
47
+ root_name = Specification.root_name(u).downcase
48
+ dependency_graph.vertices.each_key.select { |n| Specification.root_name(n).downcase == root_name }
49
+ end
50
+
51
+ pods_to_update.each do |u|
52
+ dependency_graph.detach_vertex_named(u)
53
+ end
54
+ end
55
+
56
+ dependency_graph
57
+ end
58
+
59
+ # Generates a completely 'unlocked' dependency graph.
60
+ #
61
+ # @return [Molinillo::DependencyGraph<Dependency>] an empty dependency
62
+ # graph
63
+ #
64
+ def self.unlocked_dependency_graph
65
+ Molinillo::DependencyGraph.new
66
+ end
67
+
68
+ private
69
+
70
+ def self.add_child_vertex_to_graph(dependency_string, parents, dependency_graph, pods_to_unlock)
71
+ dependency = Dependency.from_string(dependency_string)
72
+ if pods_to_unlock.include?(dependency.root_name)
73
+ dependency = Dependency.new(dependency.name)
74
+ end
75
+ vertex = dependency_graph.add_child_vertex(dependency.name, nil, parents, nil)
76
+ dependency = vertex.payload.merge(dependency) if vertex.payload
77
+ vertex.payload = dependency
78
+ dependency
79
+ end
80
+
81
+ def self.add_to_dependency_graph(object, parents, dependency_graph, pods_to_unlock)
82
+ case object
83
+ when String
84
+ add_child_vertex_to_graph(object, parents, dependency_graph, pods_to_unlock)
85
+ when Hash
86
+ object.each do |key, value|
87
+ dependency = add_child_vertex_to_graph(key, parents, dependency_graph, pods_to_unlock)
88
+ value.each { |v| add_to_dependency_graph(v, [dependency.name], dependency_graph, pods_to_unlock) }
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,68 @@
1
+ module Pod
2
+ class DyInstaller
3
+ class Analyzer
4
+ # Bundles the information needed to setup a {PodTarget}.
5
+ class PodVariant
6
+ # @return [Array<Specification>] the spec and subspecs for the target
7
+ #
8
+ attr_reader :specs
9
+
10
+ # @return [Array<Specification>] the test specs for the target
11
+ #
12
+ attr_reader :test_specs
13
+
14
+ # @return [Platform] the platform
15
+ #
16
+ attr_reader :platform
17
+
18
+ # @return [Bool] whether this pod should be built as framework
19
+ #
20
+ attr_reader :requires_frameworks
21
+ alias_method :requires_frameworks?, :requires_frameworks
22
+
23
+ # @return [Specification] the root specification
24
+ #
25
+ def root_spec
26
+ specs.first.root
27
+ end
28
+
29
+ # Initialize a new instance from its attributes.
30
+ #
31
+ # @param [Array<Specification>] specs @see #specs
32
+ # @param [Array<Specification>] test_specs @see #test_specs
33
+ # @param [Platform] platform @see #platform
34
+ # @param [Bool] requires_frameworks @see #requires_frameworks?
35
+ #
36
+ def initialize(specs, test_specs, platform, requires_frameworks = false)
37
+ @specs = specs
38
+ @test_specs = test_specs
39
+ @platform = platform
40
+ @requires_frameworks = requires_frameworks
41
+ end
42
+
43
+ # @note Test specs are intentionally not included as part of the equality for pod variants since a
44
+ # pod variant should not be affected by the number of test specs included.
45
+ #
46
+ # @return [Bool] whether the {PodVariant} is equal to another taking all
47
+ # all their attributes into account
48
+ #
49
+ def ==(other)
50
+ self.class == other.class &&
51
+ specs == other.specs &&
52
+ platform == other.platform &&
53
+ requires_frameworks == other.requires_frameworks
54
+ end
55
+ alias_method :eql?, :==
56
+
57
+ # Hashes the instance by all its attributes.
58
+ #
59
+ # This adds support to make instances usable as Hash keys.
60
+ #
61
+ # @!visibility private
62
+ def hash
63
+ [specs, platform, requires_frameworks].hash
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,157 @@
1
+ require 'set'
2
+
3
+ module Pod
4
+ class DyInstaller
5
+ class Analyzer
6
+ # Collects all {PodVariant}.
7
+ class PodVariantSet
8
+ # @return [Array<PodVariant>] the different variants within this set.
9
+ #
10
+ attr_reader :variants
11
+
12
+ # Initialize a new instance.
13
+ #
14
+ # @param [Array<PodVariant>] variants @see #variants
15
+ #
16
+ def initialize(variants)
17
+ @variants = variants
18
+ end
19
+
20
+ # Describes what makes each {PodVariant} distinct among the others.
21
+ #
22
+ # @return [Hash<PodVariant, String>]
23
+ #
24
+ def scope_suffixes
25
+ return { variants.first => nil } if variants.count == 1
26
+ Hash[scope_by_specs.map do |variant, scope|
27
+ require 'digest'
28
+ scope = Digest::MD5.hexdigest(scope)[0..7] if !scope.nil? && scope.length >= 50
29
+ [variant, scope]
30
+ end]
31
+ end
32
+
33
+ # Groups the collection by result of the block.
34
+ #
35
+ # @param [Block<Variant, #hash>] block
36
+ # @return [Array<PodVariantSet>]
37
+ #
38
+ def group_by(&block)
39
+ variants.group_by(&block).map { |_, v| PodVariantSet.new(v) }
40
+ end
41
+
42
+ # @private
43
+ #
44
+ # Prepends the given scoped {PodVariant}s with another scoping label, if there
45
+ # was more than one group of {PodVariant}s given.
46
+ #
47
+ # @param [Array<Hash<PodVariant, String>>] scoped_variants
48
+ # {PodVariant}s, which where grouped on base of a criteria, which is used
49
+ # in the block argument to generate a descriptive label.
50
+ #
51
+ # @param [Block<PodVariant, String>] block
52
+ # takes a {PodVariant} and returns a scope suffix which is prepended, if
53
+ # necessary.
54
+ #
55
+ # @return [Hash<PodVariant, String>]
56
+ #
57
+ def scope_if_necessary(scoped_variants, &block)
58
+ if scoped_variants.count == 1
59
+ return scoped_variants.first
60
+ end
61
+ Hash[scoped_variants.flat_map do |variants|
62
+ variants.map do |variant, suffix|
63
+ prefix = block.call(variant)
64
+ scope = [prefix, suffix].compact.join('-')
65
+ [variant, !scope.empty? ? scope : nil]
66
+ end
67
+ end]
68
+ end
69
+
70
+ # @private
71
+ # @return [Hash<PodVariant, String>]
72
+ #
73
+ def scope_by_build_type
74
+ scope_if_necessary(group_by(&:requires_frameworks).map(&:scope_by_platform)) do |variant|
75
+ variant.requires_frameworks? ? 'framework' : 'library'
76
+ end
77
+ end
78
+
79
+ # @private
80
+ # @return [Hash<PodVariant, String>]
81
+ #
82
+ def scope_by_platform
83
+ grouped_variants = group_by { |v| v.platform.name }
84
+ if grouped_variants.all? { |set| set.variants.count == 1 }
85
+ # => Platform name
86
+ platform_name_proc = proc { |v| Platform.string_name(v.platform.symbolic_name).tr(' ', '') }
87
+ else
88
+ grouped_variants = group_by(&:platform)
89
+ # => Platform name + SDK version
90
+ platform_name_proc = proc { |v| v.platform.to_s.tr(' ', '') }
91
+ end
92
+ scope_if_necessary(grouped_variants.map(&:scope_without_suffix), &platform_name_proc)
93
+ end
94
+
95
+ # @private
96
+ # @return [Hash<PodVariant, String>]
97
+ #
98
+ def scope_by_specs
99
+ root_spec = variants.first.root_spec
100
+ specs = [root_spec]
101
+ specs += if root_spec.default_subspecs.empty?
102
+ root_spec.subspecs.compact
103
+ else
104
+ root_spec.default_subspecs.map do |subspec_name|
105
+ root_spec.subspec_by_name("#{root_spec.name}/#{subspec_name}")
106
+ end
107
+ end
108
+ default_specs = Set.new(specs)
109
+ grouped_variants = group_by(&:specs)
110
+ all_spec_variants = grouped_variants.map { |set| set.variants.first.specs }
111
+ common_specs = all_spec_variants.map(&:to_set).flatten.inject(&:&)
112
+ omit_common_specs = common_specs.any? && common_specs.proper_superset?(default_specs)
113
+ scope_if_necessary(grouped_variants.map(&:scope_by_build_type)) do |variant|
114
+ specs = variant.specs.to_set
115
+
116
+ # The current variant contains all default specs
117
+ omit_default_specs = default_specs.any? && default_specs.subset?(specs)
118
+ if omit_default_specs
119
+ specs -= default_specs
120
+ end
121
+
122
+ # There are common specs, which are different from the default specs
123
+ if omit_common_specs
124
+ specs -= common_specs
125
+ end
126
+
127
+ spec_names = specs.map do |spec|
128
+ spec.root? ? '.root' : spec.name.split('/')[1..-1].join('_')
129
+ end.sort
130
+ if spec_names.empty?
131
+ omit_common_specs ? '.common' : nil
132
+ else
133
+ if omit_common_specs
134
+ spec_names.unshift('.common')
135
+ elsif omit_default_specs
136
+ spec_names.unshift('.default')
137
+ end
138
+ spec_names.reduce('') do |acc, name|
139
+ "#{acc}#{acc.empty? || name[0] == '.' ? '' : '-'}#{name}"
140
+ end
141
+ end
142
+ end
143
+ end
144
+
145
+ # @private
146
+ #
147
+ # Helps to define scope suffixes recursively.
148
+ #
149
+ # @return [Hash<PodVariant, String>]
150
+ #
151
+ def scope_without_suffix
152
+ Hash[variants.map { |v| [v, nil] }]
153
+ end
154
+ end
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,54 @@
1
+ module Pod
2
+ class DyInstaller
3
+ class Analyzer
4
+ # Caches podfile & target definition dependencies, so they do not need to be re-computed
5
+ # from the internal hash on each access
6
+ #
7
+ class PodfileDependencyCache
8
+ # @return [Array<Pod::Dependency>]
9
+ # All the dependencies in the podfile
10
+ #
11
+ attr_reader :podfile_dependencies
12
+
13
+ def initialize(podfile_dependencies, dependencies_by_target_definition)
14
+ @podfile_dependencies = podfile_dependencies
15
+ @dependencies_by_target_definition = dependencies_by_target_definition
16
+ end
17
+
18
+ # Returns the dependencies for the given target definition
19
+ #
20
+ def target_definition_dependencies(target_definition)
21
+ @dependencies_by_target_definition[target_definition] ||
22
+ raise(ArgumentError, "dependencies for #{target_definition.inspect} do not exist in the cache")
23
+ end
24
+
25
+ # Returns a list of all of the target definitions in the Podfile
26
+ #
27
+ def target_definition_list
28
+ @dependencies_by_target_definition.keys
29
+ end
30
+
31
+ # Creates a {PodfileDependencyCache} from the given {Podfile}
32
+ #
33
+ # @param [Podfile] podfile
34
+ # The {Podfile} from which dependencies should be cached
35
+ #
36
+ # @return [PodfileDependencyCache]
37
+ # A warmed, immutable cache of all the dependencies in the {Podfile}
38
+ #
39
+ def self.from_podfile(podfile)
40
+ podfile_dependencies = []
41
+ dependencies_by_target_definition = {}
42
+ podfile.target_definition_list.each do |target_definition|
43
+ deps = target_definition.dependencies.freeze
44
+ podfile_dependencies.concat deps
45
+ dependencies_by_target_definition[target_definition] = deps
46
+ end
47
+ podfile_dependencies.uniq!
48
+
49
+ new(podfile_dependencies.freeze, dependencies_by_target_definition.freeze)
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,251 @@
1
+ module Pod
2
+ class DyInstaller
3
+ class Analyzer
4
+ # Analyze the sandbox to detect which Pods should be removed, and which
5
+ # ones should be reinstalled.
6
+ #
7
+ # The logic is the following:
8
+ #
9
+ # Added
10
+ # - If not present in the sandbox lockfile.
11
+ # - The directory of the Pod doesn't exits.
12
+ #
13
+ # Changed
14
+ # - The version of the Pod changed.
15
+ # - The SHA of the specification file changed.
16
+ # - The specific installed (sub)specs of the same Pod changed.
17
+ # - The specification is from an external source and the
18
+ # installation process is in update mode.
19
+ # - The directory of the Pod is empty.
20
+ # - The Pod has been pre-downloaded.
21
+ #
22
+ # Removed
23
+ # - If a specification is present in the lockfile but not in the resolved
24
+ # specs.
25
+ #
26
+ # Unchanged
27
+ # - If none of the above conditions match.
28
+ #
29
+ class SandboxAnalyzer
30
+ # @return [Sandbox] The sandbox to analyze.
31
+ #
32
+ attr_reader :sandbox
33
+
34
+ # @return [Array<Specifications>] The specifications returned by the
35
+ # resolver.
36
+ #
37
+ attr_reader :specs
38
+
39
+ # @return [Bool] Whether the installation is performed in update mode.
40
+ #
41
+ attr_reader :update_mode
42
+
43
+ alias_method :update_mode?, :update_mode
44
+
45
+ # @return [Lockfile] The lockfile of the installation as a fall-back if
46
+ # there is no sandbox manifest. This is indented as a temporary
47
+ # solution to prevent the full re-installation from users which
48
+ # are upgrading from CP < 0.17.
49
+ #
50
+ # @todo Remove for CP 0.18.
51
+ #
52
+ attr_reader :lockfile
53
+
54
+ # Init a new SandboxAnalyzer
55
+ #
56
+ # @param [Sandbox] sandbox @see sandbox
57
+ # @param [Array<Specifications>] specs @see specs
58
+ # @param [Bool] update_mode @see update_mode
59
+ # @param [Lockfile] lockfile @see lockfile
60
+ #
61
+ def initialize(sandbox, specs, update_mode, lockfile = nil)
62
+ @sandbox = sandbox
63
+ @specs = specs
64
+ @update_mode = update_mode
65
+ @lockfile = lockfile
66
+ end
67
+
68
+ # Performs the analysis to the detect the state of the sandbox respect
69
+ # to the resolved specifications.
70
+ #
71
+ # @return [void]
72
+ #
73
+ def analyze
74
+ state = SpecsState.new
75
+ if sandbox_manifest
76
+ all_names = (resolved_pods + sandbox_pods).uniq.sort
77
+ all_names.sort.each do |name|
78
+ state.add_name(name, pod_state(name))
79
+ end
80
+ else
81
+ state.added.merge(resolved_pods)
82
+ end
83
+ state
84
+ end
85
+
86
+ #---------------------------------------------------------------------#
87
+
88
+ private
89
+
90
+ # @!group Pod state
91
+
92
+ # Returns the state of the Pod with the given name.
93
+ #
94
+ # @param [String] pod
95
+ # the name of the Pod.
96
+ #
97
+ # @return [Symbol] The state
98
+ #
99
+ def pod_state(pod)
100
+ return :added if pod_added?(pod)
101
+ return :deleted if pod_deleted?(pod)
102
+ return :changed if pod_changed?(pod)
103
+ :unchanged
104
+ end
105
+
106
+ # Returns whether the Pod with the given name should be installed.
107
+ #
108
+ # @note A Pod whose folder doesn't exists is considered added.
109
+ #
110
+ # @param [String] pod
111
+ # the name of the Pod.
112
+ #
113
+ # @return [Bool] Whether the Pod is added.
114
+ #
115
+ def pod_added?(pod)
116
+ return true if resolved_pods.include?(pod) && !sandbox_pods.include?(pod)
117
+ return true unless folder_exist?(pod)
118
+ false
119
+ end
120
+
121
+ # Returns whether the Pod with the given name should be removed from
122
+ # the installation.
123
+ #
124
+ # @param [String] pod
125
+ # the name of the Pod.
126
+ #
127
+ # @return [Bool] Whether the Pod is deleted.
128
+ #
129
+ def pod_deleted?(pod)
130
+ return true if !resolved_pods.include?(pod) && sandbox_pods.include?(pod)
131
+ false
132
+ end
133
+
134
+ # Returns whether the Pod with the given name should be considered
135
+ # changed and thus should be reinstalled.
136
+ #
137
+ # @note In update mode, as there is no way to know if a remote source
138
+ # hash changed the Pods from external
139
+ # sources are always marked as changed.
140
+ #
141
+ # @note A Pod whose folder is empty is considered changed.
142
+ #
143
+ # @param [String] pod
144
+ # the name of the Pod.
145
+ #
146
+ # @return [Bool] Whether the Pod is changed.
147
+ #
148
+ def pod_changed?(pod)
149
+ spec = root_spec(pod)
150
+ return true if spec.version != sandbox_version(pod)
151
+ return true if spec.checksum != sandbox_checksum(pod)
152
+ return true if resolved_spec_names(pod) != sandbox_spec_names(pod)
153
+ return true if sandbox.predownloaded?(pod)
154
+ return true if folder_empty?(pod)
155
+ false
156
+ end
157
+
158
+ #---------------------------------------------------------------------#
159
+
160
+ private
161
+
162
+ # @!group Private helpers
163
+
164
+ # @return [Lockfile] The manifest to use for the sandbox.
165
+ #
166
+ def sandbox_manifest
167
+ sandbox.manifest || lockfile
168
+ end
169
+
170
+ #--------------------------------------#
171
+
172
+ # @return [Array<String>] The name of the resolved Pods.
173
+ #
174
+ def resolved_pods
175
+ specs.map { |spec| spec.root.name }.uniq
176
+ end
177
+
178
+ # @return [Array<String>] The name of the Pods stored in the sandbox
179
+ # manifest.
180
+ #
181
+ def sandbox_pods
182
+ sandbox_manifest.pod_names.map { |name| Specification.root_name(name) }.uniq
183
+ end
184
+
185
+ # @return [Array<String>] The name of the resolved specifications
186
+ # (includes subspecs).
187
+ #
188
+ # @param [String] pod
189
+ # the name of the Pod.
190
+ #
191
+ def resolved_spec_names(pod)
192
+ specs.select { |s| s.root.name == pod }.map(&:name).uniq.sort
193
+ end
194
+
195
+ # @return [Array<String>] The name of the specifications stored in the
196
+ # sandbox manifest (includes subspecs).
197
+ #
198
+ # @param [String] pod
199
+ # the name of the Pod.
200
+ #
201
+ def sandbox_spec_names(pod)
202
+ sandbox_manifest.pod_names.select { |name| Specification.root_name(name) == pod }.uniq.sort
203
+ end
204
+
205
+ # @return [Specification] The root specification for the Pod with the
206
+ # given name.
207
+ #
208
+ # @param [String] pod
209
+ # the name of the Pod.
210
+ #
211
+ def root_spec(pod)
212
+ specs.find { |s| s.root.name == pod }.root
213
+ end
214
+
215
+ #--------------------------------------#
216
+
217
+ # @return [Version] The version of Pod with the given name stored in
218
+ # the sandbox.
219
+ #
220
+ # @param [String] pod
221
+ # the name of the Pod.
222
+ #
223
+ def sandbox_version(pod)
224
+ sandbox_manifest.version(pod)
225
+ end
226
+
227
+ # @return [String] The checksum of the specification of the Pod with
228
+ # the given name stored in the sandbox.
229
+ #
230
+ # @param [String] pod
231
+ # the name of the Pod.
232
+ #
233
+ def sandbox_checksum(pod)
234
+ sandbox_manifest.checksum(pod)
235
+ end
236
+
237
+ #--------------------------------------#
238
+
239
+ def folder_exist?(pod)
240
+ sandbox.pod_dir(pod).exist?
241
+ end
242
+
243
+ def folder_empty?(pod)
244
+ Dir.glob(sandbox.pod_dir(pod) + '*').empty?
245
+ end
246
+
247
+ #---------------------------------------------------------------------#
248
+ end
249
+ end
250
+ end
251
+ end