cocoapods-core 1.6.2 → 1.7.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ed8ead46288e97d3d0f2e40be798c50e17414ee2
4
- data.tar.gz: 79bcf66137a524456dfff3f5a707139dec734031
3
+ metadata.gz: 6d6029877133203026dca0a0536818e5799bb22a
4
+ data.tar.gz: 14c7457385e244d39a5fabff47257f702c6b5afe
5
5
  SHA512:
6
- metadata.gz: 0ae496e65d8142956c8e6761d9e7f458e5d1a70de2fe4a865c7058ca6430a6c5bd0cd2be67904dd8f7b51a00d34e33e0a629d1674fb29630d09fb01339c619ba
7
- data.tar.gz: c818be4b01bd274eae09542015c4aeb9459039d9535257601ca9c4271f52c8ccef098a7fa660b6b605b6f5b28248b61f2266411a1999a8bc1e2c438868a7de3f
6
+ metadata.gz: b34c2e92c8d1125c7d30237ca3f8771195860817768873d4ca3c774a82d6d83cf2741e7ca81e21ec738ce6fdd3c14b442c4815dc11aab2260ae9416e9fdad437
7
+ data.tar.gz: 1e4bc919ec36bd8f87a92dae0ce64755103d4bcd04b510443a6ef87078c22352ac084470d5e95c6f02c883b940cf7f68c9c31d1e71bb05ca21011b983a1e495d
@@ -27,6 +27,7 @@ module Pod
27
27
  autoload :Platform, 'cocoapods-core/platform'
28
28
  autoload :Podfile, 'cocoapods-core/podfile'
29
29
  autoload :Source, 'cocoapods-core/source'
30
+ autoload :CDNSource, 'cocoapods-core/cdn_source'
30
31
  autoload :MasterSource, 'cocoapods-core/master_source'
31
32
  autoload :Specification, 'cocoapods-core/specification'
32
33
  autoload :StandardError, 'cocoapods-core/standard_error'
@@ -0,0 +1,292 @@
1
+ require 'cocoapods-core/source'
2
+ require 'rest'
3
+ require 'concurrent'
4
+
5
+ module Pod
6
+ # Subclass of Pod::Source to provide support for CDN-based Specs repositories
7
+ #
8
+ class CDNSource < Source
9
+ # @param [String] repo The name of the repository
10
+ #
11
+ def initialize(repo)
12
+ @check_existing_files_for_update = false
13
+ # Optimization: we initialize startup_time when the source is first initialized
14
+ # and then test file modification dates against it. Any file that was touched
15
+ # after the source was initialized, is considered fresh enough.
16
+ @startup_time = Time.new
17
+
18
+ @executor = Concurrent::ThreadPoolExecutor.new(
19
+ :min_threads => 1,
20
+ :max_threads => 200,
21
+ :max_queue => 0 # unbounded work queue
22
+ )
23
+ super(repo)
24
+ end
25
+
26
+ # @return [String] The URL of the source.
27
+ #
28
+ def url
29
+ @url ||= File.read(repo.join('.url'))
30
+ end
31
+
32
+ # @return [String] The type of the source.
33
+ #
34
+ def type
35
+ 'CDN'
36
+ end
37
+
38
+ def refresh_metadata
39
+ if metadata.nil?
40
+ unless repo.exist?
41
+ raise Informative, "Unable to find a source named: `#{name}`"
42
+ end
43
+
44
+ specs_dir.mkpath
45
+ download_file('CocoaPods-version.yml')
46
+ end
47
+
48
+ super
49
+ end
50
+
51
+ def preheat_existing_files
52
+ all_existing_files = [repo.join('**/*.yml'), repo.join('**/*.txt'), repo.join('**/*.json')].map(&Pathname.method(:glob)).flatten
53
+ loaders = all_existing_files.map { |f| f.relative_path_from(repo).to_s }.map do |file|
54
+ Concurrent::Promise.execute(:executor => @executor) do
55
+ download_file(file)
56
+ end
57
+ end
58
+ Concurrent::Promise.zip(*loaders).wait!
59
+ end
60
+
61
+ # @return [Pathname] The directory where the specs are stored.
62
+ #
63
+ def specs_dir
64
+ @specs_dir ||= repo + 'Specs'
65
+ end
66
+
67
+ # @!group Querying the source
68
+ #-------------------------------------------------------------------------#
69
+
70
+ # @return [Array<String>] the list of the name of all the Pods.
71
+ #
72
+ def pods
73
+ download_file('all_pods.txt')
74
+ local_file('all_pods.txt', &:to_a).map(&:chomp)
75
+ end
76
+
77
+ # @return [Array<Version>] all the available versions for the Pod, sorted
78
+ # from highest to lowest.
79
+ #
80
+ # @param [String] name
81
+ # the name of the Pod.
82
+ #
83
+ def versions(name)
84
+ return nil unless specs_dir
85
+ raise ArgumentError, 'No name' unless name
86
+
87
+ return @versions_by_name[name] unless @versions_by_name[name].nil?
88
+
89
+ pod_path_actual = pod_path(name)
90
+ pod_path_relative = relative_pod_path(name)
91
+ versions_file_path_relative = pod_path_relative.join(INDEX_FILE_NAME).to_s
92
+ download_file(versions_file_path_relative)
93
+
94
+ return nil unless pod_path_actual.join(INDEX_FILE_NAME).exist?
95
+
96
+ loaders = []
97
+ @versions_by_name[name] ||= local_file(versions_file_path_relative) do |file|
98
+ file.map do |v|
99
+ version = v.chomp
100
+
101
+ # Optimization: ensure all the podspec files at least exist. The correct one will get refreshed
102
+ # in #specification_path regardless.
103
+ podspec_version_path_relative = Pathname.new(version).join("#{name}.podspec.json")
104
+ unless pod_path_actual.join(podspec_version_path_relative).exist?
105
+ loaders << Concurrent::Promise.execute(:executor => @executor) do
106
+ download_file(pod_path_relative.join(podspec_version_path_relative).to_s)
107
+ end
108
+ end
109
+ begin
110
+ Version.new(version) if version[0, 1] != '.'
111
+ rescue ArgumentError
112
+ raise Informative, 'An unexpected version directory ' \
113
+ "`#{version}` was encountered for the " \
114
+ "`#{pod_dir}` Pod in the `#{name}` repository."
115
+ end
116
+ end
117
+ end.compact.sort.reverse
118
+ Concurrent::Promise.zip(*loaders).wait!
119
+ @versions_by_name[name]
120
+ end
121
+
122
+ # Returns the path of the specification with the given name and version.
123
+ #
124
+ # @param [String] name
125
+ # the name of the Pod.
126
+ #
127
+ # @param [Version,String] version
128
+ # the version for the specification.
129
+ #
130
+ # @return [Pathname] The path of the specification.
131
+ #
132
+ def specification_path(name, version)
133
+ raise ArgumentError, 'No name' unless name
134
+ raise ArgumentError, 'No version' unless version
135
+
136
+ podspec_version_path_relative = Pathname.new(version.to_s).join("#{name}.podspec.json")
137
+ relative_podspec = relative_pod_path(name).join(podspec_version_path_relative).to_s
138
+ download_file(relative_podspec)
139
+ pod_path(name).join(podspec_version_path_relative)
140
+ end
141
+
142
+ # @return [Array<Specification>] all the specifications contained by the
143
+ # source.
144
+ #
145
+ def all_specs
146
+ raise Informative, "Can't retrieve all the specs for a CDN-backed source, it will take forever"
147
+ end
148
+
149
+ # @!group Searching the source
150
+ #-------------------------------------------------------------------------#
151
+
152
+ # @return [Set] a set for a given dependency. The set is identified by the
153
+ # name of the dependency and takes into account subspecs.
154
+ #
155
+ # @note This method is optimized for fast lookups by name, i.e. it does
156
+ # *not* require iterating through {#pod_sets}
157
+ #
158
+ # @todo Rename to #load_set
159
+ #
160
+ def search(query)
161
+ unless specs_dir
162
+ raise Informative, "Unable to find a source named: `#{name}`"
163
+ end
164
+ if query.is_a?(Dependency)
165
+ query = query.root_name
166
+ end
167
+
168
+ found = download_file(relative_pod_path(query).join(INDEX_FILE_NAME).to_s)
169
+
170
+ if found
171
+ set = set(query)
172
+ set if set.specification_name == query
173
+ end
174
+ end
175
+
176
+ # @return [Array<Set>] The list of the sets that contain the search term.
177
+ #
178
+ # @param [String] query
179
+ # the search term. Can be a regular expression.
180
+ #
181
+ # @param [Bool] full_text_search
182
+ # not supported due to performance reasons
183
+ #
184
+ # @note full text search requires to load the specification for each pod,
185
+ # and therefore not supported.
186
+ #
187
+ def search_by_name(query, full_text_search = false)
188
+ if full_text_search
189
+ raise Informative, "Can't perform full text search, it will take forever"
190
+ else
191
+ super(query)
192
+ end
193
+ end
194
+
195
+ # Check update dates for all existing files.
196
+ # Does not download non-existing specs, since CDN-backed repo is updated live.
197
+ #
198
+ # @param [Bool] show_output
199
+ #
200
+ # @return [Array<String>] Always returns empty array, as it cannot know
201
+ # everything that actually changed.
202
+ #
203
+ def update(_show_output)
204
+ @check_existing_files_for_update = true
205
+ begin
206
+ preheat_existing_files
207
+ ensure
208
+ @check_existing_files_for_update = false
209
+ end
210
+ []
211
+ end
212
+
213
+ def git?
214
+ # Long story here. This property is actually used solely by Source::Manager to determine
215
+ # which sources are updatable. Ideally, this would require a name change but @segiddins
216
+ # has pointed out that it is public and could break plugins.
217
+ # In any case, CDN-backed repos can be updated and therefore the value ought to be true.
218
+ true
219
+ end
220
+
221
+ private
222
+
223
+ # Index files contain all the sub directories in the directory, separated by
224
+ # a newline. We use those because you can't get a directory listing from a CDN.
225
+ INDEX_FILE_NAME = 'index.txt'.freeze
226
+
227
+ def local_file(partial_url)
228
+ File.open(repo.join(partial_url)) do |file|
229
+ yield file if block_given?
230
+ end
231
+ end
232
+
233
+ def relative_pod_path(pod_name)
234
+ pod_path(pod_name).relative_path_from(repo)
235
+ end
236
+
237
+ def download_file(partial_url)
238
+ file_remote_url = url + partial_url.to_s
239
+ path = repo + partial_url
240
+
241
+ if File.exist?(path)
242
+ if @startup_time < File.mtime(path)
243
+ debug "CDN: #{name} Relative path: #{partial_url} modified during this run! Returning local"
244
+ return partial_url
245
+ end
246
+
247
+ unless @check_existing_files_for_update
248
+ debug "CDN: #{name} Relative path: #{partial_url} exists! Returning local because checking is only perfomed in repo update"
249
+ return partial_url
250
+ end
251
+ end
252
+
253
+ path.dirname.mkpath
254
+
255
+ etag_path = path.sub_ext(path.extname + '.etag')
256
+
257
+ etag = File.read(etag_path) if File.exist?(etag_path)
258
+ debug "CDN: #{name} Relative path: #{partial_url}, has ETag? #{etag}" unless etag.nil?
259
+
260
+ response = etag.nil? ? REST.get(file_remote_url) : REST.get(file_remote_url, 'If-None-Match' => etag)
261
+
262
+ case response.status_code
263
+ when 304
264
+ debug "CDN: #{name} Relative path not modified: #{partial_url}"
265
+ # We need to update the file modification date, as it is later used for freshness
266
+ # optimization. See #initialize for more information.
267
+ FileUtils.touch path
268
+ partial_url
269
+ when 200
270
+ File.open(path, 'w') { |f| f.write(response.body) }
271
+
272
+ etag_new = response.headers['etag'].first if response.headers.include?('etag')
273
+ debug "CDN: #{name} Relative path downloaded: #{partial_url}, save ETag: #{etag_new}"
274
+ File.open(etag_path, 'w') { |f| f.write(etag_new) } unless etag_new.nil?
275
+ partial_url
276
+ when 404
277
+ debug "CDN: #{name} Relative path couldn't be downloaded: #{partial_url} Response: #{response.status_code}"
278
+ nil
279
+ else
280
+ raise Informative, "CDN: #{name} Relative path couldn't be downloaded: #{partial_url} Response: #{response.status_code}"
281
+ end
282
+ end
283
+
284
+ def debug(message)
285
+ if defined?(Pod::UI)
286
+ Pod::UI.message(message)
287
+ else
288
+ CoreUI.puts(message)
289
+ end
290
+ end
291
+ end
292
+ end
@@ -1,5 +1,5 @@
1
1
  module Pod
2
2
  # The version of the cocoapods-core.
3
3
  #
4
- CORE_VERSION = '1.6.2'.freeze unless defined? Pod::CORE_VERSION
4
+ CORE_VERSION = '1.7.0.beta.1'.freeze unless defined? Pod::CORE_VERSION
5
5
  end
@@ -454,22 +454,17 @@ module Pod
454
454
  #
455
455
  #
456
456
  def generate_pods_data(specs)
457
- pod_and_deps = specs.map do |spec|
458
- [spec.to_s, spec.all_dependencies.map(&:to_s).sort]
459
- end.uniq
460
-
461
- tmp = {}
462
- pod_and_deps.each do |name, deps|
463
- if tmp[name]
464
- tmp[name].concat(deps).uniq!
465
- else
466
- tmp[name] = deps
467
- end
457
+ pods_and_deps_merged = specs.reduce({}) do |result, spec|
458
+ name = spec.to_s
459
+ result[name] ||= []
460
+ result[name].concat(spec.all_dependencies.map(&:to_s))
461
+ result
468
462
  end
469
- pod_and_deps = tmp.sort_by(&:first).map do |name, deps|
470
- deps.empty? ? name : { name => deps }
463
+
464
+ pod_and_deps = pods_and_deps_merged.map do |name, deps|
465
+ deps.empty? ? name : { name => YAMLHelper.sorted_array(deps.uniq) }
471
466
  end
472
- pod_and_deps
467
+ YAMLHelper.sorted_array(pod_and_deps)
473
468
  end
474
469
 
475
470
  # Generates the list of the dependencies of the Podfile.
@@ -481,7 +476,7 @@ module Pod
481
476
  # @return [Array] the generated data.
482
477
  #
483
478
  def generate_dependencies_data(podfile)
484
- podfile.dependencies.map(&:to_s).sort
479
+ YAMLHelper.sorted_array(podfile.dependencies.map(&:to_s))
485
480
  end
486
481
 
487
482
  # Generates the hash of spec repo sources used in the Podfile.
@@ -496,7 +491,7 @@ module Pod
496
491
  key = source.url || source.name
497
492
  key = key.downcase if source.name == Pod::MasterSource::MASTER_REPO_NAME
498
493
  value = specs.map { |s| s.root.name }.uniq
499
- [key, value]
494
+ [key, YAMLHelper.sorted_array(value)]
500
495
  end.compact]
501
496
  end
502
497
 
@@ -255,7 +255,7 @@ module Pod
255
255
  end
256
256
 
257
257
  case path.extname
258
- when '', '.podfile'
258
+ when '', '.podfile', '.rb'
259
259
  Podfile.from_ruby(path)
260
260
  when '.yaml'
261
261
  Podfile.from_yaml(path)
@@ -20,7 +20,7 @@ module Pod
20
20
  # target 'MyApp' do
21
21
  # pod 'ObjectiveSugar', '~> 0.5'
22
22
  #
23
- # target "MyAppTests" do
23
+ # target 'MyAppTests' do
24
24
  # inherit! :search_paths
25
25
  # pod 'OCMock', '~> 2.0.1'
26
26
  # end
@@ -112,6 +112,9 @@ module Pod
112
112
  # specify in your version requirement. The example is equal to
113
113
  # `>= 0.1.2` combined with `< 0.2.0` and will always match the
114
114
  # latest known version matching your requirements.
115
+ # * `~> 0.1.3-beta.0` Beta and release versions for 0.1.3, release versions
116
+ # up to 0.2 excluding 0.2. Components separated by a dash (-)
117
+ # will not be considered for the version requirement.
115
118
  #
116
119
  # A list of version requirements can be specified for even more fine
117
120
  # grained control.
@@ -182,6 +185,18 @@ module Pod
182
185
  #
183
186
  # pod 'QueryKit', :subspecs => ['Attribute', 'QuerySet']
184
187
  #
188
+ # ### Test Specs
189
+ #
190
+ # Test specs can be optionally included via the `:testspecs` option. By default,
191
+ # none of a Pod's test specs are included.
192
+ #
193
+ # You may specify a list of test spec names to install using the following:
194
+ #
195
+ # pod 'AFNetworking', :testspecs => ['UnitTests', 'SomeOtherTests']
196
+ #
197
+ # The values provided to `:testspecs` correspond to the name provided to the
198
+ # `test_spec` DSL attribute in a Podspec.
199
+ #
185
200
  # ------
186
201
  #
187
202
  # Dependencies can be obtained also from external sources.
@@ -753,8 +768,7 @@ module Pod
753
768
  # @param [String] source
754
769
  # The URL of a specs repository.
755
770
  #
756
- # @example Specifying to first use the Artsy repository and then the
757
- # CocoaPods Master Repository
771
+ # @example Specifying to first use the Artsy repository and then the CocoaPods Master Repository
758
772
  #
759
773
  # source 'https://github.com/artsy/Specs.git'
760
774
  # source 'https://github.com/CocoaPods/Specs.git'
@@ -847,6 +861,39 @@ module Pod
847
861
  raise Informative, 'Specifying multiple `post_install` hooks is unsupported.' if @post_install_callback
848
862
  @post_install_callback = block
849
863
  end
864
+
865
+ # Specifies the Swift version requirements this target definition supports.
866
+ #
867
+ # **Note** These requirements are inherited from the parent, if specified and if none
868
+ # are specified at the root level then all versions are considered to be supported.
869
+ #
870
+ # @param [String, Version, Array<String>, Array<Version>] requirements
871
+ # The set of requirements this target supports.
872
+ #
873
+ # @example
874
+ #
875
+ # target 'MyApp' do
876
+ # supports_swift_versions '>= 3.0', '< 4.0'
877
+ # pod 'AFNetworking', '~> 1.0'
878
+ # end
879
+ #
880
+ # @example
881
+ #
882
+ # supports_swift_versions '>= 3.0', '< 4.0'
883
+ #
884
+ # target 'MyApp' do
885
+ # pod 'AFNetworking', '~> 1.0'
886
+ # end
887
+ #
888
+ # target 'ZipApp' do
889
+ # pod 'SSZipArchive'
890
+ # end
891
+ #
892
+ # @return [void]
893
+ #
894
+ def supports_swift_versions(*requirements)
895
+ current_target_definition.store_swift_version_requirements(*requirements)
896
+ end
850
897
  end
851
898
  end
852
899
  end
@@ -140,7 +140,7 @@ module Pod
140
140
  # Sets the path of the user project this target definition should link
141
141
  # with.
142
142
  #
143
- # @param [String] path
143
+ # @param [String] name
144
144
  # The path of the project.
145
145
  #
146
146
  # @return [void]
@@ -393,6 +393,27 @@ module Pod
393
393
  get_hash_value('swift_version')
394
394
  end
395
395
 
396
+ # @return [Array<String>] the Swift version requirements this target definition enforces.
397
+ #
398
+ def swift_version_requirements
399
+ get_hash_value('swift_version_requirements')
400
+ end
401
+
402
+ # Queries the target if a version of Swift is supported or not.
403
+ #
404
+ # @param [Version] swift_version
405
+ # The Swift version to query against.
406
+ #
407
+ # @return [Boolean] Whether the target accepts the specified Swift version.
408
+ #
409
+ def supports_swift_version?(swift_version)
410
+ if swift_version_requirements.nil?
411
+ root? || parent.supports_swift_version?(swift_version)
412
+ else
413
+ Requirement.create(swift_version_requirements).satisfied_by?(swift_version)
414
+ end
415
+ end
416
+
396
417
  #--------------------------------------#
397
418
 
398
419
  # Whether a specific pod should be linked to the target when building for
@@ -610,6 +631,17 @@ module Pod
610
631
  set_platform(name, target)
611
632
  end
612
633
 
634
+ # Stores the Swift version requirements to be used for this target.
635
+ #
636
+ # @param [String, Version, Array<String>, Array<Version>] requirements
637
+ # The set of requirements this target supports.
638
+ #
639
+ # @return [void]
640
+ #
641
+ def store_swift_version_requirements(*requirements)
642
+ set_hash_value('swift_version_requirements', requirements.flatten.map(&:to_s))
643
+ end
644
+
613
645
  #--------------------------------------#
614
646
 
615
647
  # Stores the dependency for a Pod with the given name.
@@ -742,6 +774,7 @@ module Pod
742
774
  children
743
775
  configuration_pod_whitelist
744
776
  uses_frameworks
777
+ swift_version_requirements
745
778
  inheritance
746
779
  abstract
747
780
  swift_version
@@ -860,6 +893,7 @@ module Pod
860
893
  if inhibit_hash['all']
861
894
  # Clean pods that are set to not inhibit inside parent if inhibit_all_warnings! was set.
862
895
  parent_hash['not_for_pods'] = nil
896
+ inhibit_hash.delete('all') if parent_hash['all']
863
897
  end
864
898
  parent_hash.merge(inhibit_hash) do |_, l, r|
865
899
  Array(l).concat(r).uniq
@@ -966,7 +1000,7 @@ module Pod
966
1000
  # Removes :inhibit_warnings from the requirements list, and adds
967
1001
  # the pod's name into internal hash for disabling warnings.
968
1002
  #
969
- # @param [String] pod name
1003
+ # @param [String] name The name of the pod
970
1004
  #
971
1005
  # @param [Array] requirements
972
1006
  # If :inhibit_warnings is the only key in the hash, the hash
@@ -988,7 +1022,7 @@ module Pod
988
1022
  # Removes :modular_headers from the requirements list, and adds
989
1023
  # the pods name into internal hash for modular headers.
990
1024
  #
991
- # @param [String] pod name
1025
+ # @param [String] name The name of the pod
992
1026
  #
993
1027
  # @param [Array] requirements
994
1028
  # If :modular_headers is the only key in the hash, the hash
@@ -1011,7 +1045,7 @@ module Pod
1011
1045
  # and adds the pod's name into the internal hash for which pods should be
1012
1046
  # linked in which configuration only.
1013
1047
  #
1014
- # @param [String] pod name
1048
+ # @param [String] name The name of the pod
1015
1049
  #
1016
1050
  # @param [Array] requirements
1017
1051
  # If :configurations is the only key in the hash, the hash
@@ -1048,6 +1082,7 @@ module Pod
1048
1082
 
1049
1083
  subspecs = options.delete(:subspecs)
1050
1084
  test_specs = options.delete(:testspecs)
1085
+ app_specs = options.delete(:appspecs)
1051
1086
 
1052
1087
  subspecs.each do |ss|
1053
1088
  store_pod("#{name}/#{ss}", *requirements.dup)
@@ -1058,6 +1093,11 @@ module Pod
1058
1093
  store_pod("#{name}/#{ss}", *requirements_copy)
1059
1094
  end if test_specs
1060
1095
 
1096
+ app_specs.each do |as|
1097
+ requirements_copy = requirements.map(&:dup)
1098
+ store_pod("#{name}/#{as}", *requirements_copy)
1099
+ end if app_specs
1100
+
1061
1101
  requirements.pop if options.empty?
1062
1102
  !subspecs.nil?
1063
1103
  end
@@ -33,15 +33,12 @@ module Pod
33
33
  # will be used.
34
34
  #
35
35
  def aggregate_for_dependency(dependency)
36
- if dependency.podspec_repo
37
- source = source_with_url(dependency.podspec_repo)
38
- raise StandardError, '[Bug] Failed to find known source with the URL ' \
39
- "#{dependency.podspec_repo.inspect}" if source.nil?
36
+ return aggregate if dependency.podspec_repo.nil?
40
37
 
41
- aggregate_with_repos([source.repo])
42
- else
43
- aggregate
44
- end
38
+ source = source_with_url(dependency.podspec_repo)
39
+ return aggregate if source.nil?
40
+
41
+ aggregate_with_repos([source.repo])
45
42
  end
46
43
 
47
44
  # @return [Array<Source>] The list of the sources with the given names.
@@ -234,6 +231,10 @@ module Pod
234
231
  # A hash containing changed specification paths for each source.
235
232
  #
236
233
  def update_search_index_if_needed_in_background(changed_spec_paths)
234
+ if Gem.win_platform?
235
+ update_search_index_if_needed(changed_spec_paths)
236
+ return
237
+ end
237
238
  Process.fork do
238
239
  Process.daemon
239
240
  update_search_index_if_needed(changed_spec_paths)
@@ -283,7 +284,10 @@ module Pod
283
284
  #
284
285
  def source_from_path(path)
285
286
  @sources_by_path ||= Hash.new do |hash, key|
286
- hash[key] = if key.basename.to_s == Pod::MasterSource::MASTER_REPO_NAME
287
+ hash[key] = case
288
+ when (key + '.url').exist?
289
+ CDNSource.new(key)
290
+ when key.basename.to_s == Pod::MasterSource::MASTER_REPO_NAME
287
291
  MasterSource.new(key)
288
292
  else
289
293
  Source.new(key)
@@ -37,13 +37,18 @@ module Pod
37
37
  # @param [Bool] test_specification
38
38
  # Whether the specification is a test specification
39
39
  #
40
- def initialize(parent = nil, name = nil, test_specification = false)
40
+ # @param [Bool] app_specification
41
+ # Whether the specification is an app specification
42
+ #
43
+ def initialize(parent = nil, name = nil, test_specification = false, app_specification: false)
44
+ raise StandardError, "#{self} can not be both an app and test specification." if test_specification && app_specification
41
45
  @attributes_hash = {}
42
46
  @subspecs = []
43
47
  @consumers = {}
44
48
  @parent = parent
45
49
  @hash_value = nil
46
50
  @test_specification = test_specification
51
+ @app_specification = app_specification
47
52
  attributes_hash['name'] = name
48
53
  attributes_hash['test_type'] = :unit if test_specification
49
54
 
@@ -74,6 +79,11 @@ module Pod
74
79
  attr_accessor :test_specification
75
80
  alias_method :test_specification?, :test_specification
76
81
 
82
+ # @return [Bool] If this specification is an app specification.
83
+ #
84
+ attr_accessor :app_specification
85
+ alias_method :app_specification?, :app_specification
86
+
77
87
  # Checks if a specification is equal to the given one according its name
78
88
  # and to its version.
79
89
  #
@@ -221,8 +231,35 @@ module Pod
221
231
 
222
232
  public
223
233
 
234
+ # @return [Symbol] Spec type of the current spec.
235
+ #
236
+ # @note see Attribute#SUPPORTED_SPEC_TYPES for the list of available spec_types.
237
+ #
238
+ def spec_type
239
+ return :app if app_specification?
240
+ return :test if test_specification?
241
+
242
+ :library
243
+ end
244
+
224
245
  # @!group Dependencies & Subspecs
225
246
 
247
+ # @return [Bool] If this specification is a library specification.
248
+ #
249
+ # @note a library specification is a specification that is not of type app or test.
250
+ #
251
+ def library_specification?
252
+ !app_specification? && !test_specification?
253
+ end
254
+
255
+ # @return [Bool] If this specification is not a library specification.
256
+ #
257
+ # @note see #library_specification?
258
+ #
259
+ def non_library_specification?
260
+ !library_specification?
261
+ end
262
+
226
263
  # @return [Symbol] the test type supported if this is a test specification.
227
264
  #
228
265
  def test_type
@@ -236,6 +273,20 @@ module Pod
236
273
  subspecs.select(&:test_specification?)
237
274
  end
238
275
 
276
+ # @return [Array<Specification>] the list of all the app subspecs of
277
+ # a specification.
278
+ #
279
+ def app_specs
280
+ subspecs.select(&:app_specification?)
281
+ end
282
+
283
+ # @return [Array<Specification>] the list of all the non libary (app or test) subspecs of
284
+ # a specification.
285
+ #
286
+ def non_library_specs
287
+ subspecs.select(&:non_library_specification?)
288
+ end
289
+
239
290
  # @return [Array<Specification>] the recursive list of all the subspecs of
240
291
  # a specification.
241
292
  #
@@ -265,7 +316,7 @@ module Pod
265
316
  #
266
317
  # @return [Specification] the subspec with the given name or self.
267
318
  #
268
- def subspec_by_name(relative_name, raise_if_missing = true, include_test_specifications = false)
319
+ def subspec_by_name(relative_name, raise_if_missing = true, include_non_library_specifications = false)
269
320
  if relative_name.nil? || relative_name == base_name
270
321
  self
271
322
  elsif relative_name.downcase == base_name.downcase
@@ -274,7 +325,7 @@ module Pod
274
325
  else
275
326
  remainder = relative_name[base_name.size + 1..-1]
276
327
  subspec_name = remainder.split('/').shift
277
- subspec = subspecs.find { |s| s.base_name == subspec_name && (include_test_specifications || !s.test_specification?) }
328
+ subspec = subspecs.find { |s| s.base_name == subspec_name && (include_non_library_specifications || !s.non_library_specification?) }
278
329
  unless subspec
279
330
  if raise_if_missing
280
331
  raise Informative, 'Unable to find a specification named ' \
@@ -283,7 +334,7 @@ module Pod
283
334
  return nil
284
335
  end
285
336
  end
286
- subspec.subspec_by_name(remainder, raise_if_missing, include_test_specifications)
337
+ subspec.subspec_by_name(remainder, raise_if_missing, include_non_library_specifications)
287
338
  end
288
339
  end
289
340
 
@@ -307,7 +358,7 @@ module Pod
307
358
  #
308
359
  def subspec_dependencies(platform = nil)
309
360
  specs = if default_subspecs.empty?
310
- subspecs.compact.reject(&:test_specification?)
361
+ subspecs.compact.reject(&:non_library_specification?)
311
362
  else
312
363
  default_subspecs.map do |subspec_name|
313
364
  root.subspec_by_name("#{name}/#{subspec_name}")
@@ -377,6 +428,13 @@ module Pod
377
428
  end
378
429
  end
379
430
 
431
+ # @return [Hash] The scheme value.
432
+ #
433
+ def scheme
434
+ value = attributes_hash['scheme'] || {}
435
+ Specification.convert_keys_to_symbol(value, :recursive => false)
436
+ end
437
+
380
438
  #-------------------------------------------------------------------------#
381
439
 
382
440
  public
@@ -520,30 +578,36 @@ module Pod
520
578
  # @param [Object] value
521
579
  # the value that needs to be stripped from the Symbols.
522
580
  #
523
- # @return [Hash] the hash with the strings instead of the keys.
581
+ # @param [Boolean] recursive
582
+ # whether to convert keys of nested hashes.
583
+ #
584
+ # @return [Hash] the hash with the keys as strings instead of symbols.
524
585
  #
525
- def self.convert_keys_to_string(value)
586
+ def self.convert_keys_to_string(value, recursive: true)
526
587
  return unless value
527
588
  result = {}
528
589
  value.each do |key, subvalue|
529
- subvalue = Specification.convert_keys_to_string(subvalue) if subvalue.is_a?(Hash)
590
+ subvalue = Specification.convert_keys_to_string(subvalue) if recursive && subvalue.is_a?(Hash)
530
591
  result[key.to_s] = subvalue
531
592
  end
532
593
  result
533
594
  end
534
595
 
535
- # Converts the keys of the given hash to a string.
596
+ # Converts the keys of the given hash to a symbol.
536
597
  #
537
598
  # @param [Object] value
538
- # the value that needs to be stripped from the Symbols.
599
+ # the value that needs to be stripped from the Strings.
600
+ #
601
+ # @param [Boolean] recursive
602
+ # whether to convert keys of nested hashes.
539
603
  #
540
- # @return [Hash] the hash with the strings instead of the keys.
604
+ # @return [Hash] the hash with the keys as symbols instead of strings.
541
605
  #
542
- def self.convert_keys_to_symbol(value)
606
+ def self.convert_keys_to_symbol(value, recursive: true)
543
607
  return unless value
544
608
  result = {}
545
609
  value.each do |key, subvalue|
546
- subvalue = Specification.convert_keys_to_symbol(subvalue) if subvalue.is_a?(Hash)
610
+ subvalue = Specification.convert_keys_to_symbol(subvalue) if recursive && subvalue.is_a?(Hash)
547
611
  result[key.to_sym] = subvalue
548
612
  end
549
613
  result
@@ -9,6 +9,7 @@ module Pod
9
9
  # - standardizing the attributes
10
10
  # - handling multi-platform values
11
11
  # - handle default values
12
+ # - handle automatic container wrapping of values
12
13
  # - handle inherited values
13
14
  #
14
15
  # This class allows to store the values of the attributes in the
@@ -184,6 +185,10 @@ module Pod
184
185
  #
185
186
  spec_attr_accessor :script_phases
186
187
 
188
+ # @return [Hash] A hash that contains the scheme configuration.
189
+ #
190
+ spec_attr_accessor :scheme
191
+
187
192
  # @return [Array<String>] A hash where the key represents the
188
193
  # paths of the resources to copy and the values the paths of
189
194
  # the resources that should be copied.
@@ -407,6 +412,17 @@ module Pod
407
412
  end
408
413
  end
409
414
 
415
+ # Converts the a scheme where keys are strings into symbols.
416
+ #
417
+ # @param [Hash] value.
418
+ # The value of the attribute as specified by the user.
419
+ #
420
+ # @return [Hash] the scheme with symbols as keys instead of strings or `nil` if the value is not a hash.
421
+ #
422
+ def _prepare_scheme(value)
423
+ Specification.convert_keys_to_symbol(value, :recursive => false) if value && value.is_a?(Hash)
424
+ end
425
+
410
426
  # Ensures that the file patterns of the resource bundles are contained in
411
427
  # an array.
412
428
  #
@@ -129,18 +129,35 @@ module Pod
129
129
 
130
130
  #------------------#
131
131
 
132
- # @!method swift_version=(version)
132
+ # @!method swift_versions=(version)
133
133
  #
134
- # The version of Swift that the specification supports.
134
+ # The versions of Swift that the specification supports. A version of '4' will be treated as
135
+ # '4.0' by CocoaPods and not '4.1' or '4.2'.
136
+ #
137
+ # **Note** The Swift compiler mostly accepts major versions and sometimes will honor minor versions.
138
+ # While CocoaPods allows specifying a minor or patch version it might not be honored fully by the Swift compiler.
139
+ #
140
+ # @example
141
+ #
142
+ # spec.swift_versions = ['3.0']
135
143
  #
136
144
  # @example
137
145
  #
138
- # spec.swift_version = '3.2'
146
+ # spec.swift_versions = ['3.0', '4.0', '4.2']
147
+ #
148
+ # @example
139
149
  #
140
- # @param [String] swift_version
150
+ # spec.swift_version = '3.0'
141
151
  #
142
- root_attribute :swift_version,
143
- :multi_platform => false
152
+ # @example
153
+ #
154
+ # spec.swift_version = '3.0', '4.0'
155
+ #
156
+ # @param [String, Array<String>] swift_versions
157
+ #
158
+ root_attribute :swift_versions,
159
+ :container => Array,
160
+ :singularize => true
144
161
 
145
162
  #-----------------------------------------------------------------------#
146
163
 
@@ -660,8 +677,21 @@ module Pod
660
677
  end
661
678
  end
662
679
  unless version_requirements.all? { |req| req.is_a?(String) }
663
- raise Informative, 'Unsupported version requirements'
680
+ version_requirements.each do |requirement|
681
+ if requirement.is_a?(Hash)
682
+ if !requirement[:path].nil?
683
+ raise Informative, 'Podspecs cannot specify the source of dependencies. The `:path` option is not supported.'\
684
+ ' `:path` can be used in the Podfile instead to override global dependencies.'
685
+ elsif !requirement[:git].nil?
686
+ raise Informative, 'Podspecs cannot specify the source of dependencies. The `:git` option is not supported.'\
687
+ ' `:git` can be used in the Podfile instead to override global dependencies.'
688
+ end
689
+ end
690
+ end
691
+
692
+ raise Informative, "Unsupported version requirements. #{version_requirements.inspect} is not valid."
664
693
  end
694
+
665
695
  attributes_hash['dependencies'] ||= {}
666
696
  attributes_hash['dependencies'][name] = version_requirements
667
697
  end
@@ -1230,10 +1260,10 @@ module Pod
1230
1260
  #
1231
1261
  # spec.resource_bundles = {
1232
1262
  # 'MapBox' => ['MapView/Map/Resources/*.png'],
1233
- # 'OtherResources' => ['MapView/Map/OtherResources/*.png']
1263
+ # 'MapBoxOtherResources' => ['MapView/Map/OtherResources/*.png']
1234
1264
  # }
1235
1265
  #
1236
- # @param [Hash{String=>String}] resource_bundles
1266
+ # @param [Hash{String=>String}, Hash{String=>Array<String>}] resource_bundles
1237
1267
  # A hash where the keys are the names of the resource bundles
1238
1268
  # and the values are their relative file patterns.
1239
1269
  #
@@ -1443,10 +1473,11 @@ module Pod
1443
1473
  #
1444
1474
  # @param [Symbol, String] type
1445
1475
  # The test type to use.
1476
+ #
1446
1477
  attribute :test_type,
1447
1478
  :types => [Symbol, String],
1448
1479
  :multi_platform => false,
1449
- :test_only => true
1480
+ :spec_types => [:test]
1450
1481
 
1451
1482
  # @!method requires_app_host=(flag)
1452
1483
  #
@@ -1462,7 +1493,31 @@ module Pod
1462
1493
  attribute :requires_app_host,
1463
1494
  :types => [TrueClass, FalseClass],
1464
1495
  :default_value => false,
1465
- :test_only => true
1496
+ :spec_types => [:test]
1497
+
1498
+ SCHEME_KEYS = [:launch_arguments, :environment_variables].freeze
1499
+
1500
+ # @!method scheme=(flag)
1501
+ #
1502
+ # Specifies the scheme configuration to be used for this specification.
1503
+ #
1504
+ # ---
1505
+ #
1506
+ # @example
1507
+ #
1508
+ # spec.scheme = { :launch_arguments => ['Arg1'] }
1509
+ #
1510
+ # @example
1511
+ #
1512
+ # spec.scheme = { :launch_arguments => ['Arg1', 'Arg2'], :environment_variables => { 'Key1' => 'Val1'} }
1513
+ #
1514
+ # @param [Hash] scheme
1515
+ # the scheme configuration to be used for this specification.
1516
+ #
1517
+ attribute :scheme,
1518
+ :types => [Hash],
1519
+ :container => Hash,
1520
+ :keys => SCHEME_KEYS
1466
1521
 
1467
1522
  # Represents a test specification for the library. Here you can place all
1468
1523
  # your tests for your podspec along with the test dependencies.
@@ -1486,6 +1541,28 @@ module Pod
1486
1541
  subspec
1487
1542
  end
1488
1543
 
1544
+ # Represents an app specification for the library. Here you can place all
1545
+ # your app source files for your podspec along with the app dependencies.
1546
+ #
1547
+ # ---
1548
+ #
1549
+ # @example
1550
+ #
1551
+ # Pod::Spec.new do |spec|
1552
+ # spec.name = 'NSAttributedString+CCLFormat'
1553
+ #
1554
+ # spec.app_spec do |app_spec|
1555
+ # app_spec.source_files = 'NSAttributedString+CCLFormat.m'
1556
+ # app_spec.dependency 'AFNetworking'
1557
+ # end
1558
+ # end
1559
+ #
1560
+ def app_spec(name = 'App', &block)
1561
+ appspec = Specification.new(self, name, :app_specification => true, &block)
1562
+ @subspecs << appspec
1563
+ appspec
1564
+ end
1565
+
1489
1566
  #------------------#
1490
1567
 
1491
1568
  # @!method default_subspecs=(subspec_array)
@@ -7,6 +7,10 @@ module Pod
7
7
  class Attribute
8
8
  require 'active_support/inflector/inflections'
9
9
 
10
+ # Spec types currently supported.
11
+ #
12
+ SUPPORTED_SPEC_TYPES = [:library, :app, :test].freeze
13
+
10
14
  # @return [Symbol] the name of the attribute.
11
15
  #
12
16
  attr_reader :name
@@ -31,7 +35,7 @@ module Pod
31
35
 
32
36
  @multi_platform = options.delete(:multi_platform) { true }
33
37
  @root_only = options.delete(:root_only) { false }
34
- @test_only = options.delete(:test_only) { false }
38
+ @spec_types = options.delete(:spec_types) { SUPPORTED_SPEC_TYPES }
35
39
  @inherited = options.delete(:inherited) { @root_only }
36
40
  @required = options.delete(:required) { false }
37
41
  @singularize = options.delete(:singularize) { false }
@@ -46,6 +50,9 @@ module Pod
46
50
  unless options.empty?
47
51
  raise StandardError, "Unrecognized options: #{options} for #{self}"
48
52
  end
53
+ unless (@spec_types - SUPPORTED_SPEC_TYPES).empty?
54
+ raise StandardError, "Unrecognized spec type option: #{@spec_types} for #{self}"
55
+ end
49
56
  end
50
57
 
51
58
  # @return [String] A string representation suitable for UI.
@@ -126,7 +133,7 @@ module Pod
126
133
  # test specifications.
127
134
  #
128
135
  def test_only?
129
- @test_only
136
+ @spec_types == [:test]
130
137
  end
131
138
 
132
139
  # @return [Bool] whether the attribute is multi-platform and should
@@ -26,13 +26,15 @@ module Pod
26
26
  platforms = Hash[available_platforms.map { |p| [p.name.to_s, p.deployment_target && p.deployment_target.to_s] }]
27
27
  hash['platforms'] = platforms
28
28
  end
29
- all_testspecs, all_subspecs = subspecs.partition(&:test_specification?)
30
- unless all_testspecs.empty?
31
- hash['testspecs'] = all_testspecs.map(&:to_hash)
32
- end
33
- unless all_subspecs.empty?
34
- hash['subspecs'] = all_subspecs.map(&:to_hash)
35
- end
29
+ specs_by_type = subspecs.group_by(&:spec_type)
30
+ all_appspecs = specs_by_type[:app] || []
31
+ all_testspecs = specs_by_type[:test] || []
32
+ all_subspecs = specs_by_type[:library] || []
33
+
34
+ hash['testspecs'] = all_testspecs.map(&:to_hash) unless all_testspecs.empty?
35
+ hash['appspecs'] = all_appspecs.map(&:to_hash) unless all_appspecs.empty?
36
+ hash['subspecs'] = all_subspecs.map(&:to_hash) unless all_subspecs.empty?
37
+
36
38
  hash
37
39
  end
38
40
  end
@@ -61,22 +63,33 @@ module Pod
61
63
  #
62
64
  # @return [Specification] the specification
63
65
  #
64
- def self.from_hash(hash, parent = nil)
65
- spec = Spec.new(parent)
66
+ def self.from_hash(hash, parent = nil, test_specification: false, app_specification: false)
66
67
  attributes_hash = hash.dup
68
+ spec = Spec.new(parent, nil, test_specification, :app_specification => app_specification)
67
69
  subspecs = attributes_hash.delete('subspecs')
68
70
  testspecs = attributes_hash.delete('testspecs')
69
- spec.attributes_hash = attributes_hash
71
+ appspecs = attributes_hash.delete('appspecs')
72
+
73
+ ## backwards compatibility with 1.3.0
70
74
  spec.test_specification = !attributes_hash['test_type'].nil?
71
- spec.subspecs.concat(subspecs_from_hash(spec, subspecs))
72
- spec.subspecs.concat(subspecs_from_hash(spec, testspecs))
75
+
76
+ testspecs.each { |ts| ts['test_specification'] = true; } unless testspecs.nil?
77
+ appspecs.each { |ts| ts['app_specification'] = true; } unless appspecs.nil?
78
+
79
+ spec.attributes_hash = attributes_hash
80
+ spec.subspecs.concat(subspecs_from_hash(spec, subspecs, false, false))
81
+ spec.subspecs.concat(subspecs_from_hash(spec, testspecs, true, false))
82
+ spec.subspecs.concat(subspecs_from_hash(spec, appspecs, false, true))
83
+
73
84
  spec
74
85
  end
75
86
 
76
- def self.subspecs_from_hash(spec, subspecs)
87
+ def self.subspecs_from_hash(spec, subspecs, test_specification, app_specification)
77
88
  return [] if subspecs.nil?
78
89
  subspecs.map do |s_hash|
79
- Specification.from_hash(s_hash, spec)
90
+ Specification.from_hash(s_hash, spec,
91
+ :test_specification => test_specification,
92
+ :app_specification => app_specification)
80
93
  end
81
94
  end
82
95
 
@@ -401,8 +401,8 @@ module Pod
401
401
  keys = script_phase.keys
402
402
  unrecognized_keys = keys - Specification::ALL_SCRIPT_PHASE_KEYS
403
403
  unless unrecognized_keys.empty?
404
- results.add_error('script_phases', "Unrecognized options `#{unrecognized_keys}` in script phase `#{script_phase[:name]}`. " \
405
- "Available options are `#{Specification::ALL_SCRIPT_PHASE_KEYS}`.")
404
+ results.add_error('script_phases', "Unrecognized option(s) `#{unrecognized_keys.join(', ')}` in script phase `#{script_phase[:name]}`. " \
405
+ "Available options are `#{Specification::ALL_SCRIPT_PHASE_KEYS.join(', ')}`.")
406
406
  end
407
407
  missing_required_keys = Specification::SCRIPT_PHASE_REQUIRED_KEYS - keys
408
408
  unless missing_required_keys.empty?
@@ -410,7 +410,24 @@ module Pod
410
410
  end
411
411
  unless Specification::EXECUTION_POSITION_KEYS.include?(script_phase[:execution_position])
412
412
  results.add_error('script_phases', "Invalid execution position value `#{script_phase[:execution_position]}` in shell script `#{script_phase[:name]}`. " \
413
- "Available options are `#{Specification::EXECUTION_POSITION_KEYS}`.")
413
+ "Available options are `#{Specification::EXECUTION_POSITION_KEYS.join(', ')}`.")
414
+ end
415
+ end
416
+ end
417
+
418
+ # Performs validation related to the `scheme` attribute.
419
+ #
420
+ def _validate_scheme(s)
421
+ unless s.empty?
422
+ if consumer.spec.subspec? && consumer.spec.library_specification?
423
+ results.add_error('scheme', 'Scheme configuration is not currently supported for subspecs.')
424
+ return
425
+ end
426
+ if s.key?(:launch_arguments) && !s[:launch_arguments].is_a?(Array)
427
+ results.add_error('scheme', 'Expected an array for key `launch_arguments`.')
428
+ end
429
+ if s.key?(:environment_variables) && !s[:environment_variables].is_a?(Hash)
430
+ results.add_error('scheme', 'Expected a hash for key `environment_variables`.')
414
431
  end
415
432
  end
416
433
  end
@@ -40,12 +40,25 @@ module Pod
40
40
  end
41
41
  end
42
42
 
43
- # @return [Version] The swift_versions required to use the specification.
43
+ # @deprecated in favor of #swift_versions
44
+ #
45
+ # @return [Version] The Swift version specified by the specification.
44
46
  #
45
47
  def swift_version
46
- @swift_version ||= if version = attributes_hash['swift_version']
47
- Version.new(version)
48
- end
48
+ swift_versions.last
49
+ end
50
+
51
+ # @return [Array<Version>] The Swift versions supported by the specification.
52
+ #
53
+ def swift_versions
54
+ @swift_versions ||= begin
55
+ swift_versions = Array(attributes_hash['swift_versions'])
56
+ # Pre 1.7.0, the DSL was singularized as it supported only a single version of Swift. In 1.7.0 the DSL
57
+ # is now pluralized always and a specification can support multiple versions of Swift. This ensures
58
+ # we parse the old JSON serialized format and include it as part of the Swift versions supported.
59
+ swift_versions << attributes_hash['swift_version'] unless attributes_hash['swift_version'].nil?
60
+ swift_versions.map { |swift_version| Version.new(swift_version) }.uniq.sort
61
+ end
49
62
  end
50
63
 
51
64
  # @return [Requirement] The CocoaPods version required to use the specification.
@@ -221,7 +221,9 @@ module Pod
221
221
  return 1 if rhs.nil?
222
222
  end
223
223
 
224
- return lhs <=> rhs if lhs <=> rhs
224
+ if comparison = lhs <=> rhs
225
+ return comparison
226
+ end
225
227
  return 1 if lhs.is_a?(String) && rhs.is_a?(Numeric)
226
228
  return -1 if lhs.is_a?(Numeric) && rhs.is_a?(String)
227
229
  end
@@ -239,6 +239,8 @@ module Pod
239
239
  end
240
240
  end
241
241
 
242
+ public
243
+
242
244
  # Sorts an array according to the string representation of it values.
243
245
  # This method allows to sort arrays which contains strings or hashes.
244
246
  #
@@ -259,6 +261,8 @@ module Pod
259
261
  end.map(&:first)
260
262
  end
261
263
 
264
+ private
265
+
262
266
  # Returns the string representation of a value useful for sorting.
263
267
  #
264
268
  # @param [String, Symbol, Array, Hash] value
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cocoapods-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.2
4
+ version: 1.7.0.beta.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eloy Duran
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2019-05-15 00:00:00.000000000 Z
12
+ date: 2019-02-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -87,6 +87,7 @@ files:
87
87
  - LICENSE
88
88
  - README.md
89
89
  - lib/cocoapods-core.rb
90
+ - lib/cocoapods-core/cdn_source.rb
90
91
  - lib/cocoapods-core/core_ui.rb
91
92
  - lib/cocoapods-core/dependency.rb
92
93
  - lib/cocoapods-core/gem_version.rb