Permalink
Browse files

Merge pull request #13 from guedes/issue_9

Prepare to 0.1.2.
  • Loading branch information...
2 parents cf1b176 + cdffc83 commit 4e6c951942929d4d845ebe0e13ad5e94d8d451aa @guedes committed Jun 24, 2011
Showing with 170 additions and 39 deletions.
  1. +1 −0 .gitignore
  2. +15 −3 README.md
  3. +7 −4 Rakefile
  4. +3 −0 lib/pgxn_utils.rb
  5. +116 −16 lib/pgxn_utils/cli.rb
  6. +5 −0 lib/pgxn_utils/constants.rb
  7. +1 −1 lib/pgxn_utils/version.rb
  8. +22 −15 pgxn_utils.gemspec
View
@@ -3,3 +3,4 @@
Gemfile.lock
pkg/*
*.sw?
+tags
View
@@ -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
---------------------
View
@@ -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
View
@@ -2,7 +2,10 @@
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
View
@@ -3,16 +3,17 @@ class CLI < Thor
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."
method_option :target, :aliases => "-p", :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"
@@ -25,16 +26,26 @@ class CLI < Thor
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 @@ def skeleton(extension_name,target=nil)
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 @@ def bundle(extension_name=".")
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 @@ def is_extension?(dir=".")
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 @@ def set_accessors(extension_name="your_extension_name")
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"] || "maintainer@email.here"
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"
@@ -0,0 +1,5 @@
+module PgxnUtils
+ module Constants
+ UPLOAD_URL = URI.parse('https://manager.pgxn.org/auth/upload')
+ end
+end
@@ -1,3 +1,3 @@
module PgxnUtils
- VERSION = "0.1.1"
+ VERSION = "0.1.2"
end
View
@@ -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

0 comments on commit 4e6c951

Please sign in to comment.