From 003e3c27ff0cfb3f118524d56f76b0ef7483c886 Mon Sep 17 00:00:00 2001 From: "Dickson S. Guedes" Date: Thu, 8 Sep 2011 01:57:28 -0300 Subject: [PATCH] refactored code and changed README --- README.md | 8 ++- lib/pgxn_utils.rb | 1 + lib/pgxn_utils/cli.rb | 137 ++----------------------------------- lib/pgxn_utils/no_tasks.rb | 129 ++++++++++++++++++++++++++++++++++ spec/no_tasks_spec.rb | 59 ++++++++++++++++ spec/spec_helper.rb | 2 +- 6 files changed, 203 insertions(+), 133 deletions(-) create mode 100644 lib/pgxn_utils/no_tasks.rb create mode 100644 spec/no_tasks_spec.rb diff --git a/README.md b/README.md index 843029a..7523f28 100644 --- a/README.md +++ b/README.md @@ -4,11 +4,17 @@ pgxn utils What is it? -------- -It aims to be a set of task to help PostgreSQL extension's developers to focus more on the problem that they wants to solve than in the all structure and files and control files need to PGXS to build the extension. +It aims to be a set of task to help PostgreSQL extension's developers to focus more on the problem that they wants to solve than in all structure and files and control files need to PGXS to build the extension. How to install it? ------------------ +If you have pgxn client installed you can do: + + pgxn install pgxn_utils + +Or you can install it by rubygems: + gem install pgxn_utils How it works? diff --git a/lib/pgxn_utils.rb b/lib/pgxn_utils.rb index 44bc8b6..0fea754 100644 --- a/lib/pgxn_utils.rb +++ b/lib/pgxn_utils.rb @@ -10,4 +10,5 @@ module PgxnUtils autoload :CLI, 'pgxn_utils/cli' autoload :VERSION, 'pgxn_utils/version' autoload :Constants, 'pgxn_utils/constants' + autoload :NoTasks, 'pgxn_utils/no_tasks' end diff --git a/lib/pgxn_utils/cli.rb b/lib/pgxn_utils/cli.rb index 53f00dd..fc22c1d 100644 --- a/lib/pgxn_utils/cli.rb +++ b/lib/pgxn_utils/cli.rb @@ -6,16 +6,16 @@ module PgxnUtils attr_accessor :pgxn_username, :pgxn_password include Thor::Actions - include PgxnUtils::Constants + include PgxnUtils::NoTasks - desc "skeleton extension_name", "Creates an extension skeleton in current directory." + 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 " 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 :license, :aliases => "-l", :type => :string, :desc => "The extension license" method_option :version, :aliases => "-v", :type => :string, :desc => "Initial version" # META optional fields @@ -40,7 +40,7 @@ module PgxnUtils end end - desc "change [extension_name]", "Change META's attributes in current extension." + desc "change [extension_name]", "Changes META's attributes in current extension" method_option :target, :aliases => "-p", :type => :string, :default => ".", :desc => "Define the target directory" @@ -72,7 +72,7 @@ module PgxnUtils end end - desc "bundle [extension_name]", "Bundles an extension." + desc "bundle [extension_name]", "Bundles the extension in a zip file" def bundle(extension_name=".") unless is_extension?(extension_name) @@ -99,137 +99,12 @@ module PgxnUtils end end - desc "release filename", "Release a extension" + desc "release filename", "Release an extension to PGXN" 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 - http = Net::HTTP.new(UPLOAD_URL.host, UPLOAD_URL.port) - http.use_ssl = true - http.verify_mode = OpenSSL::SSL::VERIFY_NONE - say "Trying to release #{File.basename(filename)} ... " - http.request(request) - 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) - say_status :conflict, archive, :red - if yes? "Overwrite #{archive}? [yN]" - can_zip = true - else - can_zip = false - end - else - can_zip = true - end - end - - 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.join(target, "META.json") - - if File.exist?(file) - @@config_options ||= JSON.load(File.read(file)) - else - {} - end - end - - 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.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" - - self.description = options[:description] || config_options["description"] || "A long description" - self.generated_by = options[:generated_by] || config_options["generated_by"] || maintainer - self.tags = options[:tags] || config_options["tags"] - self.release_status = options[:release_status] || config_options["release_status"] || "unstable" - - self.destination_root = target - end - end - def self.source_root @_source_root ||= File.expand_path('../templates', __FILE__) end diff --git a/lib/pgxn_utils/no_tasks.rb b/lib/pgxn_utils/no_tasks.rb new file mode 100644 index 0000000..a066998 --- /dev/null +++ b/lib/pgxn_utils/no_tasks.rb @@ -0,0 +1,129 @@ +module PgxnUtils + module NoTasks + + include PgxnUtils::Constants + + 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 + http = Net::HTTP.new(UPLOAD_URL.host, UPLOAD_URL.port) + http.use_ssl = true + http.verify_mode = OpenSSL::SSL::VERIFY_NONE + say "Trying to release #{File.basename(filename)} ... " + http.request(request) + 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) + say_status :conflict, archive, :red + if yes? "Overwrite #{archive}? [yN]" + can_zip = true + else + can_zip = false + end + else + can_zip = true + end + end + + def is_extension?(dir=".") + is_dir?(dir) && File.exists?("#{dir}/META.json") + end + + def is_dir?(dir) + File.directory?(dir) + end + + def config_options + file = File.join(target, "META.json") + + if File.exist?(file) + @@config_options ||= JSON.load(File.read(file)) + else + {} + end + end + + 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.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" + + self.description = options[:description] || config_options["description"] || "A long description" + self.generated_by = options[:generated_by] || config_options["generated_by"] || maintainer + self.tags = options[:tags] || config_options["tags"] + self.release_status = options[:release_status] || config_options["release_status"] || "unstable" + + self.destination_root = target + end + end +end diff --git a/spec/no_tasks_spec.rb b/spec/no_tasks_spec.rb new file mode 100644 index 0000000..0117b72 --- /dev/null +++ b/spec/no_tasks_spec.rb @@ -0,0 +1,59 @@ +require File.expand_path('spec/spec_helper') + +describe PgxnUtils::NoTasks do + include PgxnUtils::NoTasks + include FileUtils + + after(:all) do + rm_r("/tmp/teste") + rm_r("/tmp/teste2") + end + + context "#resolve_extension_path_and_name" do + it "should raise error when no extension name was supplied" do + PgxnUtils::NoTasks.send(:define_method, :options) do + { :target => "/something" } + end + extension_name = "." + lambda {resolve_extension_path_and_name(extension_name)}.should raise_error(ArgumentError) + end + + it "should return correctly if target is '.'" do + PgxnUtils::NoTasks.send(:define_method, :options) do + { :target => "." } + end + + original_dir = File.expand_path(".") + destination_dir = "/tmp/teste" + mkdir destination_dir + cd destination_dir + + extension_name = "teste" + resolved_path, resolved_name = resolve_extension_path_and_name(extension_name) + + cd original_dir + + resolved_path.should == "#{destination_dir}/#{extension_name}" + resolved_name.should == extension_name + end + + it "should return correctly when target are not '.' and a extension name was specified" do + PgxnUtils::NoTasks.send(:define_method, :options) do + { :target => "/tmp" } + end + + original_dir = File.expand_path(".") + destination_dir = "/tmp/teste2" + mkdir destination_dir + cd destination_dir + + extension_name = "teste2" + resolved_path, resolved_name = resolve_extension_path_and_name(extension_name) + + cd original_dir + + resolved_path.should == destination_dir + resolved_name.should == extension_name + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 894f648..3ad1c37 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -9,7 +9,7 @@ require 'pgxn_utils' $counter = 0 LIB_PATH = File.expand_path('../../lib', __FILE__) -BIN_PATH = File.expand_path('../../bin/pgxn_utils', __FILE__) +BIN_PATH = File.expand_path('../../bin/pgxn-utils', __FILE__) DESTINATION_ROOT = File.expand_path('../pgxn_utils', __FILE__) FileUtils.rm_rf(DESTINATION_ROOT) -- 2.30.2