pgxn_utils 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -3,3 +3,4 @@
3
3
  Gemfile.lock
4
4
  pkg/*
5
5
  *.sw?
6
+ tags
data/README.md CHANGED
@@ -105,18 +105,30 @@ For all switches that you can use with *change*, type:
105
105
  -r, [--release-status=RELEASE_STATUS] # Initial extension's release status
106
106
 
107
107
 
108
- # Bundle it!
108
+ # Bundling and Releasing!
109
109
 
110
110
  Well, since you finished your work you can bundle it to send to [PGXN](http://pgxn.org).
111
111
 
112
- Just type:
112
+ Bundle it:
113
113
 
114
114
  $ pgxn_utils bundle my_cool_extension
115
115
  Extension generated at: /home/guedes/extensions/my_cool_extension-0.0.1.zip
116
116
 
117
+ and release it:
118
+
119
+ $ pgxn_utils release my_cool_extension-0.0.1.zip
120
+ Enter your PGXN username: guedes
121
+ Enter your PGXN password: ******
122
+ Trying to release my_cool_extension-0.0.1.zip ... released successfully!
123
+ Visit: http://manager.pgxn.org/distributions/my_cool_extension/0.0.1
124
+
125
+ You can export `PGXN_USER` and `PGXN_PASSWORD` environment variables to avoid
126
+ type username and password everytime.
127
+
117
128
  # Working in progress
118
129
 
119
- I'm working in an option to release the bundled extension, sending it to [PGXN](http://pgxn.org).
130
+ * support to [git](http://git-scm.org)
131
+ * support to proxy
120
132
 
121
133
  Copyright and License
122
134
  ---------------------
data/Rakefile CHANGED
@@ -1,15 +1,18 @@
1
1
  require 'bundler'
2
+ #include Rake::DSL
2
3
  Bundler::GemHelper.install_tasks
3
-
4
4
  require 'rspec/core/rake_task'
5
5
 
6
6
  desc "Run RSpec"
7
7
  RSpec::Core::RakeTask.new do |t|
8
8
  t.verbose = false
9
- #t.rspec_opts = %w(-fs --color)
10
9
  t.rspec_opts = %w(--color)
11
- #dont show warnings here yet
12
- #t.ruby_opts = %w(-w)
10
+ end
11
+
12
+ desc "CTag Files"
13
+ task :ctag do
14
+ #system("ctags -R --exclude=.git --exclude=log * ~/.rvm/gems/")
15
+ system("ctags -R --exclude=.git --exclude=log *")
13
16
  end
14
17
 
15
18
  task :default => :spec
@@ -3,8 +3,10 @@ module PgxnUtils
3
3
  attr_accessor :extension_name, :target, :maintainer #, :maintainer_mail
4
4
  attr_accessor :abstract, :description, :version, :tags
5
5
  attr_accessor :license, :release_status, :generated_by
6
+ attr_accessor :pgxn_username, :pgxn_password
6
7
 
7
8
  include Thor::Actions
9
+ include PgxnUtils::Constants
8
10
 
9
11
  desc "skeleton extension_name", "Creates an extension skeleton in current directory."
10
12
 
@@ -12,7 +14,6 @@ module PgxnUtils
12
14
 
13
15
  # META required fields
14
16
  method_option :maintainer, :aliases => "-m", :type => :string, :desc => "Maintainer's name <maintainer@email>"
15
- #method_option :maintainer_mail, :aliases => "-e", :type => :string, :desc => "Maintainer's mail"
16
17
  method_option :abstract, :aliases => "-a", :type => :string, :desc => "Defines a short description to abstract"
17
18
  method_option :license, :aliases => "-l", :type => :string, :desc => "The extension license."
18
19
  method_option :version, :aliases => "-v", :type => :string, :desc => "Initial version"
@@ -25,16 +26,26 @@ module PgxnUtils
25
26
 
26
27
  def skeleton(extension_name,target=nil)
27
28
  self.target = options[:target] || target || "."
28
- self.set_accessors extension_name
29
29
 
30
- directory "root", extension_name
30
+ if is_extension?("#{self.target}/#{extension_name}")
31
+ say "'#{extension_name}' already exists. Please, use 'change' instead 'skeleton'.", :red
32
+ elsif is_extension?(".")
33
+ say "You are inside a extension directory, already. Consider use 'change' instead.", :red
34
+ elsif is_dir?("#{self.target}/#{extension_name}")
35
+ say "Can't create an extension overwriting an existing directory.", :red
36
+ else
37
+ self.set_accessors extension_name
38
+
39
+ directory "root", extension_name
40
+ end
31
41
  end
32
42
 
33
43
  desc "change [extension_name]", "Change META's attributes in current extension."
34
44
 
45
+ method_option :target, :aliases => "-p", :type => :string, :default => ".", :desc => "Define the target directory"
46
+
35
47
  # META required fields
36
48
  method_option :maintainer, :aliases => "-m", :type => :string, :desc => "Maintainer's name <maintainer@email>"
37
- #method_option :maintainer_mail, :aliases => "-e", :type => :string, :desc => "Maintainer's mail"
38
49
  method_option :abstract, :aliases => "-a", :type => :string, :desc => "Defines a short description to abstract"
39
50
  method_option :license, :aliases => "-l", :type => :string, :desc => "The extension license."
40
51
  method_option :version, :aliases => "-v", :type => :string, :desc => "Initial version"
@@ -46,19 +57,26 @@ module PgxnUtils
46
57
  method_option :release_status, :aliases => "-r", :type => :string, :desc => "Initial extension's release status"
47
58
 
48
59
  def change(extension_name=".")
49
- path = File.expand_path(extension_name)
60
+ extension_path, extension_name = resolve_extension_path_and_name(extension_name)
61
+
62
+ self.target = extension_path
63
+ self.extension_name = extension_name
50
64
 
51
- target = File.expand_path('..', path)
52
- extension_name = File.basename(path)
65
+ set_accessors(extension_name)
53
66
 
54
- skeleton(extension_name, target)
67
+ if is_extension?(extension_path)
68
+ template "root/META.json.tt", "#{extension_path}/META.json"
69
+ template "root/%extension_name%.control.tt", "#{extension_path}/%extension_name%.control"
70
+ else
71
+ say "'#{extension_name}' doesn't appears to be an extension. Please, supply the extension's name", :red
72
+ end
55
73
  end
56
74
 
57
75
  desc "bundle [extension_name]", "Bundles an extension."
58
76
 
59
77
  def bundle(extension_name=".")
60
78
  unless is_extension?(extension_name)
61
- say "'#{extension_name}' isn't a valid extension"
79
+ say "'#{extension_name}' doesn't appears to be an extension. Please, supply the extension's name", :red
62
80
  else
63
81
  path = File.expand_path(extension_name)
64
82
  extension_name = File.basename(path)
@@ -69,22 +87,104 @@ module PgxnUtils
69
87
  archive = "#{archive_name}.#{ext}"
70
88
 
71
89
  if can_zip?(archive)
90
+ make_dist_clean(path)
91
+
72
92
  Zippy.create(archive) do |zip|
73
93
  Dir["#{path}/**/**"].each do |file|
