cocoapods-square-stable 0.19.3

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