cocoapods-core 0.39.0 → 1.0.0.beta.1

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.
@@ -19,17 +19,11 @@ module Pod
19
19
  # @param [TargetDefinition] parent
20
20
  # @see parent
21
21
  #
22
- # @option options [Bool] :exclusive
23
- # @see exclusive?
24
- #
25
22
  def initialize(name, parent, internal_hash = nil)
26
23
  @internal_hash = internal_hash || {}
27
24
  @parent = parent
28
25
  @children = []
29
-
30
- unless internal_hash
31
- self.name = name
32
- end
26
+ self.name ||= name
33
27
  if parent.is_a?(TargetDefinition)
34
28
  parent.children << self
35
29
  end
@@ -73,13 +67,25 @@ module Pod
73
67
  # definition including the inherited ones.
74
68
  #
75
69
  def dependencies
76
- if exclusive? || parent.nil?
70
+ if exclusive?
77
71
  non_inherited_dependencies
78
72
  else
79
73
  non_inherited_dependencies + parent.dependencies
80
74
  end
81
75
  end
82
76
 
77
+ # @return [Array<TargetDefinition>] the targets from which this target
78
+ # definition should inherit only search paths.
79
+ #
80
+ def targets_to_inherit_search_paths
81
+ return [] unless inheritance == 'search_paths'
82
+ if root? || !matches_platform?(parent)
83
+ raise StandardError, "Non-sensical to have search_paths inheritance for #{name} when there is no parent."
84
+ else
85
+ parent.targets_to_inherit_search_paths << parent
86
+ end
87
+ end
88
+
83
89
  # @return [Array] The list of the dependencies of the target definition,
84
90
  # excluding inherited ones.
85
91
  #
@@ -142,83 +148,81 @@ module Pod
142
148
 
143
149
  #--------------------------------------#
144
150
 
145
- # Returns whether the target definition should inherit the dependencies
146
- # of the parent.
151
+ # @return [Boolean] whether this target definition is abstract.
147
152
  #
148
- # @note A target is always `exclusive` if it is root.
149
- #
150
- # @note A target is always `exclusive` if the `platform` does
151
- # not match the parent's `platform`.
152
- #
153
- # @return [Bool] whether is exclusive.
154
- #
155
- def exclusive?
156
- if root?
157
- true
158
- elsif get_hash_value('exclusive')
159
- true
160
- else
161
- platform && parent && parent.platform != platform
162
- end
153
+ def abstract?
154
+ get_hash_value('abstract', false)
163
155
  end
164
156
 
165
- # Sets whether the target definition is exclusive.
157
+ # Sets whether this target definition is abstract.
166
158
  #
167
- # @param [Bool] flag
168
- # Whether the definition is exclusive.
159
+ # @param [Boolean] abstract
160
+ # whether this target definition is abstract.
169
161
  #
170
162
  # @return [void]
171
163
  #
172
- def exclusive=(flag)
173
- set_hash_value('exclusive', flag)
164
+ def abstract=(abstract)
165
+ set_hash_value('abstract', abstract)
174
166
  end
175
167
 
176
168
  #--------------------------------------#
177
169
 
178
- # @return [Array<String>] The list of the names of the Xcode targets with
179
- # which this target definition should be linked with.
170
+ # @return [String] the inheritance mode for this target definition.
180
171
  #
181
- def link_with
182
- value = get_hash_value('link_with')
183
- value unless value.nil? || value.empty?
172
+ def inheritance
173
+ get_hash_value('inheritance', 'complete')
184
174
  end
185
175
 
186
- # Sets the client targets that should be integrated by this definition.
176
+ # Sets the inheritance mode for this target definition.
177
+ #
178
+ # @param [#to_s] inheritance
179
+ # the inheritance mode for this target definition.
187
180
  #
188
- # @param [Array<String>] targets
189
- # The list of the targets names.
181
+ # @raise [Informative] if this target definition is a root target
182
+ # definition or if the `inheritance` value is unknown.
190
183
  #
191
184
  # @return [void]
192
185
  #