74
94
  zip["#{extension_name}-#{config_options['version']}/#{file.sub(path+'/','')}"] = File.open(file) unless File.directory?(file)
75
95
  end
76
96
  end
77
- say "Extension generated at: #{archive}"
97
+ say_status :create, archive, :green
78
98
  end
79
99
  end
80
100
  end
81
101
 
102
+ desc "release filename", "Release a extension"
103
+
104
+ def release(filename)
105
+ send_file_to_pgxn(filename)
106
+ end
107
+
82
108
  no_tasks do
109
+ def make_dist_clean(path)
110
+ inside path do
111
+ run 'make distclean', :capture => true
112
+ end
113
+ end
114
+
115
+ def ask_for_pgxn_credential
116
+ 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])?$/ }
117
+ self.pgxn_password = ENV["PGXN_PASS"] || HighLine.ask("Enter your PGXN password: ") { |q| q.echo = '*' }
118
+ end
119
+
120
+ def check_response(response)
121
+ case response
122
+ when Net::HTTPUnauthorized then
123
+ say "oops!", :red
124
+ say "It seems that you entered a wrong username or password.", :red
125
+ when Net::HTTPConflict then
126
+ say "conflict!", :yellow
127
+ say "Distribution already exists! Please, check your META.json.", :yellow
128
+ when Net::HTTPSeeOther then
129
+ say "released successfully!", :green
130
+ say "Visit: #{URI.parse(response['Location'])}", :green
131
+ else
132
+ say "Unknown error. (#{response})"
133
+ end
134
+ end
135
+
136
+ def prepare_multipart_post_for(filename)
137
+ file_basename = File.basename(filename)
138
+ zip_file = File.open(filename)
139
+ Net::HTTP::Post::Multipart.new(
140
+ UPLOAD_URL.path,
141
+ "archive" => UploadIO.new(zip_file, "application/zip", file_basename),
142
+ "Expect" => ""
143
+ )
144
+ end
145
+
146
+ def try_send_file(request, filename)
147
+ begin
148
+ Net::HTTP.start(UPLOAD_URL.host, UPLOAD_URL.port) do |http|
149
+ say "Trying to release #{File.basename(filename)} ... "
150
+ http.request(request)
151
+ end
152
+ rescue SocketError
153
+ say "Please, check your connection.", :red
154
+ exit(1)
155
+ end
156
+ end
157
+
158
+ def send_file_to_pgxn(filename)
159
+ request = prepare_multipart_post_for(filename)
160
+ ask_for_pgxn_credential
161
+
162
+ request.basic_auth pgxn_username, pgxn_password
163
+ response = try_send_file(request, filename)
164
+ check_response(response)
165
+ end
166
+
167
+ def resolve_extension_path_and_name(extension_name)
168
+ target = options[:target]
169
+ extension_path = "."
170
+
171
+ if target != "." && extension_name == "."
172
+ raise ArgumentError, "Please, supply a extension name"
173
+ elsif target == "."
174
+ extension_path = File.expand_path(extension_name)
175
+ extension_name = File.basename(extension_path)
176
+ else
177
+ extension_path = "#{target}/#{extension_name}"
178
+ end
179
+ [ extension_path, extension_name ]
180
+ end
181
+
83
182
  def can_zip?(archive)
