cocoapods 0.6.0.rc2 → 0.6.0.rc3

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.
data/README.md CHANGED
@@ -50,13 +50,17 @@ Now that you've got CocoaPods installed you can easily add it to your project.
50
50
  Search for Pods by name or description.
51
51
 
52
52
  ```
53
- $ pod search asi
54
- ==> ASIHTTPRequest (1.8.1)
55
- Easy to use CFNetwork wrapper for HTTP requests, Objective-C, Mac OS X and iPhone
53
+ $ pod search json
56
54
 
57
- ==> ASIWebPageRequest (1.8.1)
58
- The ASIWebPageRequest class included with ASIHTTPRequest lets you download
59
- complete webpages, including external resources like images and stylesheets.
55
+ --> JSONKit (1.4, 1.5pre)
56
+ A Very High Performance Objective-C JSON Library.
57
+ - Homepage: https://github.com/johnezang/JSONKit
58
+ - Source: https://github.com/johnezang/JSONKit.git
59
+
60
+ --> SBJson (2.2.3, 3.0.4, 3.1)
61
+ This library implements strict JSON parsing and generation in Objective-C.
62
+ - Homepage: http://stig.github.com/json-framework/
63
+ - Source: https://github.com/stig/json-framework.git
60
64
  ```
61
65
 
62
66
  After you've found your favorite dependencies you add them to your [Podfile](https://github.com/CocoaPods/CocoaPods/wiki/A-Podfile).
@@ -1,7 +1,5 @@
1
- Encoding.default_external = Encoding::UTF_8 if RUBY_VERSION > '1.8.7'
2
-
3
1
  module Pod
4
- VERSION = '0.6.0.rc2'
2
+ VERSION = '0.6.0.rc3'
5
3
 
6
4
  class PlainInformative < StandardError
7
5
  end
@@ -241,13 +241,14 @@ module Pod
241
241
  end
242
242
 
243
243
  def podfile_from_spec
244
- name = spec.name
245
- podspec = file.realpath.to_s
246
- platform_sym = @platform.to_sym
247
- podfile = Pod::Podfile.new do
248
- platform(platform_sym)
244
+ name = spec.name
245
+ podspec = file.realpath.to_s
246
+ platform = @platform
247
+ podfile = Pod::Podfile.new do
248
+ platform(platform)
249
249
  dependency name, :podspec => podspec
250
250
  end
251
+ podfile
251
252
  end
252
253
 
253
254
  def set_up_lint_environment
@@ -337,7 +338,7 @@ module Pod
337
338
  messages << "The description should end with a dot" if @spec.description !~ /.*\./ && @spec.description != @spec.summary
338
339
  messages << "Git sources should specify either a tag or a commit" if source[:git] && !source[:commit] && !source[:tag]
339
340
  messages << "Github repositories should end in `.git'" if github_source? && source[:git] !~ /.*\.git/
340
- messages << "Github repositories should use `https' link" if github_source? && source[:git] !~ /https:\/\/github.com/
341
+ # messages << "Github repositories should use `https' link" if github_source? && source[:git] !~ /https:\/\/github.com/
341
342
  messages << "Comments must be deleted" if text =~ /^\w*#\n\w*#/ # allow a single line comment as it is generally used in subspecs
342
343
  messages
343
344
  end
@@ -405,7 +406,7 @@ module Pod
405
406
  def file_patterns_errors
406
407
  messages = []
407
408
  messages << "The sources did not match any file" if !@spec.source_files.empty? && @pod.source_files.empty?
408
- messages << "The resources did not match any file" if !@spec.resources.empty? && @pod.resources.empty?
409
+ messages << "The resources did not match any file" if !@spec.resources.empty? && @pod.resource_files.empty?
409
410
  messages << "The preserve_paths did not match any file" if !@spec.preserve_paths.empty? && @pod.preserve_paths.empty?
410
411
  messages << "The exclude_header_search_paths did not match any file" if !@spec.exclude_header_search_paths.empty? && @pod.headers_excluded_from_search_paths.empty?
411
412
  messages
@@ -29,7 +29,7 @@ module Pod
29
29
  pods.each do |pod|
30
30
  # Add all source files to the project grouped by pod
31
31
  group = @project.add_pod_group(pod.name)
32
- pod.source_files.each do |path|
32
+ pod.relative_source_files.each do |path|
33
33
  group.files.new('path' => path.to_s)
34
34
  end
35
35
  end
@@ -20,12 +20,12 @@ module Pod
20
20
  end
21
21
 
22
22
  def copy_resources_script_for(pods)
23
- @copy_resources_script ||= Generator::CopyResourcesScript.new(pods.map { |p| p.resources }.flatten)
23
+ @copy_resources_script ||= Generator::CopyResourcesScript.new(pods.map { |p| p.relative_resource_files }.flatten)
24
24
  end
25
25
 
26
26
  def bridge_support_generator_for(pods, sandbox)
27
27
  Generator::BridgeSupport.new(pods.map do |pod|
28
- pod.header_files.map { |header| sandbox.root + header }
28
+ pod.relative_header_files.map { |header| sandbox.root + header }
29
29
  end.flatten)
30
30
  end
31
31
 
@@ -62,13 +62,15 @@ module Pod
62
62
 
63
63
  @target = @project.add_pod_target(@target_definition.label, @target_definition.platform)
64
64
 
65
+ source_file_descriptions = []
65
66
  pods.each do |pod|
66
67
  xcconfig.merge!(pod.xcconfig)