193
- def link_with=(targets)
194
- set_hash_value('link_with', Array(targets).map(&:to_s))
186
+ def inheritance=(inheritance)
187
+ inheritance = inheritance.to_s
188
+ unless %w(none search_paths complete).include?(inheritance)
189
+ raise Informative, "Unrecognized inheritance option `#{inheritance}` specified for target `#{name}`."
190
+ end
191
+ if root?
192
+ raise Informative, 'Cannot set inheritance for the root target definition.'
193
+ end
194
+ set_hash_value('inheritance', inheritance)
195
195
  end
196
196
 
197
197
  #--------------------------------------#
198
198
 
199
- # Returns whether the target definition should link with the first target
200
- # of the project.
199
+ # Returns whether the target definition should inherit the dependencies
200
+ # of the parent.
201
+ #
202
+ # @note A target is always `exclusive` if it is root.
201
203
  #
202
- # @note This option is ignored if {link_with} is set.
204
+ # @note A target is always `exclusive` if the `platform` does
205
+ # not match the parent's `platform`.
203
206
  #
204
207
  # @return [Bool] whether is exclusive.
205
208
  #
206
- def link_with_first_target?
207
- get_hash_value('link_with_first_target') unless link_with
209
+ def exclusive?
210
+ if root?
211
+ true
212
+ else
213
+ !matches_platform?(parent) || (inheritance != 'complete')
214
+ end
208
215
  end
209
216
 
210
- # Sets whether the target definition should link with the first target of
211
- # the project.
212
- #
213
- # @note This option is ignored if {link_with} is set.
217
+ # @param [TargetDefinition, Nil] target_definition
218
+ # the target definition to check for platform compatibility.
214
219
  #
215
- # @param [Bool] flag
216
- # Whether the definition should link with the first target.
217
- #
218
- # @return [void]
220
+ # @return [Boolean]
221
+ # whether this target definition matches the platform of
222
+ # `target_definition`.
219
223
  #
220
- def link_with_first_target=(flag)
221
- set_hash_value('link_with_first_target', flag)
224
+ def matches_platform?(target_definition)
225
+ target_definition && target_definition.platform == platform
222
226
  end
223
227
 
224
228
  #--------------------------------------#
@@ -229,7 +233,7 @@ module Pod
229
233
  def user_project_path
230
234
  path = get_hash_value('user_project_path')
231
235
  if path
232
- File.extname(path) == '.xcodeproj' ? path : "#{path}.xcodeproj"
236
+ Pathname(path).sub_ext('.xcodeproj').to_path
233
237
  else
234
238
  parent.user_project_path unless root?
235
239
  end
@@ -368,7 +372,7 @@ module Pod
368
372
  end
369
373
  end
370
374
  end
371
- !found
375
+ !found && (root? || (inheritance != 'none' && parent.pod_whitelisted_for_configuration?(pod_name, configuration_name)))
372
376
  end
373
377
 
374
378
  # Whitelists a pod for a specific configuration. If a pod is whitelisted
@@ -396,7 +400,8 @@ module Pod
396
400
  # pods have been whitelisted.
397
401
  #
398
402
  def all_whitelisted_configurations
399
- configuration_pod_whitelist.keys.uniq
403
+ parent_configurations = (root? || inheritance == 'none') ? [] : parent.all_whitelisted_configurations
404
+ (configuration_pod_whitelist.keys + parent_configurations).uniq
400
405
  end
401
406
 
402
407
  #--------------------------------------#
@@ -496,7 +501,7 @@ module Pod
496
501
  # @note The storage of this information is optimized for YAML
497
502
  # readability.
498
503
  #
499
- # @todo This needs urgently a rename.
504
+ # @todo This urgently needs a rename.
500
505
  #
501
506
  # @return [void]
502
507
  #
@@ -535,6 +540,8 @@ module Pod
535
540
  children
536
541
  configuration_pod_whitelist
537
542
  uses_frameworks
543
+ inheritance
544
+ abstract
538
545
  ).freeze
539
546
 
