cocoapods-core 0.39.0 → 1.0.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
  #-----------------------------------------------------------------------#