67
- pod.add_to_target(@target)
68
+ source_file_descriptions += pod.source_file_descriptions
68
69
 
69
70
  # TODO: this doesn't need to be done here, it has nothing to do with the target
70
71
  pod.link_headers
71
72
  end
73
+ @target.add_source_files(source_file_descriptions)
72
74
 
73
75
  xcconfig.merge!('HEADER_SEARCH_PATHS' => quoted(sandbox.header_search_paths).join(" "))
74
76
 
@@ -1,125 +1,266 @@
1
1
  module Pod
2
+
3
+ # A {LocalPod} interfaces one or more specifications belonging to one pod
4
+ # (a library) and their concrete instance in the file system.
5
+ #
6
+ # The {LocalPod} is responsible for orchestrating the activated
7
+ # specifications of a single pod. Specifically, it keeps track of the
8
+ # activated specifications and handles issues related to duplicates
9
+ # files.
10
+ # Inheritance logic belongs to the {Specification} class.
11
+ #
12
+ # The activated specifications are used to compute the paths that can be
13
+ # safely cleaned by the pod.
14
+ #
15
+ # @example
16
+ # pod = LocalPod.new 'RestKit/Networking'
17
+ # pod.add_specification 'RestKit/UI'
18
+ #
19
+ # @note
20
+ # Unless otherwise specified in the name of the method the {LocalPod}
21
+ # returns absolute paths.
22
+ #
2
23
  class LocalPod
3
- attr_reader :top_specification, :specifications
24
+
25
+ # @return [Specification] The specification that describes the pod.
26
+ #
27
+ attr_reader :top_specification
28
+
29
+ # @return [Specification] The activated specifications of the pod.
30
+ #
31
+ attr_reader :specifications
32
+
33
+ # @return [Sandbox] The sandbox where the pod is installed.
34
+ #
4
35
  attr_reader :sandbox
5
36
 
37
+ # @return [Platform] The platform that will be used to build the pod.
38
+ #
39
+ attr_reader :platform
40
+
41
+ # @param [Specification] specification
42
+ # The first activated specification of the pod.
43
+ # @param [Sandbox] sandbox
44
+ # The sandbox where the files of the pod will be located.
45
+ # @param [Platform] platform
46
+ # The platform that will be used to build the pod.
47
+ #
48
+ # @todo The local pod should be initialized with all the activated
49
+ # specifications passed as an array, in order to be able to cache the
50
+ # computed values. In other words, it should be immutable.
51
+ #
6
52
  def initialize(specification, sandbox, platform)
7
- @top_specification, @sandbox = specification.top_level_parent, sandbox
53
+ @top_specification, @sandbox, @platform = specification.top_level_parent, sandbox, platform
8
54
  @top_specification.activate_platform(platform)
9
55
  @specifications = [] << specification
10
56
  end
11
57
 
58
+ # Initializes a local pod from the top specification of a podspec file.
59
+ #
60
+ # @return [LocalPod] A new local pod.
61
+ #
12
62
  def self.from_podspec(podspec, sandbox, platform)
13
63
  new(Specification.from_file(podspec), sandbox, platform)
14
64
  end
15
65
 
16
- # Method to add the specifications sharing the same top level
17
- # parent. With this information the local pod can determine the
18
- # paths to clean and avoid duplication in file processing.
66
+ # Activates a specification or subspecs for the pod.
19
67
  # Adding specifications is idempotent.
68
+ #
69
+ # @param {Specification} spec The specification to add to the pod.
70
+ #
71
+ # @raise {Informative} If the specification is not part of the same pod.
72
+ #
20
73
  def add_specification(spec)
21
- raise Informative, "[Local Pod] Attempt to add a specification from another pod" unless spec.top_level_parent == top_specification
74
+ unless spec.top_level_parent == top_specification
75
+ raise Informative,
76
+ "[Local Pod] Attempt to add a specification from another pod"
77
+ end
22
78
  spec.activate_platform(platform)
23
79
  @specifications << spec unless @specifications.include?(spec)
24
80
  end
25
81
 
82
+ # @return [Pathname] The root directory of the pod
83
+ #
26
84
  def root
27
85
  @sandbox.root + top_specification.name
28
86
  end
29
87
 
30
- def subspecs
31
- specifications.reject{|s| s.parent.nil? }
32
- end
33
-
88
+ # @return [String] A string representation of the pod which indicates if
89
+ # the pods comes from a local source.
90
+ #
34
91
  def to_s
35
92
  result = top_specification.to_s
36
93
  result << " [LOCAL]" if top_specification.local?
37
94
  result
38
95
  end
39
96
 
97
+ # @return [String] The name of the Pod.
98
+ #
40
99
  def name
41
100
  top_specification.name
42
101
  end
43
102
 
44
- def platform
45
- top_specification.active_platform
46
- end
47
-
48
- # Installation methods
103
+ # @!group Installation
49
104
 
105
+ # Creates the root path of the pod.
106
+ #
107
+ # @return [void]
108
+ #
50
109
  def create
51
110
  root.mkpath unless exists?
52
111
  end
53
112
 
113
+ # Whether the root path of the pod exists.
114
+ #
54
115
  def exists?
55
116
  root.exist?
56
117
  end
57
118
 
119
+ # Executes a block in the root directory of the Pod.
120
+ #
121
+ # @return [void]
122
+ #
58
123
  def chdir(&block)
59
124
  create
60
125
  Dir.chdir(root, &block)
61
126
  end
62
127
 