84
183
  can_zip = false
85
184
 
86
185
  if File.exists?(archive)
87
- if yes? "#{archive} found! Overwrite? [yN]"
186
+ say_status :conflict, archive, :red
187
+ if yes? "Overwrite #{archive}? [yN]"
88
188
  can_zip = true
89
189
  else
90
190
  can_zip = false
@@ -98,11 +198,12 @@ module PgxnUtils
98
198
  File.directory?(dir) && File.exists?("#{dir}/META.json")
99
199
  end
100
200
 
201
+ def is_dir?(dir)
202
+ File.directory?(dir)
203
+ end
204
+
101
205
  def config_options
102
- file = ""
103
- file = File.join(file, self.target) if self.target != "."
104
- file = File.join(file, self.extension_name) if self.extension_name
105
- file = File.join(file, "META.json")
206
+ file = File.join(target, "META.json")
106
207
 
107
208
  if File.exist?(file)
108
209
  @@config_options ||= JSON.load(File.read(file))
@@ -115,7 +216,6 @@ module PgxnUtils
115
216
  self.extension_name = extension_name
116
217
 
117
218
  self.maintainer = options[:maintainer] || config_options["maintainer"] || "The maintainer's name"
118
- #self.maintainer_mail = options[:maintainer_mail] || config_options["maintainer_mail"] || "maintainer@email.here"
119
219
  self.abstract = options[:abstract] || config_options["abstract"] || "A short description"
120
220
  self.license = options[:license] || config_options["license"] || "postgresql"
121
221
  self.version = options[:version] || config_options["version"] || "0.0.1"
@@ -0,0 +1,5 @@
1
+ module PgxnUtils
2
+ module Constants
3
+ UPLOAD_URL = URI.parse('https://manager.pgxn.org/auth/upload')
4
+ end
5
+ end
@@ -2,7 +2,7 @@ EXTENSION = <%= extension_name %>
2
2
  EXTVERSION = $(shell grep default_version $(EXTENSION).control | sed -e "s/default_version[[:space:]]*=[[:space:]]*'\([^']*\)'/\1/")
3
3
 
4
4
  DATA = $(filter-out $(wildcard sql/*--*.sql),$(wildcard sql/*.sql))
5
- DOCS = $(wildcard doc/*.txt)
5
+ DOCS = $(wildcard doc/*.md)
6
6
  TESTS = $(wildcard test/sql/*.sql)
7
7
  REGRESS = $(patsubst test/sql/%.sql,%,$(TESTS))
8
8
  REGRESS_OPTS = --inputdir=test --load-language=plpgsql
@@ -1,3 +1,3 @@
1
1
  module PgxnUtils
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.2"
3
3
  end
data/lib/pgxn_utils.rb CHANGED
@@ -2,7 +2,10 @@ require 'thor'
2
2
  require 'json'
3
3
  require 'zip/zip'
4
4
  require 'zippy'
5
+ require 'net/http/post/multipart'
6
+ require 'highline/import'
5
7
 
6
8
  module PgxnUtils
7
9
  autoload :CLI, 'pgxn_utils/cli'
10
+ autoload :Constants, 'pgxn_utils/constants'
8
11
  end
data/pgxn_utils.gemspec CHANGED
@@ -13,33 +13,40 @@ Gem::Specification.new do |s|
13
13
  s.summary = %q{A PGXN set of tools to PostgreSQL extension's developers}
14
14
  s.description = %q{A PGXN set of tools to help developers create and publish your PostgreSQL extensions without pain}
15
15
 
16
- s.rubyforge_project = "pgxn_utils"
16
+ s.required_ruby_version = '>= 1.8.7'
17
+ s.required_rubygems_version = '>= 1.3.7'
17
18
 
18
19
  s.files = `git ls-files`.split("\n")
19
20
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
20
21
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
22
  s.require_paths = ["lib"]
22
23
 
23
- # dev
24
- s.add_development_dependency "rspec"
25
- s.add_development_dependency "simplecov", ">= 0.4.0"
26
-
27
- # prod
28
24
  if s.respond_to? :specification_version then
29
25
  s.specification_version = 3
30
26
 
31
27
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
32
- s.add_runtime_dependency(%q<thor>, ["~> 0.14"])
33
- s.add_runtime_dependency(%q<rubyzip>, ["~> 0.9.4"])
34
- s.add_runtime_dependency(%q<zippy>, ["~> 0.1.0"])
28
+ s.add_runtime_dependency "json", "~> 1.5.2"
29
+ s.add_runtime_dependency "thor", "~> 0.14"
30
+ s.add_runtime_dependency "rubyzip", "~> 0.9.4"
31
+ s.add_runtime_dependency "zippy", "~> 0.1.0"
32
+ s.add_runtime_dependency "multipart-post", "~> 1.1.2"
33
+ s.add_runtime_dependency "highline", "~> 1.6.2"
34
+ s.add_development_dependency "rspec"
35
+ s.add_development_dependency "simplecov", "~> 0.4.0"
35
36
  else
36
- s.add_dependency(%q<thor>, ["~> 0.14"])
37
- s.add_runtime_dependency(%q<rubyzip>, ["~> 0.9.4"])
38
- s.add_runtime_dependency(%q<zippy>, ["~> 0.1.0"])
37
+ s.add_dependency "json", "~> 1.5.2"
38
+ s.add_dependency "thor", "~> 0.14"
39
+ s.add_dependency "rubyzip", "~> 0.9.4"
40
+ s.add_dependency "zippy", "~> 0.1.0"
41
+ s.add_dependency "multipart-post", "~> 1.1.2"
42
+ s.add_dependency "highline", "~> 1.6.2"
39
43
  end
40
44
  else
41
- s.add_dependency(%q<thor>, ["~> 0.14"])
42
- s.add_runtime_dependency(%q<rubyzip>, ["~> 0.9.4"])
43
- s.add_runtime_dependency(%q<zippy>, ["~> 0.1.0"])
45
+ s.add_dependency "json", "~> 1.5.2"
46
+ s.add_dependency "thor", "~> 0.14"
47
+ s.add_dependency "rubyzip", "~> 0.9.4"
48
+ s.add_dependency "zippy", "~> 0.1.0"
49
+ s.add_dependency "multipart-post", "~> 1.1.2"
50
+ s.add_dependency "highline", "~> 1.6.2"
44
51
  end
45
52
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: pgxn_utils
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.1.1
5
+ version: 0.1.2
6
6
  platform: ruby
7
7
  authors:
8
8
  - Dickson S. Guedes
@@ -14,60 +14,93 @@ date: 2011-05-06 00:00:00 -03:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
- name: rspec
17
+ name: json
18
18
  prerelease: false
19
19
  requirement: &id001 !ruby/object:Gem::Requirement
20
20
  none: false
21
21
  requirements:
22
- - - ">="
22
+ - - ~>
23
23
  - !ruby/object:Gem::Version
24
- version: "0"
25
- type: :development
24
+ version: 1.5.2
25
+ type: :runtime
26
26
  version_requirements: *id001
27
27
  - !ruby/object:Gem::Dependency
28
- name: simplecov
28
+ name: thor
29
29
  prerelease: false
30
30
  requirement: &id002 !ruby/object:Gem::Requirement
31
31
  none: false
32
32
  requirements:
33
- - - ">="
33
+ - - ~>
34
34
  - !ruby/object:Gem::Version
35
- version: 0.4.0
36
- type: :development
35
+ version: "0.14"
36
+ type: :runtime
37
37
  version_requirements: *id002
38
38
  - !ruby/object:Gem::Dependency
39
- name: thor
39
+ name: rubyzip
40
40
  prerelease: false
41
41
  requirement: &id003 !ruby/object:Gem::Requirement
42
42
  none: false
43
43
  requirements:
44
44
  - - ~>
45
45
  - !ruby/object:Gem::Version
46
- version: "0.14"
46
+ version: 0.9.4
47
47
  type: :runtime
48
48
  version_requirements: *id003
49
49
  - !ruby/object:Gem::Dependency
50
- name: rubyzip
50
+ name: zippy
51
51
  prerelease: false
52
52
  requirement: &id004 !ruby/object:Gem::Requirement
53
53
  none: false
54
54
  requirements:
55
55
  - - ~>
56
56
  - !ruby/object:Gem::Version
57
- version: 0.9.4
57
+ version: 0.1.0
58
58
  type: :runtime
59
59
  version_requirements: *id004
60
60
  - !ruby/object:Gem::Dependency
61
- name: zippy
61
+ name: multipart-post
62
62
  prerelease: false
63
63
  requirement: &id005 !ruby/object:Gem::Requirement
64
64
  none: false
65
65
  requirements:
66
66
  - - ~>
67
67
  - !ruby/object:Gem::Version
68
- version: 0.1.0
68
+ version: 1.1.2
69
69
  type: :runtime
70
70
  version_requirements: *id005
71
+ - !ruby/object:Gem::Dependency
72
+ name: highline
73
+ prerelease: false
74
+ requirement: &id006 !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ~>
78
+ - !ruby/object:Gem::Version
79
+ version: 1.6.2
80
+ type: :runtime
81
+ version_requirements: *id006
82
+ - !ruby/object:Gem::Dependency
83
+ name: rspec
84
+ prerelease: false
85
+ requirement: &id007 !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: "0"
91
+ type: :development
92
+ version_requirements: *id007
93
+ - !ruby/object:Gem::Dependency
94
+ name: simplecov
95
+ prerelease: false
96
+ requirement: &id008 !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ~>
100
+ - !ruby/object:Gem::Version
101
+ version: 0.4.0
102
+ type: :development
103
+ version_requirements: *id008
71
104
  description: A PGXN set of tools to help developers create and publish your PostgreSQL extensions without pain
72
105
  email:
73
106
  - guedes@guedesoft.net
@@ -85,6 +118,7 @@ files:
85
118
  - bin/pgxn_utils
86
119
  - lib/pgxn_utils.rb
87
120
  - lib/pgxn_utils/cli.rb
121
+ - lib/pgxn_utils/constants.rb
88
122
  - lib/pgxn_utils/templates/root/%extension_name%.control.tt
89
123
  - lib/pgxn_utils/templates/root/META.json.tt
90
124
  - lib/pgxn_utils/templates/root/Makefile.tt
@@ -112,16 +146,16 @@ required_ruby_version: !ruby/object:Gem::Requirement
112
146
  requirements:
113
147
  - - ">="
114
148
  - !ruby/object:Gem::Version
115
- version: "0"
149
+ version: 1.8.7
116
150
  required_rubygems_version: !ruby/object:Gem::Requirement
117
151
  none: false
118
152
  requirements:
119
153
  - - ">="
120
154
  - !ruby/object:Gem::Version
121
- version: "0"
155
+ version: 1.3.7
122
156
  requirements: []
123
157
 
124
- rubyforge_project: pgxn_utils
158
+ rubyforge_project:
125
159
  rubygems_version: 1.6.2
126
160
  signing_key:
127
161
  specification_version: 3