540
547
  # @return [Hash] The hash representation of the target definition.
@@ -588,7 +595,7 @@ module Pod
588
595
  # @param [Object] value
589
596
  # The value to store.
590
597
  #
591
- # @raise If the key is not recognized.
598
+ # @raise [StandardError] If the key is not recognized.
592
599
  #
593
600
  # @return [void]
594
601
  #
@@ -608,7 +615,7 @@ module Pod
608
615
  # @param [Object] base_value
609
616
  # The value to set if they key is nil. Useful for collections.
610
617
  #
611
- # @raise If the key is not recognized.
618
+ # @raise [StandardError] If the key is not recognized.
612
619
  #
613
620
  # @return [Object] The value for the key.
614
621
  #
@@ -625,7 +632,12 @@ module Pod
625
632
  # warnings, and :for_pods key for inhibiting warnings per Pod.
626
633
  #
627
634
  def inhibit_warnings_hash
628
- get_hash_value('inhibit_warnings', {})
635
+ inhibit_hash = get_hash_value('inhibit_warnings', {})
636
+ if exclusive?
637
+ inhibit_hash
638
+ else
639
+ parent.send(:inhibit_warnings_hash).merge(inhibit_hash) { |l, r| (l + r).uniq }
640
+ end
629
641
  end
630
642
 
631
643
  # Returns the configuration_pod_whitelist hash
@@ -635,7 +647,12 @@ module Pod
635
647
  # as value.
636
648
  #
637
649
  def configuration_pod_whitelist
638
- get_hash_value('configuration_pod_whitelist', {})
650
+ whitelist_hash = get_hash_value('configuration_pod_whitelist', {})
651
+ if exclusive?
652
+ whitelist_hash
653
+ else
654
+ parent.send(:configuration_pod_whitelist).merge(whitelist_hash) { |l, r| (l + r).uniq }
655
+ end
639
656
  end
640
657
 
641
658
  # @return [Array<Dependency>] The dependencies specified by the user for
@@ -656,8 +673,8 @@ module Pod
656
673
 
657
674
  # @return [Array<Dependency>] The dependencies inherited by the podspecs.
658
675
  #
659
- # @note The podspec directive is intended include the dependencies of a
660
- # spec in the project where it is developed. For this reason the
676
+ # @note The podspec directive is intended to include the dependencies of
677
+ # a spec in the project where it is developed. For this reason the
661
678
  # spec, or any of it subspecs, cannot be included in the
662
679
  # dependencies. Otherwise it would generate a chicken-and-egg
663
680
  # problem.
@@ -744,15 +761,13 @@ module Pod
744
761
 
745
762
  configurations = options.delete(:configurations)
746
763
  configurations ||= options.delete(:configuration)
747
- if configurations
748
- Array(configurations).each do |configuration|
749
- whitelist_pod_for_configuration(name, configuration)
750
- end
764
+ Array(configurations).each do |configuration|
765
+ whitelist_pod_for_configuration(name, configuration)
751
766
  end
752
767
  requirements.pop if options.empty?
753
768
  end
754
769
 
755
- # Removes :subspecs form the requirements list, and stores the pods
770
+ # Removes :subspecs from the requirements list, and stores the pods
756
771
  # with the given subspecs as dependencies.
757
772
  #
758
773
  # @param [String] name
@@ -93,6 +93,22 @@ module Pod
93
93
  end.sort
94
94
  end
95
95
 
96
+ # Returns pod names for given array of specification paths.
97
+ #
98
+ # @param [Array<String>] spec_paths
99
+ # Array of file path names for specifications. Path strings should be relative to the source path.
100
+ #
101
+ # @return [Array<String>] the list of the name of Pods corresponding to specification paths.
102
+ #
103
+ def pods_for_specification_paths(spec_paths)
104
+ spec_paths.map do |path|
105
+ absolute_path = repo + path
106
+ relative_path = absolute_path.relative_path_from(specs_dir)
107
+ # The first file name returned by 'each_filename' is the pod name
108
+ relative_path.each_filename.first
109
+ end
110
+ end
111
+
96
112
  # @return [Array<Version>] all the available versions for the Pod, sorted