128
+ # Deletes the pod from the file system.
129
+ #
130
+ # @return [void]
131
+ #
63
132
  def implode
64
133
  root.rmtree if exists?
65
134
  end
66
135
 
67
- ### Cleaning
136
+ # @!group Cleaning
68
137
 
69
- # Public: Deletes any path that is not used by the pod.
138
+ # Deletes any path that is not used by the pod.
139
+ #
140
+ # @return [void]
141
+ #
70
142
  def clean
71
143
  clean_paths.each { |path| FileUtils.rm_rf(path) }
144
+ @cleaned = true
72
145
  end
73
146
 
74
- # Public: Finds the absolute paths, including hidden ones, of the files
75
- # that are not used by the pod and can be safely deleted.
147
+ # Finds the absolute paths, including hidden ones, of the files
148
+ # that are not used by the pod and thus can be safely deleted.
149
+ #
150
+ # @return [Array<Strings>] The paths that can be deleted.
76
151
  #
77
- # Returns an Array of Strings containing the absolute paths.
78
152
  def clean_paths
79
- cached_used_paths = used_paths.map{ |path| path.to_s }
153
+ cached_used_paths = used_files
80
154
  files = Dir.glob(root + "**/*", File::FNM_DOTMATCH)
155
+
81
156
  files.reject! do |candidate|
82
- candidate.end_with?('.', '..') ||
83
- cached_used_paths.any? { |path| path.include?(candidate) || candidate.include?(path) }
157
+ candidate.end_with?('.', '..') || cached_used_paths.any? do |path|
158
+ path.include?(candidate) || candidate.include?(path)
159
+ end
84
160
  end
85
161
  files
86
162
  end
87
163
 
88
- # Public: Finds all the absolute paths used by pod.
164
+ # @return [Array<String>] The absolute path of the files used by the pod.
89
165
  #
90
- # Returns an Array of Pathnames containing the absolute paths.
91
- def used_paths
92
- files = source_files(false) + resources(false) + preserve_paths + [ readme_file, license_file, prefix_header_file ]
93
- files.compact
166
+ def used_files
167
+ files = [ source_files, resource_files, preserve_files, readme_file, license_file, prefix_header_file ]
168
+ files.compact!
169
+ files.flatten!
170
+ files.map!{ |path| path.to_s }
171
+ files
94
172
  end
95
173
 
96
- ### File attributes
174
+ # @!group Files
97
175
 
98
- def prefix_header_file
99
- root + top_specification.prefix_header_file if top_specification.prefix_header_file
176
+ # @return [Array<Pathname>] The paths of the source files.
177
+ #
178
+ def source_files
179
+ source_files_by_spec.values.flatten
180
+ end
181
+
182
+ # @return [Array<Pathname>] The *relative* paths of the source files.
183
+ #
184
+ def relative_source_files
185
+ source_files.map{ |p| p.relative_path_from(@sandbox.root) }
100
186
  end
101
187
 
102
- def source_files(relative = true)
103
- chained_expanded_paths(:source_files, :glob => '*.{h,m,mm,c,cpp}', :relative_to_sandbox => relative)
188
+ # Finds the source files that every activated {Specification} requires.
189
+ #
190
+ # @note If the same file is required by two specifications the one at the
191
+ # higher level in the inheritance chain wins.
192
+ #
193
+ # @return [Hash{Specification => Array<Pathname>}] The files grouped by
194
+ # {Specification}.
195
+ #
196
+ def source_files_by_spec
197
+ options = {:glob => '*.{h,m,mm,c,cpp}'}
198
+ paths_by_spec(:source_files, options)
104
199
  end
105
200
 
201
+ # @return [Array<Pathname>] The paths of the header files.
202
+ #
106
203
  def header_files
107
- source_files.select { |f| f.extname == '.h' }
204
+ header_files_by_spec.values.flatten
108
205
  end
109
206
 
110
- def resources(relative = true)
111
- chained_expanded_paths(:resources, :relative_to_sandbox => relative)
207
+ # @return [Array<Pathname>] The *relative* paths of the source files.
208
+ #
209
+ def relative_header_files
210
+ header_files.map{ |p| p.relative_path_from(@sandbox.root) }
112
211
  end
113
212
 
114
- # TODO: implement case insensitive search
115
- def preserve_paths
116
- chained_expanded_paths(:preserve_paths) + expanded_paths(%w[ *.podspec notice* NOTICE* CREDITS* ])
213
+ # @return [Hash{Specification => Array<Pathname>}] The paths of the header
214
+ # files grouped by {Specification}.
215
+ #
216
+ def header_files_by_spec
217
+ result = {}
218
+ source_files_by_spec.each do |spec, paths|
219
+ headers = paths.select { |f| f.extname == '.h' }
220
+ result[spec] = headers unless headers.empty?
221
+ end
222
+ result
223
+ end
224
+
225
+ # @return [Array<Pathname>] The paths of the resources.
226
+ #
227
+ def resource_files
228
+ paths_by_spec(:resources).values.flatten
229
+ end
230
+
231
+ # @return [Array<Pathname>] The *relative* paths of the resources.
232
+ #
233
+ def relative_resource_files
234
+ resource_files.map{ |p| p.relative_path_from(@sandbox.root) }
235
+ end
236
+
237
+ # @return [Pathname] The absolute path of the prefix header file
238
+ #
239
+ def prefix_header_file
240
+ root + top_specification.prefix_header_file if top_specification.prefix_header_file
117
241
  end
118
242
 
243
+ # @return [Array<Pathname>] The absolute paths of the files of the pod
244
+ # that should be preserved.
245
+ #
246
+ def preserve_files
247
+ paths = paths_by_spec(:preserve_paths).values
248
+ paths += expanded_paths(%w[ *.podspec notice* NOTICE* CREDITS* ])
249
+ paths.compact!
250
+ paths.uniq!
251
+ paths
252
+ end
253
+
254
+ # @return [Pathname] The automatically detected absolute path of the README
255
+ # file.
256
+ #
119
257
  def readme_file
120
258
  expanded_paths(%w[ README{*,.*} readme{*,.*} ]).first
121
259
  end
122
260
 
261
+ # @return [Pathname] The absolute path of the license file from the
262
+ # specification or automatically detected.
263
+ #
123
264
  def license_file
124
265
  if top_specification.license && top_specification.license[:file]
125
266
  root + top_specification.license[:file]
@@ -128,6 +269,9 @@ module Pod
128
269
  end
129
270
  end
130
271
 
272
+ # @return [String] The text of the license of the pod from the
273
+ # specification or from the license file.
274
+ #
131
275
  def license_text
132
276
  if (license_hash = top_specification.license)
133
277
  if (result = license_hash[:text])
@@ -142,88 +286,162 @@ module Pod
142
286
  specifications.map { |s| s.xcconfig }.reduce(:merge)
143
287
  end
144
288
 
145
- # Method used by documentation generator. It return the source files
146
- # of all the specs.
289
+ # Computes the paths of all the public headers of the pod including every
290
+ # subspec. For this reason the pod must not be cleaned before calling it.
291
+ #
292
+ # This method is used by {Generator::Documentation}.
293
+ #
294
+ # @raise [Informative] If the pod was cleaned.
295
+ #
296
+ # @todo Merge with #221
297
+ #
298
+ # @return [Array<Pathname>] The path of all the public headers of the pod.
299
+ #
147
300
  def all_specs_public_header_files
148
- #TODO: merge with #221
149
- specs = top_specification.recursive_subspecs << top_specification
150
- specs.map { |s| expanded_paths(s.source_files, :glob => '*.{h}') }.compact.flatten.select { |f| f.extname == '.h' }.uniq
301
+ if @cleaned
302
+ raise Informative, "The pod is cleaned and cannot compute the all the "\
303
+ "header files as they might be deleted."
304
+ end
305
+
306
+ all_specs = [ top_specification ] + top_specification.subspecs
307
+ options = {:glob => '*.{h}'}
308
+ files = paths_by_spec(:source_files, options, all_specs).values.flatten!
309
+ headers = files.select { |f| f.extname == '.h' }
310
+ headers
151
311
  end
152
312
 
153
- # Integration methods
313
+ # @!group Target integration
154
314
 
315
+ # @return [void] Copies the pods headers to the sandbox.
316
+ #
155
317
  def link_headers
156
- copy_header_mappings.each do |namespaced_path, files|
318
+ @sandbox.add_header_search_path(headers_sandbox)
319
+ header_mappings.each do |namespaced_path, files|
157
320
  @sandbox.add_header_files(namespaced_path, files)
158
321
  end
159
322
  end
160
323
 
161
- def add_to_target(target)
162
- sources_files_by_specification.each do | spec, files |
324
+ # @param [Xcodeproj::Project::Object::PBXNativeTarget] target
325
+ # The target to integrate.
326
+ #
327
+ # @return [void] Adds the pods source files to a given target.
328
+ #
329
+ def source_file_descriptions
330
+ result = []
331
+ source_files_by_spec.each do | spec, files |
332
+ compiler_flags = spec.compiler_flags.strip
163
333
  files.each do |file|
164
- # TODO: Xcodeproj::Project::Object::PBXNativeTarget#add_source_file is quite slow
165
- # The issus appears to be related to the find call in line 107.
166
- target.add_source_file(file, nil, spec.compiler_flags.strip)
334
+ file = file.relative_path_from(@sandbox.root)
335
+ desc = Xcodeproj::Project::PBXNativeTarget::SourceFileDescription.new(file, compiler_flags, nil)
336
+ result << desc
167
337
  end
168
338
  end
339
+ result
169
340
  end
170
341
 
342
+ # @return Whether the pod requires ARC.
343
+ #
171
344
  def requires_arc?
172
345
  top_specification.requires_arc
173
346
  end
174
347
 
175
348
  private
176
349
 
350
+ # @return [Array<Pathname>] The implementation files
351
+ # (the files the need to compiled) of the pod.
352
+ #
177
353
  def implementation_files
178
- source_files.select { |f| f.extname != '.h' }
354
+ relative_source_files.select { |f| f.extname != '.h' }
179
355
  end
180
356
 
357
+ # @return [Pathname] The path of the pod relative from the sandbox.
358
+ #
181
359
  def relative_root
182
360
  root.relative_path_from(@sandbox.root)
183
361
  end
184
362
 
185
- # TODO this is being overriden in the RestKit 0.9.4 spec, need to do
363
+ # @return Hash{Pathname => [Array<Pathname>]} A hash containing the headers
364
+ # folders as the keys and the the absolute paths of the header files
365
+ # as the values.
366
+ #
367
+ # @todo this is being overridden in the RestKit 0.9.4 spec, need to do
186
368
  # something with that, and this method also still exists in Specification.
187
369
  #
188
- # This is not overriden anymore in specification refactor and the code
189
- # Pod::Specification#copy_header_mapping can be moved here.
190
- def copy_header_mappings
191
- search_path_headers = header_files - headers_excluded_from_search_paths
192
- search_path_headers.inject({}) do |mappings, from|
193
- from_without_prefix = from.relative_path_from(relative_root)
194
- to = top_specification.header_dir + top_specification.copy_header_mapping(from_without_prefix)
195
- (mappings[to.dirname] ||= []) << from
196
- mappings
370
+ # @todo This is not overridden anymore in specification refactor and the
371
+ # code Pod::Specification#copy_header_mapping can be moved here.
372
+ def header_mappings
373
+ mappings = {}
374
+ header_files_by_spec.each do |spec, paths|
375
+ paths = paths - headers_excluded_from_search_paths
376
+ paths.each do |from|
377
+ from_relative = from.relative_path_from(root)
378
+ to = headers_sandbox + (spec.header_dir) + spec.copy_header_mapping(from_relative)
379
+ (mappings[to.dirname] ||= []) << from
380
+ end
197
381
  end
382
+ mappings
198
383
  end
199
384
 
200
- # returns an hash where the source_files are groupped by specification.
201
- # If the same file is required by two specifications the one at the
202
- # higher level in the inheritance chain wins.
203
- def sources_files_by_specification
204
- files_by_spec = {}
205
- processed_files = []
206
- specifications.sort_by { |s| s.name.length }.each do |spec|
207
- files = []
208
- expanded_paths(spec.source_files, :glob => '*.{h,m,mm,c,cpp}', :relative_to_sandbox => true).each do | file |
209
- files << file unless processed_files.include?(file)
210
- end
211
- files_by_spec[spec] = files
212
- processed_files += files
213
- end
214
- files_by_spec
385
+ def headers_sandbox
386
+ @headers_sandbox ||= Pathname.new(top_specification.name)
215
387
  end
216
388
 
389
+ # @return [<Pathname>] The relative path of the headers that should not be
390
+ # included in the linker search paths.
391
+ #
217
392
  def headers_excluded_from_search_paths
218
- chained_expanded_paths(:exclude_header_search_paths, :glob => '*.h', :relative_to_sandbox => true)
393
+ options = { :glob => '*.h' }
394
+ paths = paths_by_spec(:exclude_header_search_paths, options)
395
+ paths.values.compact.uniq
219
396
  end
220
397
 
221
- def chained_expanded_paths(accessor, options = {})
222
- specifications.map { |s| expanded_paths(s.send(accessor), options) }.compact.flatten.uniq
398
+ # @!group Paths Patterns
399
+
400
+ # The paths obtained by resolving the patterns of an attribute
401
+ # groupped by spec.
402
+ #
403
+ # @param [Symbol] accessor The accessor to use to obtain the paths patterns.
404
+ # @param [Hash] options (see #expanded_paths)
405
+ #
406
+ def paths_by_spec(accessor, options = {}, specs = nil)
407
+ specs ||= specifications
408
+ paths_by_spec = {}
409
+ processed_paths = []
410
+
411
+ specs = specs.sort_by { |s| s.name.length }
412
+ specs.each do |spec|
413
+ paths = expanded_paths(spec.send(accessor), options)
414
+ unless paths.empty?
415
+ paths_by_spec[spec] = paths - processed_paths
416
+ processed_paths += paths
417
+ end
418
+ end
419
+ paths_by_spec
223
420
  end
224
421
 
422
+ # Converts patterns of paths to the {Pathname} of the files present in the
423
+ # pod.
424
+ #
425
+ # @param [String, FileList, Array<String, Pathname>] patterns
426
+ # The patterns to expand.
427
+ # @param [Hash] options
428
+ # The options to used for expanding the paths patterns.
429
+ # @option options [String] :glob
430
+ # The pattern to use for globing directories.
431
+ #
432
+ # @raise [Informative] If the pod does not exists.
433
+ #
434
+ # @todo implement case insensitive search
435
+ #
436
+ # @return [Array<Pathname>] A list of the paths.
437
+ #
225
438
  def expanded_paths(patterns, options = {})
226
- raise Informative, "[Local Pod] Attempt to resolve paths for non existent pod." unless exists?
439
+ unless exists?
440
+ raise Informative, "[Local Pod] Attempt to resolve paths for nonexistent pod.\n" \
441
+ "\tSpecifications: #{@specifications.inspect}\n" \
442
+ "\t Patterns: #{patterns.inspect}\n" \
443
+ "\t Options: #{options.inspect}"
444
+ end
227
445
 
228
446
  patterns = [ patterns ] if patterns.is_a? String
229
447
  patterns.map do |pattern|
@@ -234,11 +452,7 @@ module Pod
234
452
  end
235
453
 
236
454
  pattern.glob.map do |file|
237
- if options[:relative_to_sandbox]
238
- file.relative_path_from(@sandbox.root)
239
- else
240
- file
241
- end
455
+ file
242
456
  end
243
457
  end.flatten
244
458
  end
@@ -1,68 +1,140 @@
1
1
  module Pod
2
+
3
+ # A platform describes an SDK name and deployment target.
4
+ #
2
5
  class Platform
6
+
7
+ # @return [Platform] Convenience method to initialize an iOS platform.
8
+ #
3
9
  def self.ios
4
10
  new :ios
5
11
  end
6
12
 
13
+ # @return [Platform] Convenience method to initialize an OS X platform.
14
+ #
7
15
  def self.osx
8
16
  new :osx
9
17
  end
10
18
 
11
- attr_reader :deployment_target
19
+ # Constructs a platform from either another platform or by
20
+ # specifying the symbolic name and optionally the deployment target.
21
+ #
22
+ # @overload initialize(name, deployment_target)
23
+ # @param [Symbol] name The name of platform.
24
+ # @param [String, Version] deployment_target The optional deployment.
25
+ # If not provided a default value according to the platform name will
26
+ # be assigned.
27
+ #
28
+ # @note that if the name is not specified a default deployment
29
+ # target will not be assigned.
30
+ #
31
+ # @example
32
+ #
33
+ # Platform.new(:ios)
34
+ # Platform.new(:ios, '4.3')
35
+ #
36
+ # @overload initialize(name, opts)
37
+ # @deprecated Remove after adding a warning to {Podfile} class.
38
+ # @param [Symbol] name The name of platform.
39
+ # @param [Hash] opts The options to create a platform with.
40
+ # @option opts [String, Version] :deployment_target The deployment target.
41
+ #
42
+ # @overload initialize(platform)
43
+ # @param [Platform] platform Another {Platform}.
44
+ #
45
+ # @example
46
+ #
47
+ # platform = Platform.new(:ios)
48
+ # Platform.new(platform)
49
+ #
50
+ def initialize(input, target = nil)
51
+ if input.is_a? Platform
52
+ @symbolic_name = input.name
53
+ @deployment_target = input.deployment_target
54
+ @declared_deployment_target = input.declared_deployment_target
55
+ else
56
+ @symbolic_name = input
57
+
58
+ target = target[:deployment_target] if target.is_a?(Hash)
59
+ @declared_deployment_target = target
12
60
 
13
- def initialize(symbolic_name = nil, deployment_target = nil)
14
- @symbolic_name = symbolic_name
15
- if deployment_target
16
- version = deployment_target.is_a?(Hash) ? deployment_target[:deployment_target] : deployment_target # backwards compatibility from 0.6
17
- @deployment_target = Pod::Version.create(version)
61
+ unless target
62
+ case @symbolic_name
63
+ when :ios
64
+ target = '4.3'
65
+ when :osx
66
+ target = '10.6'
67
+ else
68
+ target = ''
69
+ end
70
+ end
71
+ @deployment_target = Version.create(target)
18
72
  end
19
73
  end
20
74
 
75
+ # @return [Symbol] The name of the SDK represented by the platform.
76
+ #
21
77
  def name
22
78
  @symbolic_name
23
79
  end
24
80
 
25
- def deployment_target= (version)
26
- @deployment_target = Pod::Version.create(version)
27
- end
81
+ # @return [Version] The deployment target of the platform.
82
+ #
83
+ attr_reader :deployment_target
84
+
85
+ # @return [Version] The deployment target declared on initialization.
86
+ #
87
+ attr_reader :declared_deployment_target
28
88
 
29
- def ==(other_platform_or_symbolic_name)
30
- if other_platform_or_symbolic_name.is_a?(Symbol)
31
- @symbolic_name == other_platform_or_symbolic_name
89
+ # @param [Platform, Symbol] other The other platform to check.
90
+ #
91
+ # @note If a symbol is passed the comparison does not take into account
92
+ # the deployment target.
93
+ #
94
+ # @return [Boolean] Whether two platforms are the equivalent.
95
+ #
96
+ def ==(other)
97
+ if other.is_a?(Symbol)
98
+ @symbolic_name == other
32
99
  else
33
- self.name == (other_platform_or_symbolic_name.name) && self.deployment_target == other_platform_or_symbolic_name.deployment_target
100
+ (name == other.name) && (deployment_target == other.deployment_target)
34
101
  end
35
102
  end
36
103
 
104
+ # In the context of operating system SDKs, a platform supports another
105
+ # one if they have the same name and the other platform has a minor or
106
+ # equal deployment target.
107
+ #
108
+ # @return Whether the platform supports another platform.
109
+ #
37
110
  def supports?(other)
38
- return true if @symbolic_name.nil? || other.nil?
39
- os_check = @symbolic_name == other.name
40
- version_check = (deployment_target.nil? || other.deployment_target.nil? || deployment_target >= other.deployment_target)
41
- os_check && version_check
111
+ other = Platform.new(other)
112
+ (other.name == name) && (other.deployment_target <= deployment_target)
42
113
  end
43
114
 
115
+ # @return [String] A string representation including the deployment target.
116
+ #
44
117
  def to_s
45
118
  case @symbolic_name
46
119
  when :ios
47
- 'iOS' + (deployment_target ? " #{deployment_target}" : '')
120
+ s = 'iOS'
48
121
  when :osx
49
- 'OS X' + (deployment_target ? " #{deployment_target}" : '')
50
- else
51
- 'iOS - OS X'
122
+ s = 'OS X'
52
123
  end
124
+ s << " #{declared_deployment_target}" if declared_deployment_target
125
+ s
53
126
  end
54
127
 
128
+ # @return [Symbol] A Symbol representation of the name.
129
+ #
55
130
  def to_sym
56
131
  name
57
132
  end
58
133
 
59
- def nil?
60
- name.nil?
61
- end
62
-
134
+ # @return Whether the platform requires legacy architectures for iOS.
135
+ #
63
136
  def requires_legacy_ios_archs?
64
- return unless deployment_target
65
- (name == :ios) && (deployment_target < Pod::Version.new("4.3"))
137
+ (name == :ios) && (deployment_target < Version.new("4.3"))
66
138
  end
67
139
  end
68
140
  end
@@ -153,7 +153,10 @@ module Pod
153
153
 
154
154
  def self.from_file(path)
155
155
  podfile = Podfile.new do
156
- eval(path.read, nil, path.to_s)
156
+ string = File.open(path, 'r:utf-8') { |f| f.read }
157
+ # TODO: work around for Rubinius incomplete encoding in 1.9 mode
158
+ string.encode!('UTF-8') if string.respond_to?(:encoding) && string.encoding.name != "UTF-8"
159
+ eval(string, nil, path.to_s)
157
160
  end
158
161
  podfile.defined_in_file = path
159
162
  podfile.validate!
@@ -332,12 +335,14 @@ module Pod
332
335
  # Pod::Specification is yielded to the block. This is the same class which
333
336
  # is normally used to specify a Pod.
334
337
  #
338
+ # ```
335
339
  # dependency do |spec|
336
340
  # spec.name = 'JSONKit'
337
341
  # spec.version = '1.4'
338
342
  # spec.source = { :git => 'https://github.com/johnezang/JSONKit.git', :tag => 'v1.4' }
339
343
  # spec.source_files = 'JSONKit.*'
340
344
  # end
345
+ # ```
341
346
  #
342
347
  #
343
348
  # For more info on the definition of a Pod::Specification see:
@@ -455,10 +460,6 @@ module Pod
455
460
  end
456
461
 
457
462
  def validate!
458
- #lines = []
459
- #lines << "* the `platform` attribute should be either `:osx` or `:ios`" unless @platform && [:osx, :ios].include?(@platform.name)
460
- #lines << "* no dependencies were specified, which is, well, kinda pointless" if dependencies.empty?
461
- #raise(Informative, (["The Podfile at `#{@defined_in_file}' is invalid:"] + lines).join("\n")) unless lines.empty?
462
463
  end
463
464
  end
464
465
  end
@@ -42,6 +42,16 @@ module Pod
42
42
  @header_search_paths.uniq.map { |path| "${PODS_ROOT}/#{path}" }
43
43
  end
44
44
 
45
+ # Adds an header search path to the sandbox.
46
+ #
47
+ # @param path [Pathname] The path tho add.
48
+ #
49
+ # @return [void]
50
+ #
51
+ def add_header_search_path(path)
52
+ @header_search_paths << Pathname.new(HEADERS_DIR) + path
53
+ end
54
+
45
55
  def prepare_for_install
46
56
  headers_root.rmtree if headers_root.exist?
47
57
  end
@@ -4,7 +4,10 @@ module Pod
4
4
  extend Config::Mixin
5
5
 
6
6
  def self._eval_podspec(path)
7
- eval(path.read, nil, path.to_s)
7
+ string = File.open(path, 'r:utf-8') { |f| f.read }
8
+ # TODO: work around for Rubinius incomplete encoding in 1.9 mode
9
+ string.encode!('UTF-8') if string.respond_to?(:encoding) && string.encoding.name != "UTF-8"
10
+ eval(string, nil, path.to_s)
8
11
  end
9
12
 
10
13
  class Specification
@@ -35,10 +38,18 @@ module Pod
35
38
  end
36
39
 
37
40
  # multi-platform attributes
38
- %w[ source_files resources preserve_paths exclude_header_search_paths frameworks libraries dependencies compiler_flags].each do |attr|
41
+ %w[ source_files
42
+ resources
43
+ preserve_paths
44
+ exclude_header_search_paths
45
+ frameworks
46
+ libraries
47
+ dependencies
48
+ compiler_flags ].each do |attr|
39
49
  instance_variable_set( "@#{attr}", { :ios => [], :osx => [] } )
40
50
  end
41
51
  @xcconfig = { :ios => Xcodeproj::Config.new, :osx => Xcodeproj::Config.new }
52
+ @header_dir = { :ios => nil, :osx => nil }
42
53
 
43
54
  yield self if block_given?
44
55
  end
@@ -58,7 +69,7 @@ module Pod
58
69
  # be passed to initalize the value
59
70
  def self.top_attr_writer(attr, init_lambda = nil)
60
71
  define_method("#{attr}=") do |value|
61
- raise Informative, "Can't set `#{attr}' for subspecs." if @parent
72
+ raise Informative, "#{self.inspect} Can't set `#{attr}' for subspecs." if @parent
62
73
  instance_variable_set("@#{attr}", init_lambda ? init_lambda.call(value) : value);
63
74
  end
64
75
  end
@@ -119,6 +130,7 @@ module Pod
119
130
  libraries=
120
131
  compiler_flags=
121
132
  deployment_target=
133
+ header_dir=
122
134
  dependency }.each do |method|
123
135
  define_method(method) do |args|
124
136
  @specification._on_platform(@platform) do
@@ -180,16 +192,10 @@ module Pod
180
192
  top_attr_accessor :license, lambda { |l| ( l.kind_of? String ) ? { :type => l } : l }
181
193
  top_attr_accessor :version, lambda { |v| Version.new(v) }
182
194
  top_attr_accessor :authors, lambda { |a| parse_authors(a) }
183
- top_attr_accessor :header_mappings_dir, lambda { |file| Pathname.new(file) } # If not provided the headers files are flattened
184
- top_attr_accessor :prefix_header_file, lambda { |file| Pathname.new(file) }
185
- top_attr_accessor :prefix_header_contents
186
195
 
187
196
  top_attr_reader :description, lambda {|instance, ivar| ivar || instance.summary }
188
197
  top_attr_writer :description
189
198
 
190
- top_attr_reader :header_dir, lambda {|instance, ivar| ivar || instance.pod_destroot_name }
191
- top_attr_writer :header_dir, lambda {|dir| Pathname.new(dir) }
192
-
193
199
  alias_method :author=, :authors=
194
200
 
195
201
  def self.parse_authors(*names_and_email_addresses)
@@ -203,6 +209,13 @@ module Pod
203
209
 
204
210
  ### Attributes **with** multiple platform support
205
211
 
212
+ # @todo allow for subspecs
213
+ #
214
+ top_attr_accessor :header_mappings_dir, lambda { |file| Pathname.new(file) } # If not provided the headers files are flattened
215
+ top_attr_accessor :prefix_header_file, lambda { |file| Pathname.new(file) }
216
+ top_attr_accessor :prefix_header_contents
217
+
218
+
206
219
  pltf_chained_attr_accessor :source_files, lambda {|value, current| pattern_list(value) }
207
220
  pltf_chained_attr_accessor :resources, lambda {|value, current| pattern_list(value) }
208
221
  pltf_chained_attr_accessor :preserve_paths, lambda {|value, current| pattern_list(value) } # Paths that should not be cleaned
@@ -215,7 +228,28 @@ module Pod
215
228
  alias_method :framework=, :frameworks=
216
229
  alias_method :library=, :libraries=
217
230
 
218
- platform_attr_writer :xcconfig, lambda {|value, current| current.tap { |c| c.merge!(value) } }
231
+ # @!method header_dir=
232
+ #
233
+ # @abstract The directory where to name space the headers files of
234
+ # the specification.
235
+ #
236
+ # @param [String] The headers directory.
237
+ #
238
+ platform_attr_writer :header_dir, lambda { |dir, _| Pathname.new(dir) }
239
+
240
+ # @abstract (see #header_dir=)
241
+ #
242
+ # @return [Pathname] The headers directory.
243
+ #
244
+ # @note If no value is provided it returns an empty {Pathname}.
245
+ #
246
+ def header_dir
247
+ @header_dir[active_platform] || (@parent.header_dir if @parent) || Pathname.new('')
248
+ end
249
+
250
+ # @!method xcconfig=
251
+ #
252
+ platform_attr_writer :xcconfig, lambda {|value, current| current.tap { |c| c.merge!(value) } }
219
253
 
220
254
  def xcconfig
221
255
  raw_xconfig.dup.
@@ -338,12 +372,6 @@ module Pod
338
372
  end
339
373
  end
340
374
 
341
- def pod_destroot_name
342
- if root = pod_destroot
343
- root.basename
344
- end
345
- end
346
-
347
375
  def self.pattern_list(patterns)
348
376
  if patterns.is_a?(Array) && (!defined?(Rake) || !patterns.is_a?(Rake::FileList))
349
377
  patterns
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cocoapods
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0.rc2
4
+ version: 0.6.0.rc3
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-06 00:00:00.000000000 Z
12
+ date: 2012-06-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: faraday
@@ -34,7 +34,7 @@ dependencies:
34
34
  requirements:
35
35
  - - ~>
36
36
  - !ruby/object:Gem::Version
37
- version: 1.3.0
37
+ version: 1.7.0
38
38
  type: :runtime
39
39
  prerelease: false
40
40
  version_requirements: !ruby/object:Gem::Requirement
@@ -42,7 +42,7 @@ dependencies:
42
42
  requirements:
43
43
  - - ~>
44
44
  - !ruby/object:Gem::Version
45
- version: 1.3.0
45
+ version: 1.7.0
46
46
  - !ruby/object:Gem::Dependency
47
47
  name: colored
48
48
  requirement: !ruby/object:Gem::Requirement
@@ -130,7 +130,7 @@ dependencies:
130
130
  requirements:
131
131
  - - ~>
132
132
  - !ruby/object:Gem::Version
133
- version: 0.2.0.rc1
133
+ version: 0.2.0.rc3
134
134
  type: :runtime
135
135
  prerelease: false
136
136
  version_requirements: !ruby/object:Gem::Requirement
@@ -138,7 +138,7 @@ dependencies:
138
138
  requirements:
139
139
  - - ~>
140
140
  - !ruby/object:Gem::Version
141
- version: 0.2.0.rc1
141
+ version: 0.2.0.rc3
142
142
  - !ruby/object:Gem::Dependency
143
143
  name: bacon
144
144
  requirement: !ruby/object:Gem::Requirement
@@ -220,8 +220,7 @@ files:
220
220
  homepage: https://github.com/CocoaPods/CocoaPods
221
221
  licenses:
222
222
  - MIT
223
- post_install_message: ! '[!] If this is your first time install of CocoaPods, or if
224
- you are upgrading, first run: $ pod setup'
223
+ post_install_message:
225
224
  rdoc_options: []
226
225
  require_paths:
227
226
  - lib
@@ -233,7 +232,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
233
232
  version: '0'
234
233
  segments:
235
234
  - 0
236
- hash: -4185987676698712042
235
+ hash: -4255808977828615188
237
236
  required_rubygems_version: !ruby/object:Gem::Requirement
238
237
  none: false
239
238
  requirements:
@@ -247,3 +246,4 @@ signing_key:
247
246
  specification_version: 3
248
247
  summary: An Objective-C library package manager.
249
248
  test_files: []
249
+ has_rdoc: