cocoapods-square-stable 0.19.3

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 (58) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +1296 -0
  3. data/LICENSE +20 -0
  4. data/README.md +94 -0
  5. data/bin/pod +16 -0
  6. data/bin/sandbox-pod +120 -0
  7. data/lib/cocoapods.rb +77 -0
  8. data/lib/cocoapods/command.rb +116 -0
  9. data/lib/cocoapods/command/help.rb +23 -0
  10. data/lib/cocoapods/command/inter_process_communication.rb +178 -0
  11. data/lib/cocoapods/command/list.rb +77 -0
  12. data/lib/cocoapods/command/outdated.rb +56 -0
  13. data/lib/cocoapods/command/podfile_info.rb +91 -0
  14. data/lib/cocoapods/command/project.rb +88 -0
  15. data/lib/cocoapods/command/push.rb +172 -0
  16. data/lib/cocoapods/command/repo.rb +145 -0
  17. data/lib/cocoapods/command/search.rb +61 -0
  18. data/lib/cocoapods/command/setup.rb +134 -0
  19. data/lib/cocoapods/command/spec.rb +590 -0
  20. data/lib/cocoapods/config.rb +231 -0
  21. data/lib/cocoapods/downloader.rb +59 -0
  22. data/lib/cocoapods/executable.rb +118 -0
  23. data/lib/cocoapods/external_sources.rb +363 -0
  24. data/lib/cocoapods/file_list.rb +36 -0
  25. data/lib/cocoapods/gem_version.rb +7 -0
  26. data/lib/cocoapods/generator/acknowledgements.rb +107 -0
  27. data/lib/cocoapods/generator/acknowledgements/markdown.rb +40 -0
  28. data/lib/cocoapods/generator/acknowledgements/plist.rb +64 -0
  29. data/lib/cocoapods/generator/bridge_support.rb +22 -0
  30. data/lib/cocoapods/generator/copy_resources_script.rb +54 -0
  31. data/lib/cocoapods/generator/dummy_source.rb +22 -0
  32. data/lib/cocoapods/generator/prefix_header.rb +82 -0
  33. data/lib/cocoapods/generator/target_environment_header.rb +86 -0
  34. data/lib/cocoapods/generator/xcconfig.rb +185 -0
  35. data/lib/cocoapods/hooks/installer_representation.rb +134 -0
  36. data/lib/cocoapods/hooks/library_representation.rb +94 -0
  37. data/lib/cocoapods/hooks/pod_representation.rb +74 -0
  38. data/lib/cocoapods/installer.rb +571 -0
  39. data/lib/cocoapods/installer/analyzer.rb +559 -0
  40. data/lib/cocoapods/installer/analyzer/sandbox_analyzer.rb +253 -0
  41. data/lib/cocoapods/installer/file_references_installer.rb +179 -0
  42. data/lib/cocoapods/installer/pod_source_installer.rb +248 -0
  43. data/lib/cocoapods/installer/target_installer.rb +379 -0
  44. data/lib/cocoapods/installer/user_project_integrator.rb +180 -0
  45. data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +224 -0
  46. data/lib/cocoapods/library.rb +202 -0
  47. data/lib/cocoapods/open_uri.rb +24 -0
  48. data/lib/cocoapods/project.rb +209 -0
  49. data/lib/cocoapods/resolver.rb +212 -0
  50. data/lib/cocoapods/sandbox.rb +343 -0
  51. data/lib/cocoapods/sandbox/file_accessor.rb +217 -0
  52. data/lib/cocoapods/sandbox/headers_store.rb +96 -0
  53. data/lib/cocoapods/sandbox/path_list.rb +208 -0
  54. data/lib/cocoapods/sources_manager.rb +276 -0
  55. data/lib/cocoapods/user_interface.rb +304 -0
  56. data/lib/cocoapods/user_interface/error_report.rb +101 -0
  57. data/lib/cocoapods/validator.rb +350 -0
  58. metadata +238 -0
@@ -0,0 +1,590 @@
1
+ # encoding: utf-8
2
+
3
+ require 'active_support/core_ext/string/inflections'
4
+
5
+ module Pod
6
+ class Command
7
+ class Spec < Command
8
+ self.abstract_command = true
9
+ self.summary = 'Manage pod specs'
10
+
11
+ #-----------------------------------------------------------------------#
12
+
13
+ class Create < Spec
14
+ self.summary = 'Create spec file stub.'
15
+
16
+ self.description = <<-DESC
17
+ Creates a PodSpec, in the current working dir, called `NAME.podspec'.
18
+ If a GitHub url is passed the spec is prepopulated.
19
+ DESC
20
+
21
+ self.arguments = '[ NAME | https://github.com/USER/REPO ]'
22
+
23
+ def initialize(argv)
24
+ @name_or_url, @url = argv.shift_argument, argv.shift_argument
25
+ super
26
+ end
27
+
28
+ def validate!
29
+ super
30
+ help! "A pod name or repo URL is required." unless @name_or_url
31
+ end
32
+
33
+ def run
34
+ if repo_id_match = (@url || @name_or_url).match(/github.com\/([^\/\.]*\/[^\/\.]*)\.*/)
35
+ # This is to make sure Faraday doesn't warn the user about the `system_timer` gem missing.
36
+ old_warn, $-w = $-w, nil
37
+ begin
38
+ require 'faraday'
39
+ ensure
40
+ $-w = old_warn
41
+ end
42
+ require 'octokit'
43
+
44
+ repo_id = repo_id_match[1]
45
+ data = github_data_for_template(repo_id)
46
+ data[:name] = @name_or_url if @url
47
+ UI.puts semantic_versioning_notice(repo_id, data[:name]) if data[:version] == '0.0.1'
48
+ else
49
+ data = default_data_for_template(@name_or_url)
50
+ end
51
+ spec = spec_template(data)
52
+ (Pathname.pwd + "#{data[:name]}.podspec").open('w') { |f| f << spec }
53
+ UI.puts "\nSpecification created at #{data[:name]}.podspec".green
54
+ end
55
+ end
56
+
57
+ #-----------------------------------------------------------------------#
58
+
59
+ class Lint < Spec
60
+ self.summary = 'Validates a spec file.'
61
+
62
+ self.description = <<-DESC
63
+ Validates `NAME.podspec'. If a directory is provided it validates
64
+ the podspec files found, including subfolders. In case
65
+ the argument is omitted, it defaults to the current working dir.
66
+ DESC
67
+
68
+ self.arguments = '[ NAME.podspec | DIRECTORY | http://PATH/NAME.podspec, ... ]'
69
+
70
+ def self.options
71
+ [ ["--quick", "Lint skips checks that would require to download and build the spec"],
72
+ ["--local", "Lint a podspec against the local files contained in its directory"],
73
+ ["--only-errors", "Lint validates even if warnings are present"],
74
+ ["--no-clean", "Lint leaves the build directory intact for inspection"] ].concat(super)
75
+ end
76
+
77
+ def initialize(argv)
78
+ @quick = argv.flag?('quick')
79
+ @local = argv.flag?('local')
80
+ @only_errors = argv.flag?('only-errors')
81
+ @clean = argv.flag?('clean', true)
82
+ @podspecs_paths = argv.arguments!
83
+ super
84
+ end
85
+
86
+ def run
87
+ UI.puts
88
+ invalid_count = 0
89
+ podspecs_to_lint.each do |podspec|
90
+ validator = Validator.new(podspec)
91
+ validator.quick = @quick
92
+ validator.local = @local
93
+ validator.no_clean = !@clean
94
+ validator.only_errors = @only_errors
95
+ validator.validate
96
+ invalid_count += 1 unless validator.validated?
97
+
98
+ unless @clean
99
+ UI.puts "Pods project available at `#{validator.validation_dir}/Pods/Pods.xcodeproj` for inspection."
100
+ UI.puts
101
+ end
102
+ end
103
+
104
+ count = podspecs_to_lint.count
105
+ UI.puts "Analyzed #{count} #{'podspec'.pluralize(count)}.\n\n"
106
+ if invalid_count == 0
107
+ lint_passed_message = count == 1 ? "#{podspecs_to_lint.first.basename} passed validation." : "All the specs passed validation."
108
+ UI.puts lint_passed_message.green << "\n\n"
109
+ else
110
+ raise Informative, count == 1 ? "The spec did not pass validation." : "#{invalid_count} out of #{count} specs failed validation."
111
+ end
112
+ podspecs_tmp_dir.rmtree if podspecs_tmp_dir.exist?
113
+ end
114
+ end
115
+
116
+ #-----------------------------------------------------------------------#
117
+
118
+ class Which < Spec
119
+ self.summary = 'Prints the path of the given spec.'
120
+
121
+ self.description = <<-DESC
122
+ Prints the path of 'NAME.podspec'
123
+ DESC
124
+
125
+ self.arguments = '[ NAME ]'
126
+
127
+ def self.options
128
+ [["--show-all", "Print all versions of the given podspec"]].concat(super)
129
+ end
130
+
131
+ def initialize(argv)
132
+ @show_all = argv.flag?('show-all')
133
+ @spec = argv.shift_argument
134
+ @spec = @spec.gsub('.podspec', '') unless @spec.nil?
135
+ super
136
+ end
137
+
138
+ def validate!
139
+ super
140
+ help! "A podspec name is required." unless @spec
141
+ end
142
+
143
+ def run
144
+ UI.puts get_path_of_spec(@spec, @show_all)
145
+ end
146
+ end
147
+
148
+ #-----------------------------------------------------------------------#
149
+
150
+ class Cat < Spec
151
+ self.summary = 'Prints a spec file.'
152
+
153
+ self.description = <<-DESC
154
+ Prints 'NAME.podspec' to standard output.
155
+ DESC
156
+
157
+ self.arguments = '[ NAME ]'
158
+
159
+ def self.options
160
+ [["--show-all", "Pick from all versions of the given podspec"]].concat(super)
161
+ end
162
+
163
+ def initialize(argv)
164
+ @show_all = argv.flag?('show-all')
165
+ @spec = argv.shift_argument
166
+ @spec = @spec.gsub('.podspec', '') unless @spec.nil?
167
+ super
168
+ end
169
+
170
+ def validate!
171
+ super
172
+ help! "A podspec name is required." unless @spec
173
+ end
174
+
175
+ def run
176
+ filepath = if @show_all
177
+ specs = get_path_of_spec(@spec, @show_all).split(/\n/)
178
+ index = choose_from_array(specs, "Which spec would you like to print [1-#{ specs.count }]? ")
179
+ specs[index]
180
+ else
181
+ get_path_of_spec(@spec)
182
+ end
183
+
184
+ UI.puts File.open(filepath).read
185
+ end
186
+ end
187
+
188
+ #-----------------------------------------------------------------------#
189
+
190
+ class Edit < Spec
191
+ self.summary = 'Edit a spec file.'
192
+
193
+ self.description = <<-DESC
194
+ Opens 'NAME.podspec' to be edited.
195
+ DESC
196
+
197
+ self.arguments = '[ NAME ]'
198
+
199
+ def self.options
200
+ [["--show-all", "Pick which spec to edit from all available versions of the given podspec"]].concat(super)
201
+ end
202
+
203
+ def initialize(argv)
204
+ @show_all = argv.flag?('show-all')
205
+ @spec = argv.shift_argument
206
+ @spec = @spec.gsub('.podspec', '') unless @spec.nil?
207
+ super
208
+ end
209
+
210
+ def validate!
211
+ super
212
+ help! "A podspec name is required." unless @spec
213
+ end
214
+
215
+ def run
216
+ filepath = if @show_all
217
+ specs = get_path_of_spec(@spec, @show_all).split(/\n/)
218
+ index = choose_from_array(specs, "Which spec would you like to edit [1-#{ specs.count }]? ")
219
+ specs[index]
220
+ else
221
+ get_path_of_spec(@spec)
222
+ end
223
+
224
+ exec_editor(filepath.to_s) if File.exists? filepath
225
+ raise Informative, "#{ filepath } doesn't exist."
226
+ end
227
+
228
+ # Thank you homebrew
229
+ def which(cmd)
230
+ dir = ENV['PATH'].split(':').find { |p| File.executable? File.join(p, cmd) }
231
+ Pathname.new(File.join(dir, cmd)) unless dir.nil?
232
+ end
233
+
234
+ def which_editor
235
+ editor = ENV['EDITOR']
236
+ # If an editor wasn't set, try to pick a sane default
237
+ return editor unless editor.nil?
238
+
239
+ # Find Sublime Text 2
240
+ return 'subl' if which 'subl'
241
+ # Find Textmate
242
+ return 'mate' if which 'mate'
243
+ # Find # BBEdit / TextWrangler
244
+ return 'edit' if which 'edit'
245
+ # Default to vim
246
+ return 'vim' if which 'vim'
247
+
248
+ raise Informative, "Failed to open editor. Set your 'EDITOR' environment variable."
249
+ end
250
+
251
+ def exec_editor *args
252
+ return if args.to_s.empty?
253
+ safe_exec(which_editor, *args)
254
+ end
255
+
256
+ def safe_exec(cmd, *args)
257
+ # This buys us proper argument quoting and evaluation
258
+ # of environment variables in the cmd parameter.
259
+ exec "/bin/sh", "-i", "-c", cmd + ' "$@"', "--", *args
260
+ end
261
+ end
262
+
263
+ #-----------------------------------------------------------------------#
264
+
265
+ # @todo some of the following methods can probably move to one of the
266
+ # subclasses.
267
+
268
+ private
269
+
270
+ # @return [Fixnum] the index of the chosen array item
271
+ #
272
+ def choose_from_array(array, message)
273
+ array.each_with_index do |item, index|
274
+ UI.puts "#{ index + 1 }: #{ item }"
275
+ end
276
+
277
+ print message
278
+
279
+ index = STDIN.gets.chomp.to_i - 1
280
+ if index < 0 || index > array.count
281
+ raise Informative, "#{ index + 1 } is invalid [1-#{ array.count }]"
282
+ else
283
+ index
284
+ end
285
+ end
286
+
287
+ # @param [String] spec
288
+ # The name of the specification.
289
+ #
290
+ # @param [Bool] show_all
291
+ # Whether the paths for all the versions should be returned or
292
+ # only the one for the last version.
293
+ #
294
+ # @return [Pathname] the absolute path or paths of the given podspec
295
+ #
296
+ def get_path_of_spec(spec, show_all = false)
297
+ sets = SourcesManager.search_by_name(spec)
298
+
299
+ if sets.count == 1
300
+ set = sets.first
301
+ elsif sets.map(&:name).include?(spec)
302
+ set = sets.find { |s| s.name == spec }
303
+ else
304
+ names = sets.collect(&:name) * ', '
305
+ raise Informative, "More than one spec found for '#{ spec }':\n#{ names }"
306
+ end
307
+
308
+ unless show_all
309
+ best_spec, spec_source = spec_and_source_from_set(set)
310
+ return pathname_from_spec(best_spec, spec_source)
311
+ end
312
+
313
+ return all_paths_from_set(set)
314
+ end
315
+
316
+ # @return [Pathname] the absolute path of the given spec and source
317
+ #
318
+ def pathname_from_spec(spec, source)
319
+ Pathname.new("~/.cocoapods/#{ source }/#{ spec.name }/#{ spec.version }/#{ spec.name }.podspec").expand_path
320
+ end
321
+
322
+ # @return [String] of spec paths one on each line
323
+ #
324
+ def all_paths_from_set(set)
325
+ paths = ""
326
+
327
+ sources = set.sources
328
+
329
+ sources.each do |source|
330
+ versions = source.versions(set.name)
331
+
332
+ versions.each do |version|
333
+ spec = source.specification(set.name, version)
334
+ paths += "#{ pathname_from_spec(spec, source) }\n"
335
+ end
336
+ end
337
+
338
+ paths
339
+ end
340
+
341
+ # @return [Specification, Source] the highest known specification with it's source of the given
342
+ # set.
343
+ #
344
+ def spec_and_source_from_set(set)
345
+ sources = set.sources
346
+
347
+ best_source = sources.first
348
+ best_version = best_source.versions(set.name).first
349
+ sources.each do |source|
350
+ version = source.versions(set.name).first
351
+ if version > best_version
352
+ best_source = source
353
+ best_version = version
354
+ end
355
+ end
356
+
357
+ return best_source.specification(set.name, best_version), best_source
358
+ end
359
+
360
+ def podspecs_to_lint
361
+ @podspecs_to_lint ||= begin
362
+ files = []
363
+ @podspecs_paths << '.' if @podspecs_paths.empty?
364
+ @podspecs_paths.each do |path|
365
+ if path =~ /https?:\/\//
366
+ require 'open-uri'
367
+ output_path = podspecs_tmp_dir + File.basename(path)
368
+ output_path.dirname.mkpath
369
+ open(path) do |io|
370
+ output_path.open('w') { |f| f << io.read }
371
+ end
372
+ files << output_path
373
+ else if (pathname = Pathname.new(path)).directory?
374
+ files += Pathname.glob(pathname + '**/*.podspec')
375
+ raise Informative, "No specs found in the current directory." if files.empty?
376
+ else
377
+ files << (pathname = Pathname.new(path))
378
+ raise Informative, "Unable to find a spec named `#{path}'." unless pathname.exist? && path.include?('.podspec')
379
+ end
380
+ end
381
+ end
382
+ files
383
+ end
384
+ end
385
+
386
+ def podspecs_tmp_dir
387
+ Pathname.new('/tmp/CocoaPods/Lint_podspec')
388
+ end
389
+
390
+ #--------------------------------------#
391
+
392
+ # Templates and github information retrieval for spec create
393
+ #
394
+ # @todo It would be nice to have a template class that accepts options
395
+ # and uses the default ones if not provided.
396
+ # @todo The template is outdated.
397
+
398
+ def default_data_for_template(name)
399
+ data = {}
400
+ data[:name] = name
401
+ data[:version] = '0.0.1'
402
+ data[:summary] = "A short description of #{name}."
403
+ data[:homepage] = "http://EXAMPLE/#{name}"
404
+ data[:author_name] = `git config --get user.name`.strip
405
+ data[:author_email] = `git config --get user.email`.strip
406
+ data[:source_url] = "http://EXAMPLE/#{name}.git"
407
+ data[:ref_type] = ':tag'
408
+ data[:ref] = '0.0.1'
409
+ data
410
+ end
411
+
412
+ def github_data_for_template(repo_id)
413
+ repo = Octokit.repo(repo_id)
414
+ user = Octokit.user(repo['owner']['login'])
415
+ data = {}
416
+
417
+ data[:name] = repo['name']
418
+ data[:summary] = (repo['description'] || '').gsub(/["]/, '\"')
419
+ data[:homepage] = (repo['homepage'] && !repo['homepage'].empty? ) ? repo['homepage'] : repo['html_url']
420
+ data[:author_name] = user['name'] || user['login']
421
+ data[:author_email] = user['email'] || 'email@address.com'
422
+ data[:source_url] = repo['clone_url']
423
+
424
+ data.merge suggested_ref_and_version(repo)
425
+ end
426
+
427
+ def suggested_ref_and_version(repo)
428
+ tags = Octokit.tags(:username => repo['owner']['login'], :repo => repo['name']).map {|tag| tag["name"]}
429
+ versions_tags = {}
430
+ tags.each do |tag|
431
+ clean_tag = tag.gsub(/^v(er)? ?/,'')
432
+ versions_tags[Gem::Version.new(clean_tag)] = tag if Gem::Version.correct?(clean_tag)
433
+ end
434
+ version = versions_tags.keys.sort.last || '0.0.1'
435
+ data = {:version => version}
436
+ if version == '0.0.1'
437
+ branches = Octokit.branches(:username => repo['owner']['login'], :repo => repo['name'])
438
+ master_name = repo['master_branch'] || 'master'
439
+ master = branches.select {|branch| branch['name'] == master_name }.first
440
+ data[:ref_type] = ':commit'
441
+ data[:ref] = master['commit']['sha']
442
+ else
443
+ data[:ref_type] = ':tag'
444
+ data[:ref] = versions_tags[version]
445
+ end
446
+ data
447
+ end
448
+
449
+ def spec_template(data)
450
+ return <<-SPEC
451
+ #
452
+ # Be sure to run `pod spec lint #{data[:name]}.podspec' to ensure this is a
453
+ # valid spec and remove all comments before submitting the spec.
454
+ #
455
+ # To learn more about the attributes see http://docs.cocoapods.org/specification.html
456
+ #
457
+ Pod::Spec.new do |s|
458
+ s.name = "#{data[:name]}"
459
+ s.version = "#{data[:version]}"
460
+ s.summary = "#{data[:summary]}"
461
+ # s.description = <<-DESC
462
+ # An optional longer description of #{data[:name]}
463
+ #
464
+ # * Markdown format.
465
+ # * Don't worry about the indent, we strip it!
466
+ # DESC
467
+ s.homepage = "#{data[:homepage]}"
468
+ # s.screenshots = "www.example.com/screenshots_1", "www.example.com/screenshots_2"
469
+
470
+ # Specify the license type. CocoaPods detects automatically the license file if it is named
471
+ # 'LICENCE*.*' or 'LICENSE*.*', however if the name is different, specify it.
472
+ s.license = 'MIT (example)'
473
+ # s.license = { :type => 'MIT (example)', :file => 'FILE_LICENSE' }
474
+
475
+ # Specify the authors of the library, with email addresses. You can often find
476
+ # the email addresses of the authors by using the SCM log. E.g. $ git log
477
+ #
478
+ s.author = { "#{data[:author_name]}" => "#{data[:author_email]}" }
479
+ # s.authors = { "#{data[:author_name]}" => "#{data[:author_email]}", "other author" => "and email address" }
480
+ #
481
+ # If absolutely no email addresses are available, then you can use this form instead.
482
+ #
483
+ # s.author = '#{data[:author_name]}', 'other author'
484
+
485
+ # Specify the location from where the source should be retrieved.
486
+ #
487
+ s.source = { :git => "#{data[:source_url]}", #{data[:ref_type]} => "#{data[:ref]}" }
488
+
489
+
490
+ # If this Pod runs only on iOS or OS X, then specify the platform and
491
+ # the deployment target.
492
+ #
493
+ # s.platform = :ios, '5.0'
494
+
495
+ # ――― MULTI-PLATFORM VALUES ――――――――――――――――――――――――――――――――――――――――――――――――― #
496
+
497
+ # If this Pod runs on both platforms, then specify the deployment
498
+ # targets.
499
+ #
500
+ # s.ios.deployment_target = '5.0'
501
+ # s.osx.deployment_target = '10.7'
502
+
503
+ # A list of file patterns which select the source files that should be
504
+ # added to the Pods project. If the pattern is a directory then the
505
+ # path will automatically have '*.{h,m,mm,c,cpp}' appended.
506
+ #
507
+ s.source_files = 'Classes', 'Classes/**/*.{h,m}'
508
+ s.exclude_files = 'Classes/Exclude'
509
+
510
+ # A list of file patterns which select the header files that should be
511
+ # made available to the application. If the pattern is a directory then the
512
+ # path will automatically have '*.h' appended.
513
+ #
514
+ # If you do not explicitly set the list of public header files,
515
+ # all headers of source_files will be made public.
516
+ #
517
+ # s.public_header_files = 'Classes/**/*.h'
518
+
519
+ # A list of resources included with the Pod. These are copied into the
520
+ # target bundle with a build phase script.
521
+ #
522
+ # s.resource = "icon.png"
523
+ # s.resources = "Resources/*.png"
524
+
525
+ # A list of paths to preserve after installing the Pod.
526
+ # CocoaPods cleans by default any file that is not used.
527
+ # Please don't include documentation, example, and test files.
528
+ #
529
+ # s.preserve_paths = "FilesToSave", "MoreFilesToSave"
530
+
531
+ # Specify a list of frameworks that the application needs to link
532
+ # against for this Pod to work.
533
+ #
534
+ # s.framework = 'SomeFramework'
535
+ # s.frameworks = 'SomeFramework', 'AnotherFramework'
536
+
537
+ # Specify a list of libraries that the application needs to link
538
+ # against for this Pod to work.
539
+ #
540
+ # s.library = 'iconv'
541
+ # s.libraries = 'iconv', 'xml2'
542
+
543
+ # If this Pod uses ARC, specify it like so.
544
+ #
545
+ s.requires_arc = true
546
+
547
+ # If you need to specify any other build settings, add them to the
548
+ # xcconfig hash.
549
+ #
550
+ # s.xcconfig = { 'HEADER_SEARCH_PATHS' => '$(SDKROOT)/usr/include/libxml2' }
551
+
552
+ # Finally, specify any Pods that this Pod depends on.
553
+ #
554
+ # s.dependency 'JSONKit', '~> 1.4'
555
+ end
556
+ SPEC
557
+ end
558
+
559
+ def semantic_versioning_notice(repo_id, repo)
560
+ return <<-EOS
561
+
562
+ #{'――― MARKDOWN TEMPLATE ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――'.reversed}
563
+
564
+ I’ve recently added [#{repo}](https://github.com/CocoaPods/Specs/tree/master/#{repo}) to the [CocoaPods](https://github.com/CocoaPods/CocoaPods) package manager repo.
565
+
566
+ CocoaPods is a tool for managing dependencies for OSX and iOS Xcode projects and provides a central repository for iOS/OSX libraries. This makes adding libraries to a project and updating them extremely easy and it will help users to resolve dependencies of the libraries they use.
567
+
568
+ However, #{repo} doesn't have any version tags. I’ve added the current HEAD as version 0.0.1, but a version tag will make dependency resolution much easier.
569
+
570
+ [Semantic version](http://semver.org) tags (instead of plain commit hashes/revisions) allow for [resolution of cross-dependencies](https://github.com/CocoaPods/Specs/wiki/Cross-dependencies-resolution-example).
571
+
572
+ In case you didn’t know this yet; you can tag the current HEAD as, for instance, version 1.0.0, like so:
573
+
574
+ ```
575
+ $ git tag -a 1.0.0 -m "Tag release 1.0.0"
576
+ $ git push --tags
577
+ ```
578
+
579
+ #{'――― TEMPLATE END ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――'.reversed}
580
+
581
+ #{'[!] This repo does not appear to have semantic version tags.'.yellow}
582
+
583
+ After commiting the specification, consider opening a ticket with the template displayed above:
584
+ - link: https://github.com/#{repo_id}/issues/new
585
+ - title: Please add semantic version tags
586
+ EOS
587
+ end
588
+ end
589
+ end
590
+ end