97
113
  # from highest to lowest.
98
114
  #
@@ -259,6 +275,26 @@ module Pod
259
275
  end
260
276
  end
261
277
 
278
+ # @!group Updating the source
279
+ #-------------------------------------------------------------------------#
280
+
281
+ # Updates the local clone of the source repo.
282
+ #
283
+ # @param [Bool] show_output
284
+ #
285
+ # @return [Array<String>] changed_spec_paths
286
+ # Returns the list of changed spec paths.
287
+ #
288
+ def update(show_output)
289
+ changed_spec_paths = []
290
+ Dir.chdir(repo) do
291
+ prev_commit_hash = git_commit_hash
292
+ update_git_repo(show_output)
293
+ changed_spec_paths = diff_until_commit_hash(prev_commit_hash)
294
+ end
295
+ changed_spec_paths
296
+ end
297
+
262
298
  public
263
299
 
264
300
  # @!group Representations
@@ -312,7 +348,7 @@ module Pod
312
348
  #
313
349
  # @note In previous versions of CocoaPods they used to be stored in
314
350
  # the root of the repo. This lead to issues, especially with
315
- # the GitHub interface and now the are stored in a dedicated
351
+ # the GitHub interface and now they are stored in a dedicated
316
352
  # folder.
317
353
  #
318
354
  def specs_dir
@@ -326,6 +362,19 @@ module Pod
326
362
  end
327
363
  end
328
364
 
365
+ def git_commit_hash
366
+ (`git rev-parse HEAD` || '').strip
367
+ end
368
+
369
+ def update_git_repo(show_output = false)
370
+ output = `git pull --ff-only 2>&1`
371
+ CoreUI.puts output if show_output
372
+ end
373
+
374
+ def diff_until_commit_hash(commit_hash)
375
+ (`git diff --name-only #{commit_hash}..HEAD` || '').strip.split("\n")
376
+ end
377
+
329
378
  #-------------------------------------------------------------------------#
330
379
  end
331
380
  end
@@ -53,7 +53,7 @@ module Pod
53
53
  # The name of the Pod.
54
54
  #
55
55
  # @return [Set] The most representative set for the Pod with the given
56
- # name.
56
+ # name. Returns nil if no representative source found containing a pod with given name.
57
57
  #
58
58
  def representative_set(name)
59
59
  representative_source = nil
@@ -68,7 +68,7 @@ module Pod
68
68
  end
69
69
  end
70
70
  end
71
- Specification::Set.new(name, representative_source)
71
+ representative_source ? Specification::Set.new(name, representative_source) : nil
72
72
  end
73
73
 
74
74
  public
@@ -129,57 +129,35 @@ module Pod
129
129
  # @!group Search Index
130
130
  #-----------------------------------------------------------------------#
131
131
 
132
- # Generates from scratch the search data for all the sources of the
133
- # aggregate. This operation can take a considerable amount of time
132
+ # Generates from scratch the search data for given source.
133
+ # This operation can take a considerable amount of time
134
134
  # (seconds) as it needs to evaluate the most representative podspec
135
135
  # for each Pod.
136
136
  #
137
- # @return [Hash{String=>Hash}] The search data of every set grouped by
138
- # name.
137
+ # @param [Source] source
138
+ # The source from which a search index will be generated.
139
139
  #
140
- def generate_search_index
141
- result = {}
142
- all_sets.each do |set|
143
- result[set.name] = search_data_from_set(set)
144
- end
145
- result
140
+ # @return [Hash{String=>Hash}] The search data for the source.
141
+ #
142
+ def generate_search_index_for_source(source)
143
+ generate_search_index_for_sets(source.pod_sets)
146
144
  end
147
145
 
148
- # Updates inline the given search data with the information stored in all
149
- # the sources. The update skips the Pods for which the version of the
150
- # search data is the same of the highest version known to the aggregate.
151
- # This can lead to updates in podspecs being skipped until a new version
152
- # is released.
153
- #
154
- # @note This procedure is considerably faster as it only needs to
155
- # load the most representative spec of the new or updated Pods.
156
- #
157
- # @return [Hash{String=>Hash}] The search data of every set grouped by
158
- # name.
159
- #
160
- def update_search_index(search_data)
161
- enumerated_names = []
162
- all_sets.each do |set|
163
- enumerated_names << set.name
164
- set_data = search_data[set.name]
165
- has_data = set_data && set_data['version']
166
- if has_data
167
- stored_version = Version.new(set_data['version'])
168
- if stored_version < set.highest_version
169
- search_data[set.name] = search_data_from_set(set)
170
- end
171
- else
172
- search_data[set.name] = search_data_from_set(set)
173
- end
174
- end
175
-
176
- stored_names = search_data.keys
177
- delted_names = stored_names - enumerated_names
178
- delted_names.each do |name|
179
- search_data.delete(name)
146
+ # Generates from scratch the search data for changed specifications in given source.
147
+ #
148
+ # @param [Source] source
149
+ # The source from which a search index will be generated.
150
+ # @param [Array<String>] spec_paths
151
+ # Array of file path names for corresponding changed specifications.
152
+ #
153
+ # @return [Hash{String=>Hash}] The search data for changed specifications.
154
+ #
155
+ def generate_search_index_for_changes_in_source(source, spec_paths)
156
+ pods = source.pods_for_specification_paths(spec_paths)
157
+ sets = pods.map do |pod|
158
+ Specification::Set.new(pod, source)
180
159
  end
181
-
182
- search_data
160
+ generate_search_index_for_sets(sets)
183
161
  end
184
162
 
185
163
  private
@@ -187,8 +165,19 @@ module Pod
187
165
  # @!group Private helpers
188
166
  #-----------------------------------------------------------------------#
189
167
 
190
- # Returns the search related information from the most representative
191
- # specification of the set following keys:
168
+ # Generates search data for given array of sets.
169
+ def generate_search_index_for_sets(sets)
170
+ result = {}
171
+ sets.each do |set|
172
+ word_list_from_set(set).each do |w|
173
+ (result[w] ||= []).push(set.name.to_sym)
174
+ end
175
+ end
176
+ result
177
+ end
178
+
179
+ # Returns the vocabulary extracted from the most representative
180
+ # specification of the set. Vocabulary contains words from following information:
192
181
  #
193
182
  # - version
194
183
  # - summary
@@ -198,26 +187,34 @@ module Pod
198
187
  # @param [Set] set
199
188
  # The set for which the information is needed.
200
189
  #
201
- # @note If the specification can't load an empty hash is returned and
190
+ # @note If the specification can't load an empty array is returned and
202
191
  # a warning is printed.
203
192
  #
204
193
  # @note For compatibility with non Ruby clients a strings are used
205
194
  # instead of symbols for the keys.
206
195
  #
207
- # @return [Hash{String=>String}] A hash with the search information.
196
+ # @return [Array<String>] An array of words contained by the set's search related information.
208
197
  #
209
- def search_data_from_set(set)
210
- result = {}
198
+ def word_list_from_set(set)
211
199
  spec = set.specification
212
- result['version'] = spec.version.to_s
213
- result['summary'] = spec.summary
214
- result['description'] = spec.description
215
- result['authors'] = spec.authors.keys.sort * ', '
216
- result
200
+ word_list = [set.name.dup]
201
+ if spec.summary
202
+ word_list += spec.summary.split
203
+ end
204
+ if spec.description
205
+ word_list += spec.description.split
206
+ end
207
+ if spec.authors
208
+ spec.authors.each_pair do |k, v|
209
+ word_list += k.split if k
210
+ word_list += v.split if v
211
+ end
212
+ end
213
+ word_list.uniq
217
214
  rescue
218
215
  CoreUI.warn "Skipping `#{set.name}` because the podspec contains " \
219
216
  'errors.'
220
- result
217
+ []
221
218
  end
222
219
 
223
220
  #-----------------------------------------------------------------------#