cocoapods 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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +261 -12
  3. data/lib/cocoapods.rb +1 -0
  4. data/lib/cocoapods/command.rb +1 -0
  5. data/lib/cocoapods/command/env.rb +66 -0
  6. data/lib/cocoapods/command/init.rb +1 -1
  7. data/lib/cocoapods/command/lib.rb +1 -1
  8. data/lib/cocoapods/command/project.rb +0 -4
  9. data/lib/cocoapods/command/repo/lint.rb +7 -6
  10. data/lib/cocoapods/command/repo/push.rb +22 -1
  11. data/lib/cocoapods/command/setup.rb +0 -24
  12. data/lib/cocoapods/command/spec/create.rb +3 -1
  13. data/lib/cocoapods/command/spec/edit.rb +14 -21
  14. data/lib/cocoapods/command/spec/env_spec.rb +53 -0
  15. data/lib/cocoapods/command/spec/lint.rb +1 -1
  16. data/lib/cocoapods/config.rb +1 -34
  17. data/lib/cocoapods/downloader.rb +9 -4
  18. data/lib/cocoapods/external_sources.rb +0 -4
  19. data/lib/cocoapods/external_sources/abstract_external_source.rb +38 -11
  20. data/lib/cocoapods/external_sources/path_source.rb +2 -2
  21. data/lib/cocoapods/gem_version.rb +2 -2
  22. data/lib/cocoapods/generator/acknowledgements.rb +1 -1
  23. data/lib/cocoapods/generator/acknowledgements/plist.rb +1 -1
  24. data/lib/cocoapods/generator/copy_resources_script.rb +28 -21
  25. data/lib/cocoapods/generator/info_plist_file.rb +34 -8
  26. data/lib/cocoapods/generator/module_map.rb +3 -18
  27. data/lib/cocoapods/generator/xcconfig/aggregate_xcconfig.rb +22 -10
  28. data/lib/cocoapods/generator/xcconfig/pod_xcconfig.rb +2 -1
  29. data/lib/cocoapods/generator/xcconfig/xcconfig_helper.rb +2 -1
  30. data/lib/cocoapods/hooks_manager.rb +3 -11
  31. data/lib/cocoapods/installer.rb +45 -25
  32. data/lib/cocoapods/installer/analyzer.rb +53 -25
  33. data/lib/cocoapods/installer/analyzer/sandbox_analyzer.rb +2 -13
  34. data/lib/cocoapods/installer/analyzer/target_inspection_result.rb +4 -0
  35. data/lib/cocoapods/installer/analyzer/target_inspector.rb +22 -19
  36. data/lib/cocoapods/installer/file_references_installer.rb +53 -6
  37. data/lib/cocoapods/installer/installation_options.rb +156 -0
  38. data/lib/cocoapods/installer/migrator.rb +1 -56
  39. data/lib/cocoapods/installer/pod_source_installer.rb +10 -8
  40. data/lib/cocoapods/installer/podfile_validator.rb +42 -1
  41. data/lib/cocoapods/installer/post_install_hooks_context.rb +19 -2
  42. data/lib/cocoapods/installer/target_installer.rb +6 -2
  43. data/lib/cocoapods/installer/target_installer/aggregate_target_installer.rb +6 -5
  44. data/lib/cocoapods/installer/target_installer/pod_target_installer.rb +82 -14
  45. data/lib/cocoapods/installer/user_project_integrator.rb +37 -16
  46. data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +14 -136
  47. data/lib/cocoapods/installer/user_project_integrator/target_integrator/xcconfig_integrator.rb +15 -22
  48. data/lib/cocoapods/project.rb +109 -19
  49. data/lib/cocoapods/resolver.rb +17 -15
  50. data/lib/cocoapods/resolver/lazy_specification.rb +4 -0
  51. data/lib/cocoapods/sandbox.rb +0 -32
  52. data/lib/cocoapods/sandbox/headers_store.rb +2 -2
  53. data/lib/cocoapods/sandbox/podspec_finder.rb +1 -1
  54. data/lib/cocoapods/sources_manager.rb +181 -50
  55. data/lib/cocoapods/target/aggregate_target.rb +17 -11
  56. data/lib/cocoapods/target/pod_target.rb +31 -4
  57. data/lib/cocoapods/user_interface.rb +32 -3
  58. data/lib/cocoapods/user_interface/error_report.rb +46 -36
  59. data/lib/cocoapods/validator.rb +132 -43
  60. metadata +164 -79
@@ -60,11 +60,7 @@ module Pod
60
60
  end
61
61
  end
62
62
  @activated = Molinillo::Resolver.new(self, self).resolve(dependencies, locked_dependencies)
63
- specs_by_target.tap do |specs_by_target|
64
- specs_by_target.values.flatten.each do |spec|
65
- sandbox.store_head_pod(spec.name) if spec.version.head?
66
- end
67
- end
63
+ specs_by_target
68
64
  rescue Molinillo::ResolverError => e
69
65
  handle_resolver_error(e)
70
66
  end
@@ -185,7 +181,7 @@ module Pod
185
181
  end
186
182
  requirement_satisfied && !(
187
183
  spec.version.prerelease? &&
188
- existing_vertices.flat_map(&:requirements).none? { |r| r.prerelease? || r.external_source || r.head? }
184
+ existing_vertices.flat_map(&:requirements).none? { |r| r.prerelease? || r.external_source }
189
185
  ) && spec_is_platform_compatible?(activated, requirement, spec)
190
186
  end
191
187
 
@@ -304,9 +300,6 @@ module Pod
304
300
  else
305
301
  set = create_set_from_sources(dependency)
306
302
  end
307
- if set && dependency.head?
308
- set = Specification::Set::Head.new(set.specification)
309
- end
310
303
  cached_sets[name] = set
311
304
  unless set
312
305
  raise Molinillo::NoSuchDependencyError.new(dependency) # rubocop:disable Style/RaiseArgs
@@ -335,13 +328,17 @@ module Pod
335
328
  # The dependency for which the set is needed.
336
329
  #
337
330
  def create_set_from_sources(dependency)
338
- aggregate.search(dependency)
331
+ aggregate_for_dependency(dependency).search(dependency)
339
332
  end
340
333
 
341
334
  # @return [Source::Aggregate] The aggregate of the {#sources}.
342
335
  #
343
- def aggregate
344
- @aggregate ||= Source::Aggregate.new(sources.map(&:repo))
336
+ def aggregate_for_dependency(dependency)
337
+ if dependency && dependency.podspec_repo
338
+ return SourcesManager.aggregate_for_dependency(dependency)
339
+ else
340
+ @aggregate ||= Source::Aggregate.new(sources.map(&:repo))
341
+ end
345
342
  end
346
343
 
347
344
  # Ensures that a specification is compatible with the platform of a target.
@@ -386,8 +383,7 @@ module Pod
386
383
  elsif (conflict.possibility && conflict.possibility.version.prerelease?) &&
387
384
  (conflict.requirement && !(
388
385
  conflict.requirement.prerelease? ||
389
- conflict.requirement.external_source ||
390
- conflict.requirement.head?)
386
+ conflict.requirement.external_source)
391
387
  )
392
388
  # Conflict was caused by not specifying an explicit version for the requirement #[name],
393
389
  # and there is no available stable version satisfying constraints for the requirement.
@@ -400,7 +396,13 @@ module Pod
400
396
  message << "\nYou should explicitly specify the version in order to install a pre-release version"
401
397
  elsif !conflict.existing
402
398
  conflict.requirements.values.flatten.each do |r|
403
- unless search_for(r).empty?
399
+ if search_for(r).empty?
400
+ # There is no existing specification inside any of the spec repos with given requirements.
401
+ message << "\n\nNone of the spec sources contain a spec satisfying the `#{r}` dependency." \
402
+ "\nYou have either; mistyped the name or version," \
403
+ ' not added the source repo that hosts the Podspec to your Podfile,' \
404
+ ' or not got the latest versions of your source repos.'
405
+ else
404
406
  message << "\n\nSpecs satisfying the `#{r}` dependency were found, " \
405
407
  'but they required a higher minimum deployment target.'
406
408
  end
@@ -14,6 +14,10 @@ module Pod
14
14
  specification.send(method, *args, &block)
15
15
  end
16
16
 
17
+ def respond_to_missing?(method, include_all = false)
18
+ specification.respond_to?(method, include_all)
19
+ end
20
+
17
21
  def subspec_by_name(name = nil, raise_if_missing = true)
18
22
  if !name || name == self.name
19
23
  self
@@ -59,7 +59,6 @@ module Pod
59
59
  @root = Pathname.new(root).realpath
60
60
  @public_headers = HeadersStore.new(self, 'Public')
61
61
  @predownloaded_pods = []
62
- @head_pods = []
63
62
  @checkout_sources = {}
64
63
  @development_pods = {}
65
64
  @pods_with_absolute_path = []
@@ -313,37 +312,6 @@ module Pod
313
312
 
314
313
  #--------------------------------------#
315
314
 
316
- # Marks a Pod as head.
317
- #
318
- # @param [String] name
319
- # The name of the Pod.
320
- #
321
- # @return [void]
322
- #
323
- def store_head_pod(name)
324
- root_name = Specification.root_name(name)
325
- head_pods << root_name
326
- end
327
-
328
- # @return [Array<String>] The names of the pods that have been
329
- # marked as head.
330
- #
331
- attr_reader :head_pods
332
-
333
- # Checks if a Pod should attempt to use the head source of the git repo.
334
- #
335
- # @param [String] name
336
- # The name of the Pod.
337
- #
338
- # @return [Bool] Whether the Pod has been marked as head.
339
- #
340
- def head_pod?(name)
341
- root_name = Specification.root_name(name)
342
- head_pods.include?(root_name)
343
- end
344
-
345
- #--------------------------------------#
346
-
347
315
  # Stores the local path of a Pod.
348
316
  #
349
317
  # @param [String] name
@@ -35,7 +35,7 @@ module Pod
35
35
  # root with the `${PODS_ROOT}` variable.
36
36
  #
37
37
  def search_paths(platform)
38
- platform_search_paths = @search_paths.select { |entry| entry[:platform] == platform }
38
+ platform_search_paths = @search_paths.select { |entry| entry[:platform] == platform.name }
39
39
 
40
40
  headers_dir = root.relative_path_from(sandbox.root).dirname
41
41
  ["${PODS_ROOT}/#{headers_dir}/#{@relative_path}"] + platform_search_paths.uniq.map { |entry| "${PODS_ROOT}/#{headers_dir}/#{entry[:path]}" }
@@ -117,7 +117,7 @@ module Pod
117
117
  # @return [void]
118
118
  #
119
119
  def add_search_path(path, platform)
120
- @search_paths << { :platform => platform, :path => (Pathname.new(@relative_path) + path) }
120
+ @search_paths << { :platform => platform.name, :path => (Pathname.new(@relative_path) + path) }
121
121
  end
122
122
 
123
123
  #-----------------------------------------------------------------------#
@@ -10,7 +10,7 @@ module Pod
10
10
  def podspecs
11
11
  return @specs_by_name if @specs_by_name
12
12
  @specs_by_name = {}
13
- spec_files = Pathname.glob(root + '{,*,*/*}.podspec{,.json}')
13
+ spec_files = Pathname.glob(root + '{,*}.podspec{,.json}')
14
14
  spec_files.sort_by { |p| -p.to_path.split(File::SEPARATOR).size }.each do |file|
15
15
  begin
16
16
  spec = Specification.from_file(file)
@@ -11,7 +11,27 @@ module Pod
11
11
  def aggregate
12
12
  return Source::Aggregate.new([]) unless config.repos_dir.exist?
13
13
  dirs = config.repos_dir.children.select(&:directory?)
14
- Source::Aggregate.new(dirs)
14
+ aggregate_with_repos(dirs)
15
+ end
16
+
17
+ # @return [Source::Aggregate] The aggregate of the sources from repos.
18
+ #
19
+ # @param [Dependency] dependency
20
+ # The dependency for which to find or build the appropriate.
21
+ # aggregate. If the dependency specifies a source podspec repo
22
+ # then only that source will be used, otherwise all sources
23
+ # will be used.
24
+ #
25
+ def aggregate_for_dependency(dependency)
26
+ if dependency.podspec_repo
27
+ source = source_with_url(dependency.podspec_repo)
28
+ raise StandardError, '[Bug] Failed to find known source with the URL ' \
29
+ "#{dependency.podspec_repo.inspect}" if source.nil?
30
+
31
+ aggregate_with_repos([source_dir(source.name)])
32
+ else
33
+ aggregate
34
+ end
15
35
  end
16
36
 
17
37
  # @return [Array<Source>] The list of the sources with the given names.
@@ -86,16 +106,16 @@ module Pod
86
106
  sources(['master'])
87
107
  end
88
108
 
89
- # Search all the sources to match the set for the given dependency.
109
+ # Search the appropriate sources to match the set for the given dependency.
90
110
  #
91
111
  # @return [Set, nil] a set for a given dependency including all the
92
112
  # {Source} that contain the Pod. If no sources containing the
93
113
  # Pod where found it returns nil.
94
114
  #
95
- # @raise If no source including the set can be found.
115
+ # @raise If no source can be found that includes the dependency.
96
116
  #
97
117
  def search(dependency)
98
- aggregate.search(dependency)
118
+ aggregate_for_dependency(dependency).search(dependency)
99
119
  end
100
120
 
101
121
  # Search all the sources with the given search term.
@@ -110,27 +130,27 @@ module Pod
110
130
  #
111
131
  # @raise If no source including the set can be found.
112
132
  #
113
- # @note Full text search requires to load the specification for each
114
- # pod, hence is considerably slower.
115
- #
116
133
  # @return [Array<Set>] The sets that contain the search term.
117
134
  #
118
135
  def search_by_name(query, full_text_search = false)
136
+ query_word_regexps = query.split.map { |word| /#{word}/i }
119
137
  if full_text_search
120
- set_names = []
121
- query_regexp = /#{query}/i
122
- updated_search_index.each do |name, set_data|
123
- texts = [name]
124
- if full_text_search
125
- texts << set_data['authors'].to_s if set_data['authors']
126
- texts << set_data['summary'] if set_data['summary']
127
- texts << set_data['description'] if set_data['description']
138
+ query_word_results_hash = {}
139
+ updated_search_index.each_value do |word_spec_hash|
140
+ word_spec_hash.each_pair do |word, spec_symbols|
141
+ query_word_regexps.each do |query_word_regexp|
142
+ set = (query_word_results_hash[query_word_regexp] ||= Set.new)
143
+ set.merge(spec_symbols) if word =~ query_word_regexp
144
+ end
128
145
  end
129
- set_names << name unless texts.grep(query_regexp).empty?
130
146
  end
131
- sets = set_names.sort.map do |name|
132
- aggregate.representative_set(name)
147
+ found_set_symbols = query_word_results_hash.values.reduce(:&)
148
+ found_set_symbols ||= []
149
+ sets = found_set_symbols.map do |symbol|
150
+ aggregate.representative_set(symbol.to_s)
133
151
  end
152
+ # Remove nil values because representative_set return nil if no pod is found in any of the sources.
153
+ sets.compact!
134
154
  else
135
155
  sets = aggregate.search_by_name(query, false)
136
156
  end
@@ -139,44 +159,94 @@ module Pod
139
159
  raise Informative, "Unable to find a pod with name#{extra}" \
140
160
  "matching `#{query}`"
141
161
  end
162
+ sorted_sets(sets, query_word_regexps)
163
+ end
164
+
165
+ # Returns given set array by sorting it in-place.
166
+ #
167
+ # @param [Array<Set>] sets
168
+ # Array of sets to be sorted.
169
+ #
170
+ # @param [Array<Regexp>] query_word_regexps
171
+ # Array of regexp objects for user query.
172
+ #
173
+ # @return [Array<Set>] Given sets parameter itself after sorting it in-place.
174
+ #
175
+ def sorted_sets(sets, query_word_regexps)
176
+ sets.sort_by! do |set|
177
+ pre_match_length = nil
178
+ found_query_index = nil
179
+ found_query_count = 0
180
+ query_word_regexps.each_with_index do |q, idx|
181
+ if (m = set.name.match(/#{q}/i))
182
+ pre_match_length ||= (m.pre_match.length)
183
+ found_query_index ||= idx
184
+ found_query_count += 1
185
+ end
186
+ end
187
+ pre_match_length ||= 1000
188
+ found_query_index ||= 1000
189
+ [-found_query_count, pre_match_length, found_query_index, set.name.downcase]
190
+ end
142
191
  sets
143
192
  end
144
193
 
145
- # Creates or updates the search data and returns it. The search data
146
- # groups by name the following information for each set:
194
+ # Returns the search data. If a saved search data exists, retrieves it from file and returns it.
195
+ # Else, creates the search data from scratch, saves it to file system, and returns it.
196
+ # Search data is grouped by source repos. For each source, it contains a hash where keys are words
197
+ # and values are the pod names containing corresponding word.
147
198
  #
199
+ # For each source, list of unique words are generated from the following spec information.
148
200
  # - version
149
201
  # - summary
150
202
  # - description
151
203
  # - authors
152
204
  #
153
- # @note This operation is fairly expensive, because of the YAML
154
- # conversion.
155
- #
156
- # @return [Hash{String => String}] The up to date search data.
205
+ # @return [Hash{String => Hash{String => Array<String>}}] The up to date search data.
157
206
  #
158
207
  def updated_search_index
208
+ index = stored_search_index || {}
209
+ all.each do |source|
210
+ source_name = source.name
211
+ unless index[source_name]
212
+ UI.print "Creating search index for spec repo '#{source_name}'.."
213
+ index[source_name] = aggregate.generate_search_index_for_source(source)
214
+ UI.puts ' Done!'
215
+ end
216
+ end
217
+ save_search_index(index)
218
+ index
219
+ end
220
+
221
+ # Returns the search data stored in the file system.
222
+ # If existing data in the file system is not valid, returns nil.
223
+ #
224
+ def stored_search_index
159
225
  unless @updated_search_index
160
226
  if search_index_path.exist?
161
- require 'yaml'
162
- stored_index = YAML.load(search_index_path.read)
163
- if stored_index && stored_index.is_a?(Hash)
164
- search_index = aggregate.update_search_index(stored_index)
165
- else
166
- search_index = aggregate.generate_search_index
227
+ require 'json'
228
+ index = JSON.parse(search_index_path.read)
229
+ if index && index.is_a?(Hash) # TODO: should we also check if hash has correct hierarchy?
230
+ return @updated_search_index = index
167
231
  end
168
- else
169
- search_index = aggregate.generate_search_index
170
- end
171
-
172
- File.open(search_index_path, 'w') do |file|
173
- file.write(search_index.to_yaml)
174
232
  end
175
- @updated_search_index = search_index
233
+ @updated_search_index = nil
176
234
  end
177
235
  @updated_search_index
178
236
  end
179
237
 
238
+ # Stores given search data in the file system.
239
+ # @param [Hash] index
240
+ # Index to be saved in file system
241
+ #
242
+ def save_search_index(index)
243
+ require 'json'
244
+ @updated_search_index = index
245
+ search_index_path.open('w') do |io|
246
+ io.write(@updated_search_index.to_json)
247
+ end
248
+ end
249
+
180
250
  # Allows to clear the search index.
181
251
  #
182
252
  attr_writer :updated_search_index
@@ -192,6 +262,48 @@ module Pod
192
262
  extend Executable
193
263
  executable :git
194
264
 
265
+ # Updates the stored search index if there are changes in spec repos while updating them.
266
+ # Update is performed incrementally. Only the changed pods' search data is re-generated and updated.
267
+ # @param [Hash{Source => Array<String>}] changed_spec_paths
268
+ # A hash containing changed specification paths for each source.
269
+ #
270
+ def update_search_index_if_needed(changed_spec_paths)
271
+ search_index = stored_search_index
272
+ return unless search_index
273
+ changed_spec_paths.each_pair do |source, spec_paths|
274
+ index_for_source = search_index[source.name]
275
+ next unless index_for_source && spec_paths.length > 0
276
+ updated_pods = source.pods_for_specification_paths(spec_paths)
277
+
278
+ new_index = aggregate.generate_search_index_for_changes_in_source(source, spec_paths)
279
+ # First traverse search_index and update existing words
280
+ # Removed traversed words from new_index after adding to search_index,
281
+ # so that only non existing words will remain in new_index after enumeration completes.
282
+ index_for_source.each_pair do |word, _|
283
+ if new_index[word]
284
+ index_for_source[word] |= new_index[word]
285
+ else
286
+ index_for_source[word] -= updated_pods
287
+ end
288
+ end
289
+ # Now add non existing words remained in new_index to search_index
290
+ index_for_source.merge!(new_index)
291
+ end
292
+ save_search_index(search_index)
293
+ end
294
+
295
+ # Updates search index for changed pods in background
296
+ # @param [Hash{Source => Array<String>}] changed_spec_paths
297
+ # A hash containing changed specification paths for each source.
298
+ #
299
+ def update_search_index_if_needed_in_background(changed_spec_paths)
300
+ Process.fork do
301
+ Process.daemon
302
+ update_search_index_if_needed(changed_spec_paths)
303
+ exit
304
+ end
305
+ end
306
+
195
307
  # Updates the local clone of the spec-repo with the given name or of all
196
308
  # the git repos if the name is omitted.
197
309
  #
@@ -208,22 +320,16 @@ module Pod
208
320
  sources = git_sources
209
321
  end
210
322
 
323
+ changed_spec_paths = {}
211
324
  sources.each do |source|
212
325
  UI.section "Updating spec repo `#{source.name}`" do
213
- Dir.chdir(source.repo) do
214
- begin
215
- output = git! %w(pull --ff-only)
216
- UI.puts output if show_output && !config.verbose?
217
- rescue Informative
218
- UI.warn 'CocoaPods was not able to update the ' \
219
- "`#{source.name}` repo. If this is an unexpected issue " \
220
- 'and persists you can inspect it running ' \
221
- '`pod repo update --verbose`'
222
- end
223
- end
326
+ changed_source_paths = source.update(show_output && !config.verbose?)
327
+ changed_spec_paths[source] = changed_source_paths if changed_source_paths.count > 0
224
328
  check_version_information(source.repo)
225
329
  end
226
330
  end
331
+ # Perform search index update operation in background.
332
+ update_search_index_if_needed_in_background(changed_spec_paths)
227
333
  end
228
334
 
229
335
  # Returns whether a source is a GIT repo.
@@ -275,7 +381,7 @@ module Pod
275
381
  ("Until we reach version 1.0 the features of CocoaPods can and will change.\n" \
276
382
  'We strongly recommend that you use the latest version at all times.'.yellow unless rc),
277
383
  '',
278
- 'For more information see http://blog.cocoapods.org'.green,
384
+ 'For more information see https://blog.cocoapods.org'.green,
279
385
  'and the CHANGELOG for this version http://git.io/BaH8pQ.'.green,
280
386
  '',
281
387
  ].compact.join("\n")
@@ -337,7 +443,7 @@ module Pod
337
443
  YAMLHelper.load_file(yaml_file)
338
444
  rescue Informative
339
445
  raise Informative, "There was an error reading '#{yaml_file}'.\n" \
340
- 'Please consult http://blog.cocoapods.org/' \
446
+ 'Please consult https://blog.cocoapods.org/' \
341
447
  'Repairing-Our-Broken-Specs-Repository/ ' \
342
448
  'for more information.'
343
449
  end
@@ -362,6 +468,16 @@ module Pod
362
468
 
363
469
  private
364
470
 
471
+ # @return [Source::Aggregate] The aggregate of the sources from repos.
472
+ #
473
+ # @param [Array<Pathname>] repos
474
+ # The local file paths to one or more podspec repo caches.
475
+ #
476
+ def aggregate_with_repos(repos)
477
+ @aggregates_by_repos ||= {}
478
+ @aggregates_by_repos[repos] ||= Source::Aggregate.new(repos)
479
+ end
480
+
365
481
  # @return [Bool] Whether the given path is writable by the current user.
366
482
  #
367
483
  # @param [#to_s] path
@@ -482,4 +598,19 @@ module Pod
482
598
  end
483
599
  end
484
600
  end
601
+
602
+ class Source
603
+ extend Executable
604
+ executable :git
605
+
606
+ def update_git_repo(show_output = false)
607
+ output = git! %w(pull --ff-only)
608
+ UI.puts output if show_output
609
+ rescue
610
+ UI.warn 'CocoaPods was not able to update the ' \
611
+ "`#{name}` repo. If this is an unexpected issue " \
612
+ 'and persists you can inspect it running ' \
613
+ '`pod repo update --verbose`'
614
+ end
615
+ end
485
616
  end