diff options
author | Dickson S. Guedes | 2011-06-24 22:46:00 +0000 |
---|---|---|
committer | Dickson S. Guedes | 2011-06-24 22:46:00 +0000 |
commit | 4e6c951942929d4d845ebe0e13ad5e94d8d451aa (patch) | |
tree | 8710f6f8a55d89a42d30b9f6386aea7f10e8014c | |
parent | cf1b176494d7f8c5390726644ba7849a88bf73cf (diff) | |
parent | cdffc8308d90b86136c8bcf7921087565c9655c6 (diff) |
Merge pull request #13 from guedes/issue_9v0.1.2
Prepare to 0.1.2.
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | README.md | 18 | ||||
-rw-r--r-- | Rakefile | 11 | ||||
-rw-r--r-- | lib/pgxn_utils.rb | 3 | ||||
-rw-r--r-- | lib/pgxn_utils/cli.rb | 132 | ||||
-rw-r--r-- | lib/pgxn_utils/constants.rb | 5 | ||||
-rw-r--r-- | lib/pgxn_utils/version.rb | 2 | ||||
-rw-r--r-- | pgxn_utils.gemspec | 37 |
8 files changed, 170 insertions, 39 deletions
@@ -3,3 +3,4 @@ Gemfile.lock pkg/* *.sw? +tags @@ -105,18 +105,30 @@ For all switches that you can use with *change*, type: -r, [--release-status=RELEASE_STATUS] # Initial extension's release status -# Bundle it! +# Bundling and Releasing! Well, since you finished your work you can bundle it to send to [PGXN](http://pgxn.org). -Just type: +Bundle it: $ pgxn_utils bundle my_cool_extension Extension generated at: /home/guedes/extensions/my_cool_extension-0.0.1.zip +and release it: + + $ pgxn_utils release my_cool_extension-0.0.1.zip + Enter your PGXN username: guedes + Enter your PGXN password: ****** + Trying to release my_cool_extension-0.0.1.zip ... released successfully! + Visit: http://manager.pgxn.org/distributions/my_cool_extension/0.0.1 + +You can export `PGXN_USER` and `PGXN_PASSWORD` environment variables to avoid +type username and password everytime. + # Working in progress -I'm working in an option to release the bundled extension, sending it to [PGXN](http://pgxn.org). +* support to [git](http://git-scm.org) +* support to proxy Copyright and License --------------------- @@ -1,15 +1,18 @@ require 'bundler' +#include Rake::DSL Bundler::GemHelper.install_tasks - require 'rspec/core/rake_task' desc "Run RSpec" RSpec::Core::RakeTask.new do |t| t.verbose = false - #t.rspec_opts = %w(-fs --color) t.rspec_opts = %w(--color) - #dont show warnings here yet - #t.ruby_opts = %w(-w) +end + +desc "CTag Files" +task :ctag do + #system("ctags -R --exclude=.git --exclude=log * ~/.rvm/gems/") + system("ctags -R --exclude=.git --exclude=log *") end task :default => :spec diff --git a/lib/pgxn_utils.rb b/lib/pgxn_utils.rb index c3750bb..04c0c23 100644 --- a/lib/pgxn_utils.rb +++ b/lib/pgxn_utils.rb @@ -2,7 +2,10 @@ require 'thor' require 'json' require 'zip/zip' require 'zippy' +require 'net/http/post/multipart' +require 'highline/import' module PgxnUtils autoload :CLI, 'pgxn_utils/cli' + autoload :Constants, 'pgxn_utils/constants' end diff --git a/lib/pgxn_utils/cli.rb b/lib/pgxn_utils/cli.rb index a5b6c42..58061d4 100644 --- a/lib/pgxn_utils/cli.rb +++ b/lib/pgxn_utils/cli.rb @@ -3,8 +3,10 @@ module PgxnUtils attr_accessor :extension_name, :target, :maintainer #, :maintainer_mail attr_accessor :abstract, :description, :version, :tags attr_accessor :license, :release_status, :generated_by + attr_accessor :pgxn_username, :pgxn_password include Thor::Actions + include PgxnUtils::Constants desc "skeleton extension_name", "Creates an extension skeleton in current directory." @@ -12,7 +14,6 @@ module PgxnUtils # META required fields method_option :maintainer, :aliases => "-m", :type => :string, :desc => "Maintainer's name <maintainer@email>" - #method_option :maintainer_mail, :aliases => "-e", :type => :string, :desc => "Maintainer's mail" method_option :abstract, :aliases => "-a", :type => :string, :desc => "Defines a short description to abstract" method_option :license, :aliases => "-l", :type => :string, :desc => "The extension license." method_option :version, :aliases => "-v", :type => :string, :desc => "Initial version" @@ -25,16 +26,26 @@ module PgxnUtils def skeleton(extension_name,target=nil) self.target = options[:target] || target || "." - self.set_accessors extension_name - directory "root", extension_name + if is_extension?("#{self.target}/#{extension_name}") + say "'#{extension_name}' already exists. Please, use 'change' instead 'skeleton'.", :red + elsif is_extension?(".") + say "You are inside a extension directory, already. Consider use 'change' instead.", :red + elsif is_dir?("#{self.target}/#{extension_name}") + say "Can't create an extension overwriting an existing directory.", :red + else + self.set_accessors extension_name + + directory "root", extension_name + end end desc "change [extension_name]", "Change META's attributes in current extension." + method_option :target, :aliases => "-p", :type => :string, :default => ".", :desc => "Define the target directory" + # META required fields method_option :maintainer, :aliases => "-m", :type => :string, :desc => "Maintainer's name <maintainer@email>" - #method_option :maintainer_mail, :aliases => "-e", :type => :string, :desc => "Maintainer's mail" method_option :abstract, :aliases => "-a", :type => :string, :desc => "Defines a short description to abstract" method_option :license, :aliases => "-l", :type => :string, :desc => "The extension license." method_option :version, :aliases => "-v", :type => :string, :desc => "Initial version" @@ -46,19 +57,26 @@ module PgxnUtils method_option :release_status, :aliases => "-r", :type => :string, :desc => "Initial extension's release status" def change(extension_name=".") - path = File.expand_path(extension_name) + extension_path, extension_name = resolve_extension_path_and_name(extension_name) + + self.target = extension_path + self.extension_name = extension_name - target = File.expand_path('..', path) - extension_name = File.basename(path) + set_accessors(extension_name) - skeleton(extension_name, target) + if is_extension?(extension_path) + template "root/META.json.tt", "#{extension_path}/META.json" + template "root/%extension_name%.control.tt", "#{extension_path}/%extension_name%.control" + else + say "'#{extension_name}' doesn't appears to be an extension. Please, supply the extension's name", :red + end end desc "bundle [extension_name]", "Bundles an extension." def bundle(extension_name=".") unless is_extension?(extension_name) - say "'#{extension_name}' isn't a valid extension" + say "'#{extension_name}' doesn't appears to be an extension. Please, supply the extension's name", :red else path = File.expand_path(extension_name) extension_name = File.basename(path) @@ -69,22 +87,104 @@ module PgxnUtils archive = "#{archive_name}.#{ext}" if can_zip?(archive) + make_dist_clean(path) + Zippy.create(archive) do |zip| Dir["#{path}/**/**"].each do |file| zip["#{extension_name}-#{config_options['version']}/#{file.sub(path+'/','')}"] = File.open(file) unless File.directory?(file) end end - say "Extension generated at: #{archive}" + say_status :create, archive, :green end end end + desc "release filename", "Release a extension" + + def release(filename) + send_file_to_pgxn(filename) + end + no_tasks do + def make_dist_clean(path) + inside path do + run 'make distclean', :capture => true + end + end + + def ask_for_pgxn_credential + self.pgxn_username = ENV["PGXN_USER"] || HighLine.ask("Enter your PGXN username: ") { |q| q.validate = /^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$/ } + self.pgxn_password = ENV["PGXN_PASS"] || HighLine.ask("Enter your PGXN password: ") { |q| q.echo = '*' } + end + + def check_response(response) + case response + when Net::HTTPUnauthorized then + say "oops!", :red + say "It seems that you entered a wrong username or password.", :red + when Net::HTTPConflict then + say "conflict!", :yellow + say "Distribution already exists! Please, check your META.json.", :yellow + when Net::HTTPSeeOther then + say "released successfully!", :green + say "Visit: #{URI.parse(response['Location'])}", :green + else + say "Unknown error. (#{response})" + end + end + + def prepare_multipart_post_for(filename) + file_basename = File.basename(filename) + zip_file = File.open(filename) + Net::HTTP::Post::Multipart.new( + UPLOAD_URL.path, + "archive" => UploadIO.new(zip_file, "application/zip", file_basename), + "Expect" => "" + ) + end + + def try_send_file(request, filename) + begin + Net::HTTP.start(UPLOAD_URL.host, UPLOAD_URL.port) do |http| + say "Trying to release #{File.basename(filename)} ... " + http.request(request) + end + rescue SocketError + say "Please, check your connection.", :red + exit(1) + end + end + + def send_file_to_pgxn(filename) + request = prepare_multipart_post_for(filename) + ask_for_pgxn_credential + + request.basic_auth pgxn_username, pgxn_password + response = try_send_file(request, filename) + check_response(response) + end + + def resolve_extension_path_and_name(extension_name) + target = options[:target] + extension_path = "." + + if target != "." && extension_name == "." + raise ArgumentError, "Please, supply a extension name" + elsif target == "." + extension_path = File.expand_path(extension_name) + extension_name = File.basename(extension_path) + else + extension_path = "#{target}/#{extension_name}" + end + [ extension_path, extension_name ] + end + def can_zip?(archive) can_zip = false if File.exists?(archive) - if yes? "#{archive} found! Overwrite? [yN]" + say_status :conflict, archive, :red + if yes? "Overwrite #{archive}? [yN]" can_zip = true else can_zip = false @@ -98,11 +198,12 @@ module PgxnUtils File.directory?(dir) && File.exists?("#{dir}/META.json") end + def is_dir?(dir) + File.directory?(dir) + end + def config_options - file = "" - file = File.join(file, self.target) if self.target != "." - file = File.join(file, self.extension_name) if self.extension_name - file = File.join(file, "META.json") + file = File.join(target, "META.json") if File.exist?(file) @@config_options ||= JSON.load(File.read(file)) @@ -115,7 +216,6 @@ module PgxnUtils self.extension_name = extension_name self.maintainer = options[:maintainer] || config_options["maintainer"] || "The maintainer's name" - #self.maintainer_mail = options[:maintainer_mail] || config_options["maintainer_mail"] || "[email protected]" self.abstract = options[:abstract] || config_options["abstract"] || "A short description" self.license = options[:license] || config_options["license"] || "postgresql" self.version = options[:version] || config_options["version"] || "0.0.1" diff --git a/lib/pgxn_utils/constants.rb b/lib/pgxn_utils/constants.rb new file mode 100644 index 0000000..2abf759 --- /dev/null +++ b/lib/pgxn_utils/constants.rb @@ -0,0 +1,5 @@ +module PgxnUtils + module Constants + UPLOAD_URL = URI.parse('https://manager.pgxn.org/auth/upload') + end +end diff --git a/lib/pgxn_utils/version.rb b/lib/pgxn_utils/version.rb index c85b262..7233fc5 100644 --- a/lib/pgxn_utils/version.rb +++ b/lib/pgxn_utils/version.rb @@ -1,3 +1,3 @@ module PgxnUtils - VERSION = "0.1.1" + VERSION = "0.1.2" end diff --git a/pgxn_utils.gemspec b/pgxn_utils.gemspec index c6d0e25..ba7c79c 100644 --- a/pgxn_utils.gemspec +++ b/pgxn_utils.gemspec @@ -13,33 +13,40 @@ Gem::Specification.new do |s| s.summary = %q{A PGXN set of tools to PostgreSQL extension's developers} s.description = %q{A PGXN set of tools to help developers create and publish your PostgreSQL extensions without pain} - s.rubyforge_project = "pgxn_utils" + s.required_ruby_version = '>= 1.8.7' + s.required_rubygems_version = '>= 1.3.7' s.files = `git ls-files`.split("\n") s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } s.require_paths = ["lib"] - # dev - s.add_development_dependency "rspec" - s.add_development_dependency "simplecov", ">= 0.4.0" - - # prod if s.respond_to? :specification_version then s.specification_version = 3 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then - s.add_runtime_dependency(%q<thor>, ["~> 0.14"]) - s.add_runtime_dependency(%q<rubyzip>, ["~> 0.9.4"]) - s.add_runtime_dependency(%q<zippy>, ["~> 0.1.0"]) + s.add_runtime_dependency "json", "~> 1.5.2" + s.add_runtime_dependency "thor", "~> 0.14" + s.add_runtime_dependency "rubyzip", "~> 0.9.4" + s.add_runtime_dependency "zippy", "~> 0.1.0" + s.add_runtime_dependency "multipart-post", "~> 1.1.2" + s.add_runtime_dependency "highline", "~> 1.6.2" + s.add_development_dependency "rspec" + s.add_development_dependency "simplecov", "~> 0.4.0" else - s.add_dependency(%q<thor>, ["~> 0.14"]) - s.add_runtime_dependency(%q<rubyzip>, ["~> 0.9.4"]) - s.add_runtime_dependency(%q<zippy>, ["~> 0.1.0"]) + s.add_dependency "json", "~> 1.5.2" + s.add_dependency "thor", "~> 0.14" + s.add_dependency "rubyzip", "~> 0.9.4" + s.add_dependency "zippy", "~> 0.1.0" + s.add_dependency "multipart-post", "~> 1.1.2" + s.add_dependency "highline", "~> 1.6.2" end else - s.add_dependency(%q<thor>, ["~> 0.14"]) - s.add_runtime_dependency(%q<rubyzip>, ["~> 0.9.4"]) - s.add_runtime_dependency(%q<zippy>, ["~> 0.1.0"]) + s.add_dependency "json", "~> 1.5.2" + s.add_dependency "thor", "~> 0.14" + s.add_dependency "rubyzip", "~> 0.9.4" + s.add_dependency "zippy", "~> 0.1.0" + s.add_dependency "multipart-post", "~> 1.1.2" + s.add_dependency "highline", "~> 1.6.2" end end |