cocoapods 0.16.4 → 0.17.0.rc1

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 (71) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +108 -0
  3. data/README.md +3 -3
  4. data/bin/pod +1 -1
  5. data/lib/cocoapods.rb +31 -31
  6. data/lib/cocoapods/command.rb +62 -107
  7. data/lib/cocoapods/command/inter_process_communication.rb +103 -0
  8. data/lib/cocoapods/command/list.rb +45 -44
  9. data/lib/cocoapods/command/outdated.rb +28 -25
  10. data/lib/cocoapods/command/project.rb +90 -0
  11. data/lib/cocoapods/command/push.rb +50 -32
  12. data/lib/cocoapods/command/repo.rb +125 -155
  13. data/lib/cocoapods/command/search.rb +23 -12
  14. data/lib/cocoapods/command/setup.rb +103 -64
  15. data/lib/cocoapods/command/spec.rb +329 -90
  16. data/lib/cocoapods/config.rb +197 -44
  17. data/lib/cocoapods/downloader.rb +47 -34
  18. data/lib/cocoapods/executable.rb +98 -41
  19. data/lib/cocoapods/external_sources.rb +325 -0
  20. data/lib/cocoapods/file_list.rb +8 -1
  21. data/lib/cocoapods/gem_version.rb +7 -0
  22. data/lib/cocoapods/generator/acknowledgements.rb +71 -7
  23. data/lib/cocoapods/generator/acknowledgements/markdown.rb +10 -9
  24. data/lib/cocoapods/generator/acknowledgements/plist.rb +9 -8
  25. data/lib/cocoapods/generator/copy_resources_script.rb +2 -2
  26. data/lib/cocoapods/generator/documentation.rb +153 -37
  27. data/lib/cocoapods/generator/prefix_header.rb +82 -0
  28. data/lib/cocoapods/generator/target_header.rb +58 -0
  29. data/lib/cocoapods/generator/xcconfig.rb +130 -0
  30. data/lib/cocoapods/hooks/installer_representation.rb +123 -0
  31. data/lib/cocoapods/hooks/library_representation.rb +79 -0
  32. data/lib/cocoapods/hooks/pod_representation.rb +74 -0
  33. data/lib/cocoapods/installer.rb +398 -147
  34. data/lib/cocoapods/installer/analyzer.rb +556 -0
  35. data/lib/cocoapods/installer/analyzer/sandbox_analyzer.rb +253 -0
  36. data/lib/cocoapods/installer/file_references_installer.rb +179 -0
  37. data/lib/cocoapods/installer/pod_source_installer.rb +289 -0
  38. data/lib/cocoapods/installer/target_installer.rb +307 -112
  39. data/lib/cocoapods/installer/user_project_integrator.rb +140 -176
  40. data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +193 -0
  41. data/lib/cocoapods/library.rb +195 -0
  42. data/lib/cocoapods/open_uri.rb +16 -14
  43. data/lib/cocoapods/project.rb +175 -52
  44. data/lib/cocoapods/resolver.rb +151 -164
  45. data/lib/cocoapods/sandbox.rb +276 -54
  46. data/lib/cocoapods/sandbox/file_accessor.rb +210 -0
  47. data/lib/cocoapods/sandbox/headers_store.rb +96 -0
  48. data/lib/cocoapods/sandbox/path_list.rb +178 -0
  49. data/lib/cocoapods/sources_manager.rb +218 -0
  50. data/lib/cocoapods/user_interface.rb +82 -18
  51. data/lib/cocoapods/{command → user_interface}/error_report.rb +5 -5
  52. data/lib/cocoapods/validator.rb +379 -0
  53. metadata +74 -55
  54. data/lib/cocoapods/command/install.rb +0 -55
  55. data/lib/cocoapods/command/linter.rb +0 -317
  56. data/lib/cocoapods/command/update.rb +0 -25
  57. data/lib/cocoapods/dependency.rb +0 -285
  58. data/lib/cocoapods/downloader/git.rb +0 -276
  59. data/lib/cocoapods/downloader/http.rb +0 -99
  60. data/lib/cocoapods/downloader/mercurial.rb +0 -26
  61. data/lib/cocoapods/downloader/subversion.rb +0 -42
  62. data/lib/cocoapods/local_pod.rb +0 -620
  63. data/lib/cocoapods/lockfile.rb +0 -274
  64. data/lib/cocoapods/platform.rb +0 -127
  65. data/lib/cocoapods/podfile.rb +0 -551
  66. data/lib/cocoapods/source.rb +0 -223
  67. data/lib/cocoapods/specification.rb +0 -579
  68. data/lib/cocoapods/specification/set.rb +0 -175
  69. data/lib/cocoapods/specification/statistics.rb +0 -112
  70. data/lib/cocoapods/user_interface/ui_pod.rb +0 -130
  71. data/lib/cocoapods/version.rb +0 -26
@@ -0,0 +1,253 @@
1
+ module Pod
2
+ class Installer
3
+ class Analyzer
4
+
5
+ # Analyze the sandbox to detect which Pods should be removed, and which
6
+ # ones should be reinstalled.
7
+ #
8
+ # The logic is the following:
9
+ #
10
+ # Added
11
+ # - If not present in the sandbox lockfile.
12
+ # - The directory of the Pod doesn't exits.
13
+ #
14
+ # Changed
15
+ # - The version of the Pod changed.
16
+ # - The SHA of the specification file changed.
17
+ # - The specific installed (sub)specs of the same Pod changed.
18
+ # - The specification is in head mode or from an external source and the
19
+ # installation process is in update mode.
20
+ # - The directory of the Pod is empty.
21
+ # - The Pod has been pre-downloaded.
22
+ #
23
+ # Removed
24
+ # - If a specification is present in the lockfile but not in the resolved
25
+ # specs.
26
+ #
27
+ # Unchanged
28
+ # - If none of the above conditions match.
29
+ #
30
+ class SandboxAnalyzer
31
+
32
+ # @return [Sandbox] The sandbox to analyze.
33
+ #
34
+ attr_reader :sandbox
35
+
36
+ # @return [Array<Specifications>] The specifications returned by the
37
+ # resolver.
38
+ #
39
+ attr_reader :specs
40
+
41
+ # @return [Bool] Whether the installation is performed in update mode.
42
+ #
43
+ attr_reader :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
+ # @param [Sandbox] sandbox @see sandbox
55
+ # @param [Array<Specifications>] specs @see specs
56
+ # @param [Bool] update_mode @see update_mode
57
+ # @param [Lockfile] lockfile @see lockfile
58
+ #
59
+ def initialize(sandbox, specs, update_mode, lockfile = nil)
60
+ @sandbox = sandbox
61
+ @specs = specs
62
+ @update_mode = update_mode
63
+ @lockfile = lockfile
64
+ end
65
+
66
+ # Performs the analysis to the detect the state of the sandbox respect
67
+ # to the resolved specifications.
68
+ #
69
+ # @return [SpecsState] the state of the sandbox.
70
+ #
71
+ def analyze
72
+ state = SpecsState.new
73
+ if sandbox_manifest
74
+ all_names = (resolved_pods + sandbox_pods).uniq.sort
75
+ all_names.sort.each do |name|
76
+ state.add_name(name, pod_state(name))
77
+ end
78
+ else
79
+ state.added.concat(resolved_pods)
80
+ end
81
+ state
82
+ end
83
+
84
+ #---------------------------------------------------------------------#
85
+
86
+ private
87
+
88
+ # @!group Pod state
89
+
90
+ # Returns the state of the Pod with the given name.
91
+ #
92
+ # @param [String] pod
93
+ # the name of the Pod.
94
+ #
95
+ # @return [Symbol] The state
96
+ #
97
+ def pod_state(pod)
98
+ return :added if pod_added?(pod)
99
+ return :deleted if pod_deleted?(pod)
100
+ return :changed if pod_changed?(pod)
101
+ return :unchanged
102
+ end
103
+
104
+ # Returns whether the Pod with the given name should be installed.
105
+ #
106
+ # @note A Pod whose folder doesn't exists is considered added.
107
+ #
108
+ # @param [String] pod
109
+ # the name of the Pod.
110
+ #
111
+ # @return [Bool] Whether the Pod is added.
112
+ #
113
+ def pod_added?(pod)
114
+ return true if resolved_pods.include?(pod) && !sandbox_pods.include?(pod)
115
+ return true if !folder_exist?(pod)
116
+ return false
117
+ end
118
+
119
+ # Returns whether the Pod with the given name should be removed from
120
+ # the installation.
121
+ #
122
+ # @param [String] pod
123
+ # the name of the Pod.
124
+ #
125
+ # @return [Bool] Whether the Pod is deleted.
126
+ #
127
+ def pod_deleted?(pod)
128
+ return true if !resolved_pods.include?(pod) && sandbox_pods.include?(pod)
129
+ return false
130
+ end
131
+
132
+ # Returns whether the Pod with the given name should be considered
133
+ # changed and thus should be reinstalled.
134
+ #
135
+ # @note In update mode, as there is no way to know if a remote source
136
+ # hash changed the Pods in head mode and the ones from external
137
+ # sources are always marked as changed.
138
+ #
139
+ # @note A Pod whose folder is empty is considered changed.
140
+ #
141
+ # @param [String] pod
142
+ # the name of the Pod.
143
+ #
144
+ # @return [Bool] Whether the Pod is changed.
145
+ #
146
+ def pod_changed?(pod)
147
+ spec = root_spec(pod)
148
+ return true if spec.version != sandbox_version(pod)
149
+ return true if spec.checksum != sandbox_checksum(pod)
150
+ return true if resolved_spec_names(pod) != sandbox_spec_names(pod)
151
+ return true if sandbox.predownloaded?(pod)
152
+ return true if folder_empty?(pod)
153
+ if update_mode
154
+ return true if spec.version.head?
155
+ end
156
+ return false
157
+ end
158
+
159
+ #---------------------------------------------------------------------#
160
+
161
+ private
162
+
163
+ # @!group Private helpers
164
+
165
+ # @return [Lockfile] The manifest to use for the sandbox.
166
+ #
167
+ def sandbox_manifest
168
+ sandbox.manifest || lockfile
169
+ end
170
+
171
+ #--------------------------------------#
172
+
173
+ # @return [Array<String>] The name of the resolved Pods.
174
+ #
175
+ def resolved_pods
176
+ specs.map { |spec| spec.root.name }.uniq
177
+ end
178
+
179
+ # @return [Array<String>] The name of the Pods stored in the sandbox
180
+ # manifest.
181
+ #
182
+ def sandbox_pods
183
+ sandbox_manifest.pod_names.map { |name| Specification.root_name(name) }.uniq
184
+ end
185
+
186
+ # @return [Array<String>] The name of the resolved specifications
187
+ # (includes subspecs).
188
+ #
189
+ # @param [String] pod
190
+ # the name of the Pod.
191
+ #
192
+ def resolved_spec_names(pod)
193
+ specs.select { |s| s.root.name == pod }.map(&:name).uniq
194
+ end
195
+
196
+ # @return [Array<String>] The name of the specifications stored in the
197
+ # sandbox manifest (includes subspecs).
198
+ #
199
+ # @param [String] pod
200
+ # the name of the Pod.
201
+ #
202
+ def sandbox_spec_names(pod)
203
+ sandbox_manifest.pod_names.select { |name| Specification.root_name(name) == pod }.uniq
204
+ end
205
+
206
+ # @return [Specification] The root specification for the Pod with the
207
+ # given name.
208
+ #
209
+ # @param [String] pod
210
+ # the name of the Pod.
211
+ #
212
+ def root_spec(pod)
213
+ specs.find { |s| s.root.name == pod }.root
214
+ end
215
+
216
+ #--------------------------------------#
217
+
218
+ # @return [Version] The version of Pod with the given name stored in
219
+ # the sandbox.
220
+ #
221
+ # @param [String] pod
222
+ # the name of the Pod.
223
+ #
224
+ def sandbox_version(pod)
225
+ sandbox_manifest.version(pod)
226
+ end
227
+
228
+ # @return [String] The checksum of the specification of the Pod with
229
+ # the given name stored in the sandbox.
230
+ #
231
+ # @param [String] pod
232
+ # the name of the Pod.
233
+ #
234
+ def sandbox_checksum(pod)
235
+ sandbox_manifest.checksum(pod)
236
+ end
237
+
238
+ #--------------------------------------#
239
+
240
+ def folder_exist?(pod)
241
+ sandbox.pod_dir(pod).exist?
242
+ end
243
+
244
+ def folder_empty?(pod)
245
+ Dir.glob(sandbox.pod_dir(pod) + '*').empty?
246
+ end
247
+
248
+ #---------------------------------------------------------------------#
249
+
250
+ end
251
+ end
252
+ end
253
+ end
@@ -0,0 +1,179 @@
1
+ module Pod
2
+ class Installer
3
+
4
+ # Controller class responsible of installing the file references of the
5
+ # specifications in the Pods project.
6
+ #
7
+ class FileReferencesInstaller
8
+
9
+ # @return [Sandbox] The sandbox of the installation.
10
+ #
11
+ attr_reader :sandbox
12
+
13
+ # @return [Array<Library>] The libraries of the installation.
14
+ #
15
+ attr_reader :libraries
16
+
17
+ # @return [Project] The Pods project.
18
+ #
19
+ attr_reader :pods_project
20
+
21
+ # @param [Sandbox] sandbox @see sandbox
22
+ # @param [Array<Library>] libraries @see libraries
23
+ # @param [Project] libraries @see libraries
24
+ #
25
+ def initialize(sandbox, libraries, pods_project)
26
+ @sandbox = sandbox
27
+ @libraries = libraries
28
+ @pods_project = pods_project
29
+ end
30
+
31
+ # Installs the file references.
32
+ #
33
+ # @return [void]
34
+ #
35
+ def install!
36
+ refresh_file_accessors
37
+ add_source_files_references
38
+ add_resources_references
39
+ link_headers
40
+ end
41
+
42
+ #-----------------------------------------------------------------------#
43
+
44
+ private
45
+
46
+ # @!group Installation Steps
47
+
48
+ # Reads the file accessors contents from the file system.
49
+ #
50
+ # @note The contents of the file accessors are modified by the clean
51
+ # step of the #{PodSourceInstaller} and by the pre install hooks.
52
+ #
53
+ # @return [void]
54
+ #
55
+ def refresh_file_accessors
56
+ file_accessors.each do |fa|
57
+ fa.path_list.read_file_system
58
+ end
59
+ end
60
+
61
+ # Adds the source files of the Pods to the Pods project.
62
+ #
63
+ # @note The source files are grouped by Pod and in turn by subspec
64
+ # (recursively).
65
+ #
66
+ # @note Pods are generally added to the `Pods` group, however, if they
67
+ # have a local source they are added to the
68
+ # `Local Pods` group.
69
+ #
70
+ # @return [void]
71
+ #
72
+ def add_source_files_references
73
+ UI.message "- Adding source files to Pods project" do
74
+ file_accessors.each do |file_accessor|
75
+ files = file_accessor.source_files
76
+ spec_name = file_accessor.spec.name
77
+ local = sandbox.local?(file_accessor.spec.root.name)
78
+ parent_group = local ? pods_project.local_pods : pods_project.pods
79
+ pods_project.add_file_references(files, spec_name, parent_group)
80
+ end
81
+ end
82
+ end
83
+
84
+ # Adds the resources of the Pods to the Pods project.
85
+ #
86
+ # @note The source files are grouped by Pod and in turn by subspec
87
+ # (recursively) in the resources group.
88
+ #
89
+ # @return [void]
90
+ #
91
+ def add_resources_references
92
+ UI.message "- Adding resources to Pods project" do
93
+ file_accessors.each do |file_accessor|
94
+ file_accessor.resources.each do |resources|
95
+ files = file_accessor.resources
96
+ spec_name = file_accessor.spec.name
97
+ parent_group = pods_project.resources
98
+ pods_project.add_file_references(files, spec_name, parent_group)
99
+ end
100
+ end
101
+ end
102
+ end
103
+
104
+ # Creates the link to the headers of the Pod in the sandbox.
105
+ #
106
+ # @return [void]
107
+ #
108
+ def link_headers
109
+ UI.message "- Linking headers" do
110
+
111
+ file_accessors.each do |file_accessor|
112
+ headers_sandbox = Pathname.new(file_accessor.spec.root.name)
113
+ sandbox.build_headers.add_search_path(headers_sandbox)
114
+ sandbox.public_headers.add_search_path(headers_sandbox)
115
+
116
+ consumer = file_accessor.spec_consumer
117
+ header_mappings(headers_sandbox, consumer, file_accessor.headers).each do |namespaced_path, files|
118
+ sandbox.build_headers.add_files(namespaced_path, files)
119
+ end
120
+
121
+ header_mappings(headers_sandbox, consumer, file_accessor.public_headers).each do |namespaced_path, files|
122
+ sandbox.public_headers.add_files(namespaced_path, files)
123
+ end
124
+ end
125
+ end
126
+ end
127
+
128
+ #-----------------------------------------------------------------------#
129
+
130
+ private
131
+
132
+ # @!group Private Helpers
133
+
134
+ # @return [Array<Sandbox::FileAccessor>] The file accessors for all the
135
+ # specs platform combinations.
136
+ #
137
+ def file_accessors
138
+ @file_accessors ||= libraries.map(&:file_accessors).flatten.compact
139
+ end
140
+
141
+ # Computes the destination sub-directory in the sandbox
142
+ #
143
+ # @param [Pathname] headers_sandbox
144
+ # The sandbox where the headers links should be stored for this
145
+ # Pod.
146
+ #
147
+ # @param [Specification::Consumer] consumer
148
+ # The consumer for which the headers need to be linked.
149
+ #
150
+ # @param [Array<Pathname>] headers
151
+ # The absolute paths of the headers which need to be mapped.
152
+ #
153
+ # @return [Hash{Pathname => Array<Pathname>}] A hash containing the
154
+ # headers folders as the keys and the absolute paths of the
155
+ # header files as the values.
156
+ #
157
+ def header_mappings(headers_sandbox, consumer, headers)
158
+ dir = headers_sandbox
159
+ dir = dir + consumer.header_dir if consumer.header_dir
160
+
161
+ mappings = {}
162
+ headers.each do |header|
163
+ sub_dir = dir
164
+ if consumer.header_mappings_dir
165
+ header_mappings_dir = Pathname.new(consumer.header_mappings_dir)
166
+ relative_path = header.relative_path_from(header_mappings_dir)
167
+ sub_dir = sub_dir + relative_path.dirname
168
+ end
169
+ mappings[sub_dir] ||= []
170
+ mappings[sub_dir] << header
171
+ end
172
+ mappings
173
+ end
174
+
175
+ #-----------------------------------------------------------------------#
176
+
177
+ end
178
+ end
179
+ end
@@ -0,0 +1,289 @@
1
+ module Pod
2
+ class Installer
3
+
4
+ # Controller class responsible of installing the activated specifications
5
+ # of a single Pod.
6
+ #
7
+ # @note This class needs to consider all the activated specs of a Pod.
8
+ #
9
+ class PodSourceInstaller
10
+
11
+ # @return [Sandbox]
12
+ #
13
+ attr_reader :sandbox
14
+
15
+ # @return [Hash{Symbol=>Array}] The specifications that need to be
16
+ # installed grouped by platform.
17
+ #
18
+ attr_reader :specs_by_platform
19
+
20
+ # @param [Sandbox] sandbox @see sandbox
21
+ # @param [Hash{Symbol=>Array}] specs_by_platform @see specs_by_platform
22
+ #
23
+ def initialize(sandbox, specs_by_platform)
24
+ @sandbox = sandbox
25
+ @specs_by_platform = specs_by_platform
26
+
27
+ @clean = true
28
+ @generate_docs = false
29
+ @install_docs = false
30
+ @aggressive_cache = false
31
+ end
32
+
33
+ # @return [String] A string suitable for debugging.
34
+ #
35
+ def inspect
36
+ "<#{self.class} sandbox=#{sandbox.root} pod=#{root_spec.name}"
37
+ end
38
+
39
+ #-----------------------------------------------------------------------#
40
+
41
+ public
42
+
43
+ # @!group Configuration
44
+
45
+ # @return [Bool] whether the file not used by CocoaPods should be
46
+ # removed.
47
+ #
48
+ attr_accessor :clean
49
+ alias_method :clean?, :clean
50
+
51
+ # @return [Bool] whether the documentation should be generated for the
52
+ # Pod.
53
+ #
54
+ attr_accessor :generate_docs
55
+ alias_method :generate_docs?, :generate_docs
56
+
57
+ # @return [Bool] whether the generated documentation should be installed
58
+ # in Xcode.
59
+ #
60
+ attr_accessor :install_docs
61
+ alias_method :install_docs?, :install_docs
62
+
63
+ # @return [Bool] whether the downloader should always check against the
64
+ # remote if issues might be generated (mostly useful to speed up
65
+ # testing).
66
+ #
67
+ # @note This might be removed in future.
68
+ #
69
+ attr_accessor :aggressive_cache
70
+ alias_method :aggressive_cache?, :aggressive_cache
71
+
72
+ #-----------------------------------------------------------------------#
73
+
74
+ public
75
+
76
+ # @!group Installation
77
+
78
+ # Creates the target in the Pods project and the relative support files.
79
+ #
80
+ # @return [void]
81
+ #
82
+ def install!
83
+ download_source unless predownloaded? || local?
84
+ generate_docs if generate_docs?
85
+ clean_installation if clean? && !local?
86
+ end
87
+
88
+ # @return [Hash]
89
+ #
90
+ attr_reader :specific_source
91
+
92
+ #-----------------------------------------------------------------------#
93
+
94
+ private
95
+
96
+ # @!group Installation Steps
97
+
98
+ # Downloads the source of the Pod. It also stores the specific options
99
+ # needed to recreate the same exact installation if needed in
100
+ # `#specific_source`.
101
+ #
102
+ # @return [void]
103
+ #
104
+ def download_source
105
+ root.rmtree if root.exist?
106
+ if root_spec.version.head?
107
+ downloader.download_head
108
+ @specific_source = downloader.checkout_options
109
+ else
110
+ downloader.download
111
+ unless downloader.options_specific?
112
+ @specific_source = downloader.checkout_options
113
+ end
114
+ end
115
+
116
+ if specific_source
117
+ sandbox.store_checkout_source(root_spec.name, specific_source)
118
+ end
119
+ end
120
+
121
+ # Generates the documentation for the Pod.
122
+ #
123
+ # @return [void]
124
+ #
125
+ def generate_docs
126
+ if @cleaned
127
+ raise Informative, "Attempt to generate the documentation from a cleaned Pod."
128
+ end
129
+
130
+ if documentation_generator.already_installed?
131
+ UI.section " > Using existing documentation"
132
+ else
133
+ UI.section " > Installing documentation" do
134
+ documentation_generator.generate(install_docs?)
135
+ end
136
+ end
137
+ end
138
+
139
+ # Removes all the files not needed for the installation according to the
140
+ # specs by platform.
141
+ #
142
+ # @return [void]
143
+ #
144
+ def clean_installation
145
+ clean_paths.each { |path| FileUtils.rm_rf(path) }
146
+ @cleaned = true
147
+ end
148
+
149
+ #-----------------------------------------------------------------------#
150
+
151
+ public
152
+
153
+ # @!group Dependencies
154
+
155
+ # @return [String] The directory where CocoaPods caches the downloads.
156
+ #
157
+ CACHE_ROOT = "~/Library/Caches/CocoaPods"
158
+
159
+ # @return [Fixnum] The maximum size for the cache expressed in Mb.
160
+ #
161
+ MAX_CACHE_SIZE = 500
162
+
163
+ # @return [Downloader] The downloader to use for the retrieving the
164
+ # source.
165
+ #
166
+ def downloader
167
+ return @downloader if @downloader
168
+ @downloader = Downloader.for_target(root, root_spec.source.dup)
169
+ @downloader.cache_root = CACHE_ROOT
170
+ @downloader.max_cache_size = MAX_CACHE_SIZE
171
+ @downloader.aggressive_cache = aggressive_cache?
172
+ @downloader
173
+ end
174
+
175
+ # @return [Generator::Documentation] The documentation generator to use
176
+ # for generating the documentation.
177
+ #
178
+ def documentation_generator
179
+ @documentation_generator ||= Generator::Documentation.new(sandbox, root_spec, path_list)
180
+ end
181
+
182
+ #-----------------------------------------------------------------------#
183
+
184
+ private
185
+
186
+ # @!group Convenience methods.
187
+
188
+ # @return [Array<Specifications>] the specification of the Pod used in
189
+ # this installation.
190
+ #
191
+ def specs
192
+ specs_by_platform.values.flatten
193
+ end
194
+
195
+ # @return [Specification] the root specification of the Pod.
196
+ #
197
+ def root_spec
198
+ specs.first.root
199
+ end
200
+
201
+ # @return [Pathname] the folder where the source of the Pod is located.
202
+ #
203
+ def root
204
+ sandbox.pod_dir(root_spec.name)
205
+ end
206
+
207
+ # @return [Boolean] whether the source has been pre downloaded in the
208
+ # resolution process to retrieve its podspec.
209
+ #
210
+ def predownloaded?
211
+ sandbox.predownloaded_pods.include?(root_spec.name)
212
+ end
213
+
214
+ # @return [Boolean] whether the pod uses the local option and thus
215
+ # CocoaPods should not interfere with the files of the user.
216
+ #
217
+ def local?
218
+ sandbox.local?(root_spec.name)
219
+ end
220
+
221
+ #-----------------------------------------------------------------------#
222
+
223
+ private
224
+
225
+ # @!group Private helpers
226
+
227
+ # @return [Array<Sandbox::FileAccessor>] the file accessors for all the
228
+ # specifications on their respective platform.
229
+ #
230
+ def file_accessors
231
+ return @file_accessors if @file_accessors
232
+ @file_accessors = []
233
+ specs_by_platform.each do |platform, specs|
234
+ specs.each do |spec|
235
+ @file_accessors << Sandbox::FileAccessor.new(path_list, spec.consumer(platform))
236
+ end
237
+ end
238
+ @file_accessors
239
+ end
240
+
241
+ # @return [Sandbox::PathList] The path list for this Pod.
242
+ #
243
+ def path_list
244
+ @path_list ||= Sandbox::PathList.new(root)
245
+ end
246
+
247
+ # Finds the absolute paths, including hidden ones, of the files
248
+ # that are not used by the pod and thus can be safely deleted.
249
+ #
250
+ # @note Implementation detail: Don't use `Dir#glob` as there is an
251
+ # unexplained issue (#568, #572 and #602).
252
+ #
253
+ # @return [Array<Strings>] The paths that can be deleted.
254
+ #
255
+ def clean_paths
256
+ cached_used = used_files
257
+ glob_options = File::FNM_DOTMATCH | File::FNM_CASEFOLD
258
+ files = Pathname.glob(root + "**/*", glob_options).map(&:to_s)
259
+
260
+ files.reject! do |candidate|
261
+ candidate.end_with?('.', '..') || cached_used.any? do |path|
262
+ path.include?(candidate) || candidate.include?(path)
263
+ end
264
+ end
265
+ files
266
+ end
267
+
268
+ # @return [Array<String>] The absolute path of all the files used by the
269
+ # specifications (according to their platform) of this Pod.
270
+ #
271
+ def used_files
272
+
273
+ files = [
274
+ file_accessors.map(&:source_files),
275
+ file_accessors.map(&:resources),
276
+ file_accessors.map(&:preserve_paths),
277
+ file_accessors.map(&:prefix_header),
278
+ file_accessors.map(&:readme),
279
+ file_accessors.map(&:license),
280
+ ]
281
+
282
+ files.flatten.compact.map{ |path| path.to_s }.uniq
283
+ end
284
+
285
+ #-----------------------------------------------------------------------#
286
+
287
+ end
288
+ end
289
+ end