From 368b7086412e0d4a15ceb5bc238124d1441dcb0c Mon Sep 17 00:00:00 2001 From: Fabio Pelosin Date: Fri, 13 Apr 2012 13:39:11 +0200 Subject: [PATCH 1/4] Draft for spec create from GitHub --- Gemfile | 2 + Gemfile.lock | 4 + lib/cocoapods/command/spec.rb | 245 +++++++++++++++++++++++++++++----- 3 files changed, 215 insertions(+), 36 deletions(-) diff --git a/Gemfile b/Gemfile index 08b34370cc..7b1c72445d 100644 --- a/Gemfile +++ b/Gemfile @@ -3,6 +3,7 @@ source "http://rubygems.org" gem "open4" gem "colored" gem "escape" +gem "json" group :development do gem "xcodeproj", :git => "git://github.com/CocoaPods/Xcodeproj.git" @@ -14,4 +15,5 @@ group :development do gem "rb-fsevent" gem "vcr" gem "webmock" + gem "awesome_print" end diff --git a/Gemfile.lock b/Gemfile.lock index 2a120e4297..e071fd297e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -8,10 +8,12 @@ GEM remote: http://rubygems.org/ specs: addressable (2.2.7) + awesome_print (1.0.2) bacon (1.1.0) colored (1.2) crack (0.3.1) escape (0.0.4) + json (1.6.6) kicker (2.5.0) rb-fsevent metaclass (0.0.1) @@ -31,9 +33,11 @@ PLATFORMS ruby DEPENDENCIES + awesome_print bacon colored escape + json kicker mocha-on-bacon open4 diff --git a/lib/cocoapods/command/spec.rb b/lib/cocoapods/command/spec.rb index 8003610ce3..8bc6571851 100644 --- a/lib/cocoapods/command/spec.rb +++ b/lib/cocoapods/command/spec.rb @@ -1,14 +1,21 @@ +require 'net/https' +require 'uri' +require 'json' +require 'awesome_print' + module Pod class Command class Spec < Command def self.banner -%{Managing PodSpec files: + %{Managing PodSpec files: - $ pod spec create NAME + $ pod spec create [NAME] + $ pod spec create [https://github.com/user/repo] Creates a PodSpec, in the current working dir, called `NAME.podspec'. + If a GitHub url is passed the spec is prepopulated. - $ pod spec lint NAME.podspec + $ pod spec lint [NAME.podspec] Validates `NAME.podspec'. In case `NAME.podspec' is omitted, it defaults to `*.podspec' in the current working dir.} @@ -17,7 +24,7 @@ def self.banner def initialize(argv) args = argv.arguments unless (args[0] == 'create' && args.size == 2) || - (args[0] == 'lint' && args.size <= 2) + (args[0] == 'lint' && args.size <= 2) super end @action, @name = args.first(2) @@ -28,8 +35,70 @@ def run end def create - author = `git config --get user.name`.strip - email = `git config --get user.email`.strip + spec = is_git_hub ? github_spec_doc : spec_doc + (Pathname.pwd + "#{@name}.podspec").open('w') { |f| f << spec } + end + + def lint + file = @name ? Pathname.new(@name) : Pathname.pwd.glob('*.podspec').first + spec = Specification.from_file(file) + puts "\nThe #{spec.name} specification contains all the required attributes.".green if spec.validate! + + warnings = [] + warnings << 'The name of the specificaiton should match the name of the podspec file' if spec.name + '.podspec' != @name + warnings << 'Missing license[:type]' unless spec.license && spec.license[:type] + warnings << 'Missing license[:file] or [:text]' unless spec.license && (spec.license[:file] || spec.license[:text]) + warnings << "Github repositories should end in `.git'" if spec.source[:git] =~ /github.com/ && spec.source[:git] !~ /.*\.git/ + warnings << "Github repositories should end in `.git'" if spec.source[:git] =~ /github.com/ && spec.source[:git] !~ /.*\.git/ + warnings << "The description should end with a dot" if spec.description && spec.description !~ /.*\./ + warnings << "The summary should end with a dot" if spec.summary !~ /.*\./ + unless warnings.empty? + puts "\n[!] The #{spec.name} specification raised the following warnings".yellow + warnings.each { |warn| puts ' - '+ warn } + end + puts + end + + private + + def is_git_hub + @name =~ /https:\/\/github.com\/.*\/.*/ + end + + def find_github_info + full, user, repo = *(@name.match /https:\/\/github.com\/(.*)\/(.*)/).to_a + user_data = fetch_request("users/#{user}") + repo_data = fetch_request("repos/#{user}/#{repo}") + tags_data = fetch_request("repos/#{user}/#{repo}/tags") + [user_data, repo_data, tags_data] + end + + def fetch_request(request_url) + uri = URI.parse("https://api.github.com/#{request_url}") + http = Net::HTTP.new(uri.host, uri.port) + http.use_ssl = true + http.verify_mode = OpenSSL::SSL::VERIFY_NONE + request = Net::HTTP::Get.new(uri.request_uri) + response = http.request(request) + JSON.parse(response.body) if response.is_a?(Net::HTTPSuccess) + end + + def find_suggested_tag(tags_data) + tags = tags_data.map {|hash| hash["name"] } + versions = tags.reject {|t| t !~ /[0-9]+\.[0-9]+\.?[0-9]*/ } + versions.sort.last || '0.0.1' + end + + def version_from_tag(tag) + tag.match /[0-9]+\.[0-9]+\.?[0-9]*/ + end + + def github_spec_doc + user_data, repo_data, tags_data = find_github_info + tag = find_suggested_tag(tags_data) + version = version_from_tag(tag) + + @name = repo_data["name"] spec = <<-SPEC.gsub(/^ /, '') # # Be sure to run `pod spec lint #{@name}.podspec' to ensure this is a @@ -38,10 +107,136 @@ def create # Remove all comments before submitting the spec. # Pod::Spec.new do |s| + + # ――― REQUIRED ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― + s.name = '#{@name}' + s.version = '#{version}' + s.summary = '#{repo_data["description"].gsub(/[']/, '\\\\\'')}' + s.homepage = '#{repo_data["homepage"] != "" ? repo_data["homepage"] : repo_data["html_url"]}' + s.source = { :git => '#{repo_data["clone_url"]}', :tag => '#{tag}' } + s.author = { '#{user_data["name"]}' => '#{user_data["email"]}' } + # s.author = { '#{user_data["name"]}' => '#{user_data["email"]}', 'other author' => 'and email address' } + + # Specify the license of the pod. + # :type The type of the license. + # :file The file containing the license of the pod. + # :range If a dedicated license file is not available specify a file + # that contains the license and the range of the lines + # containing the license. + # :text If the license is not available in any of the files it should be + # included here. + s.license = { + :type => 'MIT', + :file => 'LICENSE', + # :range => 1..15, + # :text => 'Permission is hereby granted ...' + } + + # A list of file patterns which select the source files that should be + # added to the Pods project. If the pattern is a directory then the + # path will automatically have '*.{h,m,mm,c,cpp}' appended. + # + # Alternatively, you can use the FileList class for even more control + # over the selected files. + # (See http://rake.rubyforge.org/classes/Rake/FileList.html.) + # + s.source_files = 'Classes', 'Classes/**/*.{h,m}' + + # ――― OPTIONAL ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― + + s.description = 'An optional longer description of #{@name}.' + + # If this Pod runs only on iOS or OS X, then specify that with one of + # these, or none if it runs on both platforms. + # + # s.platform = :ios + # s.platform = :osx + + # A list of resources included with the Pod. These are copied into the + # target bundle with a build phase script. + # + # Also allows the use of the FileList class like `source_files does. + # + # s.resource = "icon.png" + # s.resources = "Resources/*.png" + + # A list of paths to remove after installing the Pod without the + # `--no-clean' option. These can be examples, docs, and any other type + # of files that are not needed to build the Pod. + # + # *NOTE*: Never remove license and README files. + # + # Also allows the use of the FileList class like `source_files does. + # + # s.clean_path = "examples" + # s.clean_paths = "examples", "doc" + + # Specify a list of frameworks that the application needs to link + # against for this Pod to work. + # + # s.framework = 'SomeFramework' + # s.frameworks = 'SomeFramework', 'AnotherFramework' + + # Specify a list of libraries that the application needs to link + # against for this Pod to work. + # + # s.library = 'iconv' + # s.libraries = 'iconv', 'xml2' + + # If this Pod uses ARC, specify it like so. + # + # s.requires_arc = true + + # Finally, specify any Pods that this Pod depends on. + # + # s.dependency 'JSONKit', '~> 1.4' + # + # ――― EXTRA ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― + + # If you need to specify any other build settings, add them to the + # xcconfig hash. + # + # s.xcconfig = { 'HEADER_SEARCH_PATHS' => '$(SDKROOT)/usr/include/libxml2' } + + # If available specify the documentation homepage. + # :html The online link for the documentation. + # :appledoc Ammend the default appledoc options used + # by cocoapods if needed. + # + # s.documentation = { + # :html => 'http://EXAMPLE/#{@name}/documentation', + # :appledoc => [ + # '--project-name', '#{@name}', + # '--project-company', 'Company Name', + # '--docset-copyright', copyright, + # '--ignore', 'Common', + # '--index-desc', 'readme.markdown', + # '--no-keep-undocumented-objects', + # '--no-keep-undocumented-members', + # ] + # } + + end + SPEC + end + + def spec_doc + name = @name + author = `git config --get user.name`.strip + email = `git config --get user.email`.strip + spec = <<-SPEC.gsub(/^ /, '') + # + # Be sure to run `pod spec lint #{name}.podspec' to ensure this is a + # valid spec. + # + # Remove all comments before submitting the spec. + # + Pod::Spec.new do |s| + s.name = '#{name}' s.version = '1.0.0' - s.summary = 'A short description of #{@name}.' - s.homepage = 'http://EXAMPLE/#{@name}' + s.summary = 'A short description of #{name}.' + s.homepage = 'http://EXAMPLE/#{name}' # Specify the authors of the library, with email addresses. You can often find # the email addresses of the authors by using the SCM log. E.g. $ git log @@ -53,11 +248,11 @@ def create # Specify the location from where the source should be retreived. # - s.source = { :git => 'http://EXAMPLE/#{@name}.git', :tag => '1.0.0' } - # s.source = { :svn => 'http://EXAMPLE/#{@name}/tags/1.0.0' } - # s.source = { :hg => 'http://EXAMPLE/#{@name}', :revision => '1.0.0' } + s.source = { :git => 'http://EXAMPLE/#{name}.git', :tag => '1.0.0' } + # s.source = { :svn => 'http://EXAMPLE/#{name}/tags/1.0.0' } + # s.source = { :hg => 'http://EXAMPLE/#{name}', :revision => '1.0.0' } - s.description = 'An optional longer description of #{@name}.' + s.description = 'An optional longer description of #{name}.' # If available specify the documentation homepage. # :html The online link for the documentation. @@ -65,9 +260,9 @@ def create # by cocoapods if needed. # s.documentation = { - # :html => 'http://EXAMPLE/#{@name}/documentation', + # :html => 'http://EXAMPLE/#{name}/documentation', # :appledoc => [ - # '--project-name', '#{@name}', + # '--project-name', '#{name}', # '--project-company', 'Company Name', # '--docset-copyright', copyright, # '--ignore', 'Common', @@ -151,29 +346,7 @@ def create # Finally, specify any Pods that this Pod depends on. # # s.dependency 'JSONKit', '~> 1.4' - end SPEC - (Pathname.pwd + "#{@name}.podspec").open('w') { |f| f << spec } - end - - def lint - file = @name ? Pathname.new(@name) : Pathname.pwd.glob('*.podspec').first - spec = Specification.from_file(file) - - puts "\nThe #{spec.name} specification contains all the required attributes.".green if spec.validate! - - warnings = [] - warnings << 'The name of the specificaiton should match the name of the podspec file' if spec.name + '.podspec' != @name - warnings << 'Missing license[:type]' unless spec.license && spec.license[:type] - warnings << 'Missing license[:file] or [:text]' unless spec.license && (spec.license[:file] || spec.license[:text]) - warnings << "Github repositories should end in `.git'" if spec.source[:git] =~ /github.com/ && spec.source[:git] !~ /.*\.git/ - - - unless warnings.empty? - puts "\n[!] The #{spec.name} specification raised the following warnings".yellow - warnings.each { |warn| puts ' - '+ warn } - end - puts end end end From 20613c188fa8466725a5216b6fd9303367684d79 Mon Sep 17 00:00:00 2001 From: Fabio Pelosin Date: Sat, 14 Apr 2012 17:49:19 +0200 Subject: [PATCH 2/4] GitHub support for pod spec create - added semanting versioning notice - warning if a spec description or summary does not ends with a dot - requires octokit gem - added awesome-print development gem - removed appledoc options from spec template - removed range attribute for license from the spec template --- Gemfile | 1 + Gemfile.lock | 17 ++ lib/cocoapods/command/spec.rb | 486 ++++++++++++++-------------------- 3 files changed, 213 insertions(+), 291 deletions(-) diff --git a/Gemfile b/Gemfile index 7b1c72445d..1d86f10d72 100644 --- a/Gemfile +++ b/Gemfile @@ -4,6 +4,7 @@ gem "open4" gem "colored" gem "escape" gem "json" +gem "octokit" group :development do gem "xcodeproj", :git => "git://github.com/CocoaPods/Xcodeproj.git" diff --git a/Gemfile.lock b/Gemfile.lock index e071fd297e..fa4059ee7b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -13,6 +13,13 @@ GEM colored (1.2) crack (0.3.1) escape (0.0.4) + faraday (0.7.6) + addressable (~> 2.2) + multipart-post (~> 1.1) + rack (~> 1.1) + faraday_middleware (0.8.6) + faraday (>= 0.7.4, < 0.9) + hashie (1.2.0) json (1.6.6) kicker (2.5.0) rb-fsevent @@ -21,7 +28,16 @@ GEM metaclass (~> 0.0.1) mocha-on-bacon (0.2.0) mocha (>= 0.9.8) + multi_json (1.1.0) + multipart-post (1.1.5) + octokit (1.0.1) + addressable (~> 2.2) + faraday (~> 0.7) + faraday_middleware (~> 0.8) + hashie (~> 1.2) + multi_json (~> 1.0) open4 (1.3.0) + rack (1.4.1) rake (0.9.2.2) rb-fsevent (0.9.0) vcr (2.0.0) @@ -40,6 +56,7 @@ DEPENDENCIES json kicker mocha-on-bacon + octokit open4 rake rb-fsevent diff --git a/lib/cocoapods/command/spec.rb b/lib/cocoapods/command/spec.rb index 8bc6571851..8c51e0b16d 100644 --- a/lib/cocoapods/command/spec.rb +++ b/lib/cocoapods/command/spec.rb @@ -1,7 +1,8 @@ require 'net/https' require 'uri' -require 'json' +require 'octokit' require 'awesome_print' +require 'json' module Pod class Command @@ -10,7 +11,7 @@ def self.banner %{Managing PodSpec files: $ pod spec create [NAME] - $ pod spec create [https://github.com/user/repo] + $ pod spec create [https://github.com/USER/REPO] Creates a PodSpec, in the current working dir, called `NAME.podspec'. If a GitHub url is passed the spec is prepopulated. @@ -27,7 +28,7 @@ def initialize(argv) (args[0] == 'lint' && args.size <= 2) super end - @action, @name = args.first(2) + @action, @name_or_url = args.first(2) end def run @@ -35,23 +36,31 @@ def run end def create - spec = is_git_hub ? github_spec_doc : spec_doc - (Pathname.pwd + "#{@name}.podspec").open('w') { |f| f << spec } + if repo_id = @name_or_url[/github.com\/(.*\/.*)/, 1] + data = github_data_for_template(repo_id) + puts semantic_versioning_notice(repo_id, data[:name]) if data[:tag] == 'HEAD' + else + data = default_data_for_template(@name_or_url) + end + spec = spec_template(data) + (Pathname.pwd + "#{data[:name]}.podspec").open('w') { |f| f << spec } + puts "\nSpecification created at #{data[:name]}.podspec\n".green end def lint - file = @name ? Pathname.new(@name) : Pathname.pwd.glob('*.podspec').first + name = @name_or_url + file = name ? Pathname.new(name) : Pathname.pwd.glob('*.podspec').first spec = Specification.from_file(file) puts "\nThe #{spec.name} specification contains all the required attributes.".green if spec.validate! warnings = [] - warnings << 'The name of the specificaiton should match the name of the podspec file' if spec.name + '.podspec' != @name - warnings << 'Missing license[:type]' unless spec.license && spec.license[:type] - warnings << 'Missing license[:file] or [:text]' unless spec.license && (spec.license[:file] || spec.license[:text]) - warnings << "Github repositories should end in `.git'" if spec.source[:git] =~ /github.com/ && spec.source[:git] !~ /.*\.git/ - warnings << "Github repositories should end in `.git'" if spec.source[:git] =~ /github.com/ && spec.source[:git] !~ /.*\.git/ - warnings << "The description should end with a dot" if spec.description && spec.description !~ /.*\./ - warnings << "The summary should end with a dot" if spec.summary !~ /.*\./ + warnings << 'The name of the specificaiton should match the name of the podspec file' if spec.name + '.podspec' != name + warnings << 'Missing license[:type]' unless spec.license && spec.license[:type] + warnings << 'Missing license[:file] or [:text]' unless spec.license && (spec.license[:file] || spec.license[:text]) + warnings << "Github repositories should end in `.git'" if spec.source[:git] =~ /github.com/ && spec.source[:git] !~ /.*\.git/ + warnings << "Github repositories should end in `.git'" if spec.source[:git] =~ /github.com/ && spec.source[:git] !~ /.*\.git/ + warnings << "The description should end with a dot" if spec.description && spec.description !~ /.*\./ + warnings << "The summary should end with a dot" if spec.summary !~ /.*\./ unless warnings.empty? puts "\n[!] The #{spec.name} specification raised the following warnings".yellow warnings.each { |warn| puts ' - '+ warn } @@ -59,294 +68,189 @@ def lint puts end - private - - def is_git_hub - @name =~ /https:\/\/github.com\/.*\/.*/ - end - - def find_github_info - full, user, repo = *(@name.match /https:\/\/github.com\/(.*)\/(.*)/).to_a - user_data = fetch_request("users/#{user}") - repo_data = fetch_request("repos/#{user}/#{repo}") - tags_data = fetch_request("repos/#{user}/#{repo}/tags") - [user_data, repo_data, tags_data] + def suggest_tag_and_version(tags) + versions_tags = {} + tags.each do |tag| + clean_tag = tag.gsub(/^v(er)? ?/,'') + versions_tags[Gem::Version.new(clean_tag)] = tag if Gem::Version.correct?(clean_tag) + end + version = versions_tags.keys.sort.last || 'HEAD' + tag = version == 'HEAD' ? '0.0.1' : versions_tags[version] + [tag, version.to_s] end - def fetch_request(request_url) - uri = URI.parse("https://api.github.com/#{request_url}") - http = Net::HTTP.new(uri.host, uri.port) - http.use_ssl = true - http.verify_mode = OpenSSL::SSL::VERIFY_NONE - request = Net::HTTP::Get.new(uri.request_uri) - response = http.request(request) - JSON.parse(response.body) if response.is_a?(Net::HTTPSuccess) + def github_data_for_template(repo_id) + repo = Octokit.repo(repo_id) + user = Octokit.user(repo['owner']['login']) + tags = Octokit.tags(repo_id).map {|tag| tag.name} + + tag, version = suggest_tag_and_version(tags) + + data = {} + data[:name] = repo['name'] + data[:version] = version + data[:summary] = repo['description'].gsub(/["]/, '\"') + data[:homepage] = repo['homepage'] != "" ? repo['homepage'] : repo['html_url'] + data[:author_name] = user['name'] || user['login'] + data[:author_email] = user['email'] || 'email@address.com' + data[:source_url] = repo['clone_url'] + data[:tag] = tag + data end - def find_suggested_tag(tags_data) - tags = tags_data.map {|hash| hash["name"] } - versions = tags.reject {|t| t !~ /[0-9]+\.[0-9]+\.?[0-9]*/ } - versions.sort.last || '0.0.1' + def default_data_for_template(name) + data = {} + data[:name] = name + data[:version] = '0.0.1' + data[:summary] = 'A short description of #{name}.' + data[:homepage] = "http://EXAMPLE/#{name}" + data[:author_name] = `git config --get user.name`.strip + data[:author_email] = `git config --get user.email`.strip + data[:source_url] = "http://EXAMPLE/#{name}.git" + data[:tag] = '0.0.1' + data end - def version_from_tag(tag) - tag.match /[0-9]+\.[0-9]+\.?[0-9]*/ - end + def spec_template(data) + return <<-SPEC +# +# Be sure to run `pod spec lint #{data[:name]}.podspec' to ensure this is a +# valid spec. +# +# Remove all comments before submitting the spec. +# +Pod::Spec.new do |s| + + # ――― REQUIRED VALUES ――――――――――――――――――――――――――――――――――――――――――――――――――――――― # + + s.name = "#{data[:name]}" + s.version = "#{data[:version]}" + s.summary = "#{data[:summary]}" + s.homepage = "#{data[:homepage]}" + + # Specify the authors of the library, with email addresses. You can often find + # the email addresses of the authors by using the SCM log. E.g. $ git log + # + s.author = { "#{data[:author_name]}" => "#{data[:author_email]}" } + # s.authors = { "#{data[:author_name]}" => "#{data[:author_email]}", "other author" => "and email address" } + # + # If absolutely no email addresses are available, then you can use this form instead. + # + # s.author = '#{data[:author_name]}', 'other author' + + # Specify the location from where the source should be retreived. + # + s.source = { :git => "#{data[:source_url]}", :tag => "#{data[:tag]}" } + # s.source = { :svn => 'http://EXAMPLE/#{data[:name]}/tags/1.0.0' } + # s.source = { :hg => 'http://EXAMPLE/#{data[:name]}', :revision => '1.0.0' } + + # Specify the license details. Only if no dedicated file is available include + # the full text of the license. + # + s.license = { + :type => 'MIT', + :file => 'LICENSE', + # :text => 'Permission is hereby granted ...' + } + + # A list of file patterns which select the source files that should be + # added to the Pods project. If the pattern is a directory then the + # path will automatically have '*.{h,m,mm,c,cpp}' appended. + # + # Alternatively, you can use the FileList class for even more control + # over the selected files. + # (See http://rake.rubyforge.org/classes/Rake/FileList.html.) + # + s.source_files = 'Classes', 'Classes/**/*.{h,m}' + + # ――― OPTIONAL VALUES ――――――――――――――――――――――――――――――――――――――――――――――――――――――― # + + s.description = 'An optional longer description of #{data[:name]}.' + + # If this Pod runs only on iOS or OS X, then specify that with one of + # these, or none if it runs on both platforms. + # + # s.platform = :ios + # s.platform = :osx + + # A list of resources included with the Pod. These are copied into the + # target bundle with a build phase script. + # + # Also allows the use of the FileList class like `source_files does. + # + # s.resource = "icon.png" + # s.resources = "Resources/*.png" + + # A list of paths to remove after installing the Pod without the + # `--no-clean' option. These can be examples, docs, and any other type + # of files that are not needed to build the Pod. + # + # *NOTE*: Never remove license and README files. + # + # Also allows the use of the FileList class like `source_files does. + # + # s.clean_path = "examples" + # s.clean_paths = "examples", "doc" + + # Specify a list of frameworks that the application needs to link + # against for this Pod to work. + # + # s.framework = 'SomeFramework' + # s.frameworks = 'SomeFramework', 'AnotherFramework' + + # Specify a list of libraries that the application needs to link + # against for this Pod to work. + # + # s.library = 'iconv' + # s.libraries = 'iconv', 'xml2' + + # If this Pod uses ARC, specify it like so. + # + # s.requires_arc = true + + # Finally, specify any Pods that this Pod depends on. + # + # s.dependency 'JSONKit', '~> 1.4' + + # ――― EXTRA VALUES ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # + + # If you need to specify any other build settings, add them to the + # xcconfig hash. + # + # s.xcconfig = { 'HEADER_SEARCH_PATHS' => '$(SDKROOT)/usr/include/libxml2' } - def github_spec_doc - user_data, repo_data, tags_data = find_github_info - tag = find_suggested_tag(tags_data) - version = version_from_tag(tag) - - @name = repo_data["name"] - spec = <<-SPEC.gsub(/^ /, '') - # - # Be sure to run `pod spec lint #{@name}.podspec' to ensure this is a - # valid spec. - # - # Remove all comments before submitting the spec. - # - Pod::Spec.new do |s| - - # ――― REQUIRED ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― - - s.name = '#{@name}' - s.version = '#{version}' - s.summary = '#{repo_data["description"].gsub(/[']/, '\\\\\'')}' - s.homepage = '#{repo_data["homepage"] != "" ? repo_data["homepage"] : repo_data["html_url"]}' - s.source = { :git => '#{repo_data["clone_url"]}', :tag => '#{tag}' } - s.author = { '#{user_data["name"]}' => '#{user_data["email"]}' } - # s.author = { '#{user_data["name"]}' => '#{user_data["email"]}', 'other author' => 'and email address' } - - # Specify the license of the pod. - # :type The type of the license. - # :file The file containing the license of the pod. - # :range If a dedicated license file is not available specify a file - # that contains the license and the range of the lines - # containing the license. - # :text If the license is not available in any of the files it should be - # included here. - s.license = { - :type => 'MIT', - :file => 'LICENSE', - # :range => 1..15, - # :text => 'Permission is hereby granted ...' - } - - # A list of file patterns which select the source files that should be - # added to the Pods project. If the pattern is a directory then the - # path will automatically have '*.{h,m,mm,c,cpp}' appended. - # - # Alternatively, you can use the FileList class for even more control - # over the selected files. - # (See http://rake.rubyforge.org/classes/Rake/FileList.html.) - # - s.source_files = 'Classes', 'Classes/**/*.{h,m}' - - # ――― OPTIONAL ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― - - s.description = 'An optional longer description of #{@name}.' - - # If this Pod runs only on iOS or OS X, then specify that with one of - # these, or none if it runs on both platforms. - # - # s.platform = :ios - # s.platform = :osx - - # A list of resources included with the Pod. These are copied into the - # target bundle with a build phase script. - # - # Also allows the use of the FileList class like `source_files does. - # - # s.resource = "icon.png" - # s.resources = "Resources/*.png" - - # A list of paths to remove after installing the Pod without the - # `--no-clean' option. These can be examples, docs, and any other type - # of files that are not needed to build the Pod. - # - # *NOTE*: Never remove license and README files. - # - # Also allows the use of the FileList class like `source_files does. - # - # s.clean_path = "examples" - # s.clean_paths = "examples", "doc" - - # Specify a list of frameworks that the application needs to link - # against for this Pod to work. - # - # s.framework = 'SomeFramework' - # s.frameworks = 'SomeFramework', 'AnotherFramework' - - # Specify a list of libraries that the application needs to link - # against for this Pod to work. - # - # s.library = 'iconv' - # s.libraries = 'iconv', 'xml2' - - # If this Pod uses ARC, specify it like so. - # - # s.requires_arc = true - - # Finally, specify any Pods that this Pod depends on. - # - # s.dependency 'JSONKit', '~> 1.4' - # - # ――― EXTRA ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― - - # If you need to specify any other build settings, add them to the - # xcconfig hash. - # - # s.xcconfig = { 'HEADER_SEARCH_PATHS' => '$(SDKROOT)/usr/include/libxml2' } - - # If available specify the documentation homepage. - # :html The online link for the documentation. - # :appledoc Ammend the default appledoc options used - # by cocoapods if needed. - # - # s.documentation = { - # :html => 'http://EXAMPLE/#{@name}/documentation', - # :appledoc => [ - # '--project-name', '#{@name}', - # '--project-company', 'Company Name', - # '--docset-copyright', copyright, - # '--ignore', 'Common', - # '--index-desc', 'readme.markdown', - # '--no-keep-undocumented-objects', - # '--no-keep-undocumented-members', - # ] - # } - - end +end SPEC end - def spec_doc - name = @name - author = `git config --get user.name`.strip - email = `git config --get user.email`.strip - spec = <<-SPEC.gsub(/^ /, '') - # - # Be sure to run `pod spec lint #{name}.podspec' to ensure this is a - # valid spec. - # - # Remove all comments before submitting the spec. - # - Pod::Spec.new do |s| - s.name = '#{name}' - s.version = '1.0.0' - s.summary = 'A short description of #{name}.' - s.homepage = 'http://EXAMPLE/#{name}' - - # Specify the authors of the library, with email addresses. You can often find - # the email addresses of the authors by using the SCM log. E.g. $ git log - # - s.author = { '#{author}' => '#{email}', 'other author' => 'and email address' } - # If absolutely no email addresses are available, then you can use this form instead. - # - # s.author = '#{author}', 'other author' - - # Specify the location from where the source should be retreived. - # - s.source = { :git => 'http://EXAMPLE/#{name}.git', :tag => '1.0.0' } - # s.source = { :svn => 'http://EXAMPLE/#{name}/tags/1.0.0' } - # s.source = { :hg => 'http://EXAMPLE/#{name}', :revision => '1.0.0' } - - s.description = 'An optional longer description of #{name}.' - - # If available specify the documentation homepage. - # :html The online link for the documentation. - # :appledoc Ammend the default appledoc options used - # by cocoapods if needed. - # - s.documentation = { - # :html => 'http://EXAMPLE/#{name}/documentation', - # :appledoc => [ - # '--project-name', '#{name}', - # '--project-company', 'Company Name', - # '--docset-copyright', copyright, - # '--ignore', 'Common', - # '--index-desc', 'readme.markdown', - # '--no-keep-undocumented-objects', - # '--no-keep-undocumented-members', - # ] - } - - # Specify the license of the pod. - # :type The type of the license. - # :file The file containing the license of the pod. - # :range If a dedicated license file is not available specify a file - # that contains the license and the range of the lines - # containing the license. - # :text If the license is not available in any of the files it should be - # included here. - s.license = { - :type => 'MIT', - :file => 'LICENSE', - # :range => 1..15, - # :text => 'Permission is hereby granted ...' - } - - # If this Pod runs only on iOS or OS X, then specify that with one of - # these, or none if it runs on both platforms. - # - # s.platform = :ios - # s.platform = :osx - - # A list of file patterns which select the source files that should be - # added to the Pods project. If the pattern is a directory then the - # path will automatically have '*.{h,m,mm,c,cpp}' appended. - # - # Alternatively, you can use the FileList class for even more control - # over the selected files. - # (See http://rake.rubyforge.org/classes/Rake/FileList.html.) - # - s.source_files = 'Classes', 'Classes/**/*.{h,m}' - - # A list of resources included with the Pod. These are copied into the - # target bundle with a build phase script. - # - # Also allows the use of the FileList class like `source_files does. - # - # s.resource = "icon.png" - # s.resources = "Resources/*.png" - - # A list of paths to remove after installing the Pod without the - # `--no-clean' option. These can be examples, docs, and any other type - # of files that are not needed to build the Pod. - # - # *NOTE*: Never remove license and README files. - # - # Also allows the use of the FileList class like `source_files does. - # - # s.clean_path = "examples" - # s.clean_paths = "examples", "doc" - - # Specify a list of frameworks that the application needs to link - # against for this Pod to work. - # - # s.framework = 'SomeFramework' - # s.frameworks = 'SomeFramework', 'AnotherFramework' - - # Specify a list of libraries that the application needs to link - # against for this Pod to work. - # - # s.library = 'iconv' - # s.libraries = 'iconv', 'xml2' - - # If this Pod uses ARC, specify it like so. - # - # s.requires_arc = true - - # If you need to specify any other build settings, add them to the - # xcconfig hash. - # - # s.xcconfig = { 'HEADER_SEARCH_PATHS' => '$(SDKROOT)/usr/include/libxml2' } - - # Finally, specify any Pods that this Pod depends on. - # - # s.dependency 'JSONKit', '~> 1.4' - SPEC + def semantic_versioning_notice(repo_id, repo) + return <<-EOS + +#{'――― MARKDOWN TEMPLATE ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――'.reversed} + +I’ve recently added [#{repo}](https://github.com/CocoaPods/Specs/tree/master/#{repo}) to the [CocoaPods](https://github.com/CocoaPods/CocoaPods) package manager repo. + +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. + +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. + +[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). + +In case you didn’t know this yet; you can tag the current HEAD as, for instance, version 1.0.0, like so: + +``` +$ git tag -a 1.0.0 -m "Tag release 1.0.0" +$ git push --tags +``` + +#{'――― TEMPLATE END ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――'.reversed} + +#{'[!] This repo does not appear to have semantic version tags.'.yellow} + +After commiting the specification, consider opening a ticket with the template displayed above: + - link: https://github.com/#{repo_id}/issues/new + - title: Please add semantic version tags +EOS end end end From 1997d9bced43c22e3bf4d87fd01582ccc3bf2aa3 Mon Sep 17 00:00:00 2001 From: Fabio Pelosin Date: Sat, 14 Apr 2012 18:32:43 +0200 Subject: [PATCH 3/4] Fixed spec and other minor fixes for pod spec create --- lib/cocoapods/command/spec.rb | 9 ++++----- spec/functional/command_spec.rb | 6 +++--- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/lib/cocoapods/command/spec.rb b/lib/cocoapods/command/spec.rb index 8c51e0b16d..0a79b79360 100644 --- a/lib/cocoapods/command/spec.rb +++ b/lib/cocoapods/command/spec.rb @@ -1,7 +1,6 @@ require 'net/https' require 'uri' require 'octokit' -require 'awesome_print' require 'json' module Pod @@ -36,7 +35,7 @@ def run end def create - if repo_id = @name_or_url[/github.com\/(.*\/.*)/, 1] + if repo_id = @name_or_url[/github.com\/([^\/]*\/[^\/]*).*/, 1] data = github_data_for_template(repo_id) puts semantic_versioning_notice(repo_id, data[:name]) if data[:tag] == 'HEAD' else @@ -74,8 +73,8 @@ def suggest_tag_and_version(tags) clean_tag = tag.gsub(/^v(er)? ?/,'') versions_tags[Gem::Version.new(clean_tag)] = tag if Gem::Version.correct?(clean_tag) end - version = versions_tags.keys.sort.last || 'HEAD' - tag = version == 'HEAD' ? '0.0.1' : versions_tags[version] + version = versions_tags.keys.sort.last || '0.0.1' + tag = version == '0.0.1' ? 'HEAD' : versions_tags[version] [tag, version.to_s] end @@ -102,7 +101,7 @@ def default_data_for_template(name) data = {} data[:name] = name data[:version] = '0.0.1' - data[:summary] = 'A short description of #{name}.' + data[:summary] = "A short description of #{name}." data[:homepage] = "http://EXAMPLE/#{name}" data[:author_name] = `git config --get user.name`.strip data[:author_email] = `git config --get user.email`.strip diff --git a/spec/functional/command_spec.rb b/spec/functional/command_spec.rb index 6a60927b68..21bc0923c9 100644 --- a/spec/functional/command_spec.rb +++ b/spec/functional/command_spec.rb @@ -54,11 +54,11 @@ def command.url; SpecHelper.fixture('spec-repos/master'); end spec = Pod::Specification.from_file(path) spec.name.should == 'Bananas' spec.license.should == { :type => "MIT", :file => "LICENSE" } - spec.version.should == Pod::Version.new('1.0.0') + spec.version.should == Pod::Version.new('0.0.1') spec.summary.should == 'A short description of Bananas.' spec.homepage.should == 'http://EXAMPLE/Bananas' - spec.authors.should == { `git config --get user.name`.strip => `git config --get user.email`.strip, "other author" => "and email address" } - spec.source.should == { :git => 'http://EXAMPLE/Bananas.git', :tag => '1.0.0' } + spec.authors.should == { `git config --get user.name`.strip => `git config --get user.email`.strip} + spec.source.should == { :git => 'http://EXAMPLE/Bananas.git', :tag => '0.0.1' } spec.description.should == 'An optional longer description of Bananas.' spec.source_files.should == ['Classes', 'Classes/**/*.{h,m}'] end From 6c304ff73f3a11bb986ae1bd9d66519eaa99a4cb Mon Sep 17 00:00:00 2001 From: Fabio Pelosin Date: Sat, 14 Apr 2012 18:53:18 +0200 Subject: [PATCH 4/4] Added magic comment for utf-8 encoding to spec.rb --- lib/cocoapods/command/spec.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/cocoapods/command/spec.rb b/lib/cocoapods/command/spec.rb index 0a79b79360..03cd3e24dd 100644 --- a/lib/cocoapods/command/spec.rb +++ b/lib/cocoapods/command/spec.rb @@ -1,3 +1,5 @@ +# encoding: utf-8 + require 'net/https' require 'uri' require 'octokit'