pgpass 2012.01
Sign up to get free protection for your applications and to get access to all the features.
- data/.gems +2 -0
- data/.rvmrc +2 -0
- data/.travis.yml +16 -0
- data/AUTHORS +4 -0
- data/CHANGELOG +20 -0
- data/LICENSE +19 -0
- data/MANIFEST +23 -0
- data/README.md +13 -0
- data/Rakefile +43 -0
- data/lib/pgpass.rb +194 -0
- data/lib/pgpass/version.rb +3 -0
- data/pgpass.gemspec +29 -0
- data/spec/pgpass.rb +99 -0
- data/spec/sample/invalid_permission +0 -0
- data/spec/sample/multiple +3 -0
- data/spec/sample/simple +2 -0
- data/tasks/authors.rake +30 -0
- data/tasks/bacon.rake +68 -0
- data/tasks/changelog.rake +18 -0
- data/tasks/gem.rake +19 -0
- data/tasks/manifest.rake +4 -0
- data/tasks/release.rake +41 -0
- data/tasks/reversion.rake +8 -0
- metadata +78 -0
data/.gems
ADDED
data/.rvmrc
ADDED
data/.travis.yml
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
script: 'RUBYOPT=-rubygems rake bacon'
|
2
|
+
before_script:
|
3
|
+
- test -s "$HOME/.rvm/scripts/rvm" && source "$HOME/.rvm/scripts/rvm"
|
4
|
+
- test -s .gems && rvm gemset import .gems
|
5
|
+
rvm:
|
6
|
+
- 1.9.2
|
7
|
+
- 1.9.3
|
8
|
+
- ruby-head
|
9
|
+
- rbx-19mode
|
10
|
+
- jruby
|
11
|
+
notifications:
|
12
|
+
email:
|
13
|
+
- mf@rubyists.com
|
14
|
+
branches:
|
15
|
+
only:
|
16
|
+
- master
|
data/AUTHORS
ADDED
data/CHANGELOG
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
[aac70cc | 2012-01-17 16:37:58 UTC] Michael Fellinger <m.fellinger@gmail.com>
|
2
|
+
|
3
|
+
* Fix permissions in the spec, git doesn't keep them
|
4
|
+
|
5
|
+
[52d7b71 | 2012-01-17 14:42:10 UTC] Michael Fellinger <m.fellinger@gmail.com>
|
6
|
+
|
7
|
+
* Version 2012.01
|
8
|
+
|
9
|
+
[50d87ad | 2012-01-17 13:39:25 UTC] Michael Fellinger <m.fellinger@gmail.com>
|
10
|
+
|
11
|
+
* proper indentation for example
|
12
|
+
|
13
|
+
[0fa30b5 | 2012-01-17 13:38:35 UTC] Michael Fellinger <m.fellinger@gmail.com>
|
14
|
+
|
15
|
+
* README is markdown
|
16
|
+
|
17
|
+
[66c6fe4 | 2012-01-17 13:32:18 UTC] Michael Fellinger <m.fellinger@gmail.com>
|
18
|
+
|
19
|
+
* first commit
|
20
|
+
|
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2012 Michael Fellinger <mf@rubyists.com>
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
4
|
+
this software and associated documentation files (the "Software"), to deal in
|
5
|
+
the Software without restriction, including without limitation the rights to
|
6
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
7
|
+
of the Software, and to permit persons to whom the Software is furnished to do
|
8
|
+
so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
11
|
+
copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
19
|
+
SOFTWARE.
|
data/MANIFEST
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
.gems
|
2
|
+
.rvmrc
|
3
|
+
.travis.yml
|
4
|
+
AUTHORS
|
5
|
+
CHANGELOG
|
6
|
+
LICENSE
|
7
|
+
MANIFEST
|
8
|
+
README.md
|
9
|
+
Rakefile
|
10
|
+
lib/pgpass.rb
|
11
|
+
lib/pgpass/version.rb
|
12
|
+
pgpass.gemspec
|
13
|
+
spec/pgpass.rb
|
14
|
+
spec/sample/invalid_permission
|
15
|
+
spec/sample/multiple
|
16
|
+
spec/sample/simple
|
17
|
+
tasks/authors.rake
|
18
|
+
tasks/bacon.rake
|
19
|
+
tasks/changelog.rake
|
20
|
+
tasks/gem.rake
|
21
|
+
tasks/manifest.rake
|
22
|
+
tasks/release.rake
|
23
|
+
tasks/reversion.rake
|
data/README.md
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# pgpass
|
2
|
+
|
3
|
+
This little library helps you finding, parsing, and using entries in .pgpass
|
4
|
+
files.
|
5
|
+
|
6
|
+
## Example usage
|
7
|
+
|
8
|
+
entry = Pgpass.match(database: 'sample_db', user: 'manveru')
|
9
|
+
DB = Sequel.connect(entry.to_url)
|
10
|
+
|
11
|
+
## License
|
12
|
+
|
13
|
+
MIT all the way, see the LICENSE file.
|
data/Rakefile
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'rake/clean'
|
2
|
+
require 'rubygems/package_task'
|
3
|
+
require 'time'
|
4
|
+
require 'date'
|
5
|
+
|
6
|
+
PROJECT_SPECS = FileList['spec/**/*.rb']
|
7
|
+
PROJECT_MODULE = 'Pgpass'
|
8
|
+
PROJECT_README = 'README.md'
|
9
|
+
PROJECT_VERSION = (ENV['VERSION'] || Date.today.strftime('%Y.%m.%d')).dup
|
10
|
+
|
11
|
+
DEPENDENCIES = {}
|
12
|
+
|
13
|
+
DEVELOPMENT_DEPENDENCIES = {
|
14
|
+
'bacon' => {:version => '>= 1.1.0'},
|
15
|
+
}
|
16
|
+
|
17
|
+
GEMSPEC = Gem::Specification.new{|s|
|
18
|
+
s.name = 'pgpass'
|
19
|
+
s.author = "Michael 'manveru' Fellinger"
|
20
|
+
s.summary = "Finding, parsing, and using entries in .pgpass files"
|
21
|
+
s.email = 'mf@rubyists.com'
|
22
|
+
s.homepage = 'http://github.com/manveru/pgpass'
|
23
|
+
s.platform = Gem::Platform::RUBY
|
24
|
+
s.version = PROJECT_VERSION
|
25
|
+
s.files = `git ls-files`.split("\n").sort
|
26
|
+
s.has_rdoc = true
|
27
|
+
s.require_path = 'lib'
|
28
|
+
s.required_ruby_version = '>= 1.9.2'
|
29
|
+
}
|
30
|
+
|
31
|
+
DEPENDENCIES.each do |name, options|
|
32
|
+
GEMSPEC.add_dependency(name, options[:version])
|
33
|
+
end
|
34
|
+
|
35
|
+
DEVELOPMENT_DEPENDENCIES.each do |name, options|
|
36
|
+
GEMSPEC.add_development_dependency(name, options[:version])
|
37
|
+
end
|
38
|
+
|
39
|
+
Dir['tasks/*.rake'].each{|f| import(f) }
|
40
|
+
|
41
|
+
task :default => [:bacon]
|
42
|
+
|
43
|
+
CLEAN.include('')
|
data/lib/pgpass.rb
ADDED
@@ -0,0 +1,194 @@
|
|
1
|
+
# The file .pgpass in a user's home directory or the file referenced by
|
2
|
+
# PGPASSFILE can contain passwords to be used if the connection requires a
|
3
|
+
# password (and no password has been specified otherwise).
|
4
|
+
# On Microsoft Windows the file is named %APPDATA%\postgresql\pgpass.conf
|
5
|
+
# (where %APPDATA% refers to the Application Data subdirectory in the user's
|
6
|
+
# profile).
|
7
|
+
#
|
8
|
+
# This file should contain lines of the following format:
|
9
|
+
#
|
10
|
+
# hostname:port:database:username:password
|
11
|
+
#
|
12
|
+
# (You can add a reminder comment to the file by copying the line above and
|
13
|
+
# preceding it with `#`.) Each of the first four fields can be a literal value,
|
14
|
+
# or `*`, which matches anything.
|
15
|
+
#
|
16
|
+
# The password field from the first line that matches the current connection
|
17
|
+
# parameters will be used.
|
18
|
+
#
|
19
|
+
# (Therefore, put more-specific entries first when you are using wildcards.) If
|
20
|
+
# an entry needs to contain : or \, escape this character with \.
|
21
|
+
#
|
22
|
+
# A host name of localhost matches both TCP (host name localhost) and Unix
|
23
|
+
# domain socket (pghost empty or the default socket directory) connections
|
24
|
+
# coming from the local machine.
|
25
|
+
#
|
26
|
+
# In a standby server, a database name of replication matches streaming
|
27
|
+
# replication connections made to the master server.
|
28
|
+
#
|
29
|
+
# The database field is of limited usefulness because users have the same
|
30
|
+
# password for all databases in the same cluster.
|
31
|
+
#
|
32
|
+
# On Unix systems, the permissions on .pgpass must disallow any access to world
|
33
|
+
# or group; achieve this by the command chmod 0600 ~/.pgpass. If the
|
34
|
+
# permissions are less strict than this, the file will be ignored.
|
35
|
+
#
|
36
|
+
# On Microsoft Windows, it is assumed that the file is stored in a directory
|
37
|
+
# that is secure, so no special permissions check is made.
|
38
|
+
|
39
|
+
require 'strscan'
|
40
|
+
require 'uri'
|
41
|
+
require 'etc'
|
42
|
+
|
43
|
+
module Pgpass
|
44
|
+
class Entry < Struct.new(:hostname, :port, :database, :username, :password)
|
45
|
+
def self.create(hash)
|
46
|
+
new(*hash.values_at(*members))
|
47
|
+
end
|
48
|
+
|
49
|
+
def blank?
|
50
|
+
any = hostname || port || database || username || password
|
51
|
+
any ? false : true
|
52
|
+
end
|
53
|
+
|
54
|
+
def to_url
|
55
|
+
uri = URI("postgres:///")
|
56
|
+
uri.user = username || ENV['PGUSER'] || Etc.getlogin
|
57
|
+
uri.password = password || ENV['PGPASSWORD']
|
58
|
+
uri.host = hostname || ENV['PGHOST'] || 'localhost'
|
59
|
+
uri.port = (port || ENV['PGPORT'] || 5432).to_i
|
60
|
+
uri.path = "/#{database || ENV['PGDATABASE']}"
|
61
|
+
uri.to_s
|
62
|
+
end
|
63
|
+
|
64
|
+
def to_hash
|
65
|
+
Hash[self.class.members.map{|m| self[m] }]
|
66
|
+
end
|
67
|
+
|
68
|
+
def merge(other)
|
69
|
+
self.class.create(to_hash.merge(other.to_hash))
|
70
|
+
end
|
71
|
+
|
72
|
+
def ==(other)
|
73
|
+
compare(database, other.database) &&
|
74
|
+
compare(username, other.username) &&
|
75
|
+
compare(hostname, other.hostname) &&
|
76
|
+
compare(port, other.port) &&
|
77
|
+
compare(password, other.password)
|
78
|
+
end
|
79
|
+
|
80
|
+
def complement(other)
|
81
|
+
self.class.create(
|
82
|
+
database: complement_one(database, other.database),
|
83
|
+
username: complement_one(username, other.username),
|
84
|
+
hostname: complement_one(hostname, other.hostname),
|
85
|
+
port: complement_one(port, other.port),
|
86
|
+
password: complement_one(password, other.password),
|
87
|
+
)
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
def compare(a, b)
|
93
|
+
b == nil || a == b || a == '*' || b == '*'
|
94
|
+
end
|
95
|
+
|
96
|
+
def complement_one(a, b)
|
97
|
+
a = nil if a == '*'
|
98
|
+
b = nil if b == '*'
|
99
|
+
a ? a : b
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
LOCATIONS = [ENV['PGPASSFILE'], './.pgpass', '~/.pgpass']
|
104
|
+
|
105
|
+
module_function
|
106
|
+
|
107
|
+
def match(given_options = {})
|
108
|
+
search = Entry.create(
|
109
|
+
user: (ENV['PGUSER'] || '*'),
|
110
|
+
password: ENV['PGPASSWORD'],
|
111
|
+
host: (ENV['PGHOST'] || '*'),
|
112
|
+
port: (ENV['PGPORT'] || '*'),
|
113
|
+
database: (ENV['PGDATABASE'] || '*'),
|
114
|
+
).merge(given_options)
|
115
|
+
|
116
|
+
LOCATIONS.compact.each do |path|
|
117
|
+
# consider only files
|
118
|
+
next unless File.file?(path)
|
119
|
+
# that aren't world/group accessible
|
120
|
+
next unless File.stat(path).mode & 077 == 0
|
121
|
+
|
122
|
+
load_file(path).each do |entry|
|
123
|
+
return entry.complement(search) if entry == search
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
nil
|
128
|
+
end
|
129
|
+
|
130
|
+
def guess(paths = PATH)
|
131
|
+
PATH.each do |path|
|
132
|
+
begin
|
133
|
+
load_file(File.join(path, ".pgpass"))
|
134
|
+
rescue Errno::ENOENT => ex
|
135
|
+
warn(ex)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def load_file(path)
|
141
|
+
File.open(File.expand_path(path), 'r'){|io| load(io) }
|
142
|
+
end
|
143
|
+
|
144
|
+
def load(io)
|
145
|
+
io.each_line.map{|line| parse_line(line) }
|
146
|
+
end
|
147
|
+
|
148
|
+
def parse_line(line)
|
149
|
+
sc = StringScanner.new(line)
|
150
|
+
entry = Entry.new
|
151
|
+
key_index = 0
|
152
|
+
value = ''
|
153
|
+
|
154
|
+
loop do
|
155
|
+
pos = sc.pos
|
156
|
+
|
157
|
+
if sc.bol?
|
158
|
+
if sc.scan(/\s*#/)
|
159
|
+
# commented line
|
160
|
+
return
|
161
|
+
elsif sc.scan(/\s*$/)
|
162
|
+
# empty line
|
163
|
+
return
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
if sc.eos?
|
168
|
+
entry[Entry.members[key_index]] = value
|
169
|
+
return entry # end of string
|
170
|
+
end
|
171
|
+
|
172
|
+
if sc.scan(/\\:/)
|
173
|
+
value << ':'
|
174
|
+
elsif sc.scan(/\\\\/)
|
175
|
+
value << '\\'
|
176
|
+
elsif sc.scan(/:/)
|
177
|
+
entry[Entry.members[key_index]] = value
|
178
|
+
key_index += 1
|
179
|
+
value = ''
|
180
|
+
elsif sc.scan(/\r\n|\r|\n/)
|
181
|
+
entry[Entry.members[key_index]] = value
|
182
|
+
return entry
|
183
|
+
elsif sc.scan(/./)
|
184
|
+
value << sc[0]
|
185
|
+
end
|
186
|
+
|
187
|
+
if sc.pos == pos
|
188
|
+
raise "position didn't advance, stuck in parsing"
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
return entry
|
193
|
+
end
|
194
|
+
end
|
data/pgpass.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = "pgpass"
|
5
|
+
s.version = "2012.01"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Michael 'manveru' Fellinger"]
|
9
|
+
s.date = "2012-01-17"
|
10
|
+
s.email = "mf@rubyists.com"
|
11
|
+
s.files = [".gems", ".rvmrc", ".travis.yml", "AUTHORS", "CHANGELOG", "LICENSE", "MANIFEST", "README.md", "Rakefile", "lib/pgpass.rb", "lib/pgpass/version.rb", "pgpass.gemspec", "spec/pgpass.rb", "spec/sample/invalid_permission", "spec/sample/multiple", "spec/sample/simple", "tasks/authors.rake", "tasks/bacon.rake", "tasks/changelog.rake", "tasks/gem.rake", "tasks/manifest.rake", "tasks/release.rake", "tasks/reversion.rake"]
|
12
|
+
s.homepage = "http://github.com/manveru/pgpass"
|
13
|
+
s.require_paths = ["lib"]
|
14
|
+
s.required_ruby_version = Gem::Requirement.new(">= 1.9.2")
|
15
|
+
s.rubygems_version = "1.8.10"
|
16
|
+
s.summary = "Finding, parsing, and using entries in .pgpass files"
|
17
|
+
|
18
|
+
if s.respond_to? :specification_version then
|
19
|
+
s.specification_version = 3
|
20
|
+
|
21
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
22
|
+
s.add_development_dependency(%q<bacon>, [">= 1.1.0"])
|
23
|
+
else
|
24
|
+
s.add_dependency(%q<bacon>, [">= 1.1.0"])
|
25
|
+
end
|
26
|
+
else
|
27
|
+
s.add_dependency(%q<bacon>, [">= 1.1.0"])
|
28
|
+
end
|
29
|
+
end
|
data/spec/pgpass.rb
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'bacon'
|
2
|
+
Bacon.summary_on_exit
|
3
|
+
|
4
|
+
require_relative '../lib/pgpass'
|
5
|
+
|
6
|
+
describe Pgpass do
|
7
|
+
describe '::load' do
|
8
|
+
it 'loads a normal line' do
|
9
|
+
line = 'host:1234:database:user:password'
|
10
|
+
|
11
|
+
entry = Pgpass.load(line).first
|
12
|
+
entry.hostname.should == 'host'
|
13
|
+
entry.port.should == '1234'
|
14
|
+
entry.database.should == 'database'
|
15
|
+
entry.username.should == 'user'
|
16
|
+
entry.password.should == 'password'
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'loads a line with *' do
|
20
|
+
line = 'host:*:db:user:pw'
|
21
|
+
entry = Pgpass.load(line).first
|
22
|
+
entry.hostname.should == 'host'
|
23
|
+
entry.port.should == '*'
|
24
|
+
entry.database.should == 'db'
|
25
|
+
entry.username.should == 'user'
|
26
|
+
entry.password.should == 'pw'
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'loads two lines with *' do
|
30
|
+
lines = "h1:*:d1:u1:p1\nh2:*:d2:u2:p2"
|
31
|
+
entries = Pgpass.load(lines)
|
32
|
+
entries[0].hostname.should == 'h1'
|
33
|
+
entries[0].port.should == '*'
|
34
|
+
entries[0].database.should == 'd1'
|
35
|
+
entries[0].username.should == 'u1'
|
36
|
+
entries[0].password.should == 'p1'
|
37
|
+
|
38
|
+
entries[1].hostname.should == 'h2'
|
39
|
+
entries[1].port.should == '*'
|
40
|
+
entries[1].database.should == 'd2'
|
41
|
+
entries[1].username.should == 'u2'
|
42
|
+
entries[1].password.should == 'p2'
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'loads a line with \:' do
|
46
|
+
str = '\:x\:\:y:bar\::\:d:u\::p'
|
47
|
+
Pgpass.load(str).should == [
|
48
|
+
Pgpass::Entry.create(
|
49
|
+
hostname: ':x::y',
|
50
|
+
port: 'bar:',
|
51
|
+
database: ':d',
|
52
|
+
username: 'u:',
|
53
|
+
password: 'p',
|
54
|
+
)
|
55
|
+
]
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'loads a line with \\\\' do
|
59
|
+
str = '\\\\x\\\\y:bar\\\\:\\\\d:u:p'
|
60
|
+
puts str
|
61
|
+
Pgpass.load(str).should == [
|
62
|
+
Pgpass::Entry.create(
|
63
|
+
hostname: '\\x\\y',
|
64
|
+
port: 'bar\\',
|
65
|
+
database: '\\d',
|
66
|
+
username: 'u',
|
67
|
+
password: 'p',
|
68
|
+
)
|
69
|
+
]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe '::match' do
|
74
|
+
def with_pgpass(relative_path)
|
75
|
+
location = File.expand_path("../#{relative_path}", __FILE__)
|
76
|
+
File.chmod(0600, location)
|
77
|
+
Pgpass::LOCATIONS.unshift(location)
|
78
|
+
yield
|
79
|
+
ensure
|
80
|
+
Pgpass::LOCATIONS.delete(location)
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'matches an entry with the same database' do
|
84
|
+
with_pgpass 'sample/simple' do
|
85
|
+
entry = Pgpass.match(database: 'db')
|
86
|
+
entry.database.should == 'db'
|
87
|
+
entry.username.should == 'manveru'
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'matches earlier entries with higher priority' do
|
92
|
+
with_pgpass 'sample/multiple' do
|
93
|
+
entry = Pgpass.match(database: 'db1')
|
94
|
+
entry.database.should == 'db1'
|
95
|
+
entry.password.should == 'pass1'
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
File without changes
|
data/spec/sample/simple
ADDED
data/tasks/authors.rake
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# Once git has a fix for the glibc in handling .mailmap and another fix for
|
2
|
+
# allowing empty mail address to be mapped in .mailmap we won't have to handle
|
3
|
+
# them manually.
|
4
|
+
|
5
|
+
desc 'Update AUTHORS'
|
6
|
+
task :authors do
|
7
|
+
authors = Hash.new(0)
|
8
|
+
|
9
|
+
`git shortlog -nse`.scan(/(\d+)\s(.+)\s<(.*)>$/) do |count, name, email|
|
10
|
+
case name
|
11
|
+
when "ahoward"
|
12
|
+
name, email = "Ara T. Howard", "ara.t.howard@gmail.com"
|
13
|
+
when "Martin Hilbig blueonyx@dev-area.net"
|
14
|
+
name, email = "Martin Hilbig", "blueonyx@dev-area.net"
|
15
|
+
when "Michael Fellinger m.fellinger@gmail.com"
|
16
|
+
name, email = "Michael Fellinger", "m.fellinger@gmail.com"
|
17
|
+
end
|
18
|
+
|
19
|
+
authors[[name, email]] += count.to_i
|
20
|
+
end
|
21
|
+
|
22
|
+
File.open('AUTHORS', 'w+') do |io|
|
23
|
+
io.puts "Following persons have contributed to #{GEMSPEC.name}."
|
24
|
+
io.puts '(Sorted by number of submitted patches, then alphabetically)'
|
25
|
+
io.puts ''
|
26
|
+
authors.sort_by{|(n,e),c| [-c, n.downcase] }.each do |(name, email), count|
|
27
|
+
io.puts("%6d %s <%s>" % [count, name, email])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/tasks/bacon.rake
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
desc 'Run all bacon specs with pretty output'
|
4
|
+
task :bacon do
|
5
|
+
require 'open3'
|
6
|
+
require 'scanf'
|
7
|
+
require 'matrix'
|
8
|
+
|
9
|
+
specs = PROJECT_SPECS
|
10
|
+
|
11
|
+
some_failed = false
|
12
|
+
specs_size = specs.size
|
13
|
+
len = specs.map{|s| s.size }.sort.last
|
14
|
+
total_tests = total_assertions = total_failures = total_errors = 0
|
15
|
+
totals = Vector[0, 0, 0, 0]
|
16
|
+
|
17
|
+
red, yellow, green = "\e[31m%s\e[0m", "\e[33m%s\e[0m", "\e[32m%s\e[0m"
|
18
|
+
left_format = "%4d/%d: %-#{len + 11}s"
|
19
|
+
spec_format = "%d specifications (%d requirements), %d failures, %d errors"
|
20
|
+
|
21
|
+
specs.each_with_index do |spec, idx|
|
22
|
+
print(left_format % [idx + 1, specs_size, spec])
|
23
|
+
|
24
|
+
Open3.popen3(FileUtils::RUBY, '-w', spec) do |sin, sout, serr|
|
25
|
+
out = sout.read.strip
|
26
|
+
err = serr.read.strip
|
27
|
+
|
28
|
+
# this is conventional, see spec/innate/state/fiber.rb for usage
|
29
|
+
if out =~ /^Bacon::Error: (needed .*)/
|
30
|
+
puts(yellow % ("%6s %s" % ['', $1]))
|
31
|
+
else
|
32
|
+
total = nil
|
33
|
+
|
34
|
+
out.each_line do |line|
|
35
|
+
scanned = line.scanf(spec_format)
|
36
|
+
|
37
|
+
next unless scanned.size == 4
|
38
|
+
|
39
|
+
total = Vector[*scanned]
|
40
|
+
break
|
41
|
+
end
|
42
|
+
|
43
|
+
if total
|
44
|
+
totals += total
|
45
|
+
tests, assertions, failures, errors = total_array = total.to_a
|
46
|
+
|
47
|
+
if tests > 0 && failures + errors == 0
|
48
|
+
puts((green % "%6d passed") % tests)
|
49
|
+
else
|
50
|
+
some_failed = true
|
51
|
+
puts(red % " failed")
|
52
|
+
puts out unless out.empty?
|
53
|
+
puts err unless err.empty?
|
54
|
+
end
|
55
|
+
else
|
56
|
+
some_failed = true
|
57
|
+
puts(red % " failed")
|
58
|
+
puts out unless out.empty?
|
59
|
+
puts err unless err.empty?
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
total_color = some_failed ? red : green
|
66
|
+
puts(total_color % (spec_format % totals.to_a))
|
67
|
+
exit 1 if some_failed
|
68
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
desc 'update changelog'
|
2
|
+
task :changelog do
|
3
|
+
File.open('CHANGELOG', 'w+') do |changelog|
|
4
|
+
`git log -z --abbrev-commit`.split("\0").each do |commit|
|
5
|
+
next if commit =~ /^Merge: \d*/
|
6
|
+
ref, author, time, _, title, _, message = commit.split("\n", 7)
|
7
|
+
ref = ref[/commit ([0-9a-f]+)/, 1]
|
8
|
+
author = author[/Author: (.*)/, 1].strip
|
9
|
+
time = Time.parse(time[/Date: (.*)/, 1]).utc
|
10
|
+
title.strip!
|
11
|
+
|
12
|
+
changelog.puts "[#{ref} | #{time}] #{author}"
|
13
|
+
changelog.puts '', " * #{title}"
|
14
|
+
changelog.puts '', message.rstrip if message
|
15
|
+
changelog.puts
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/tasks/gem.rake
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
task :gemspec => [:manifest, :changelog] do
|
2
|
+
gemspec_file = "#{GEMSPEC.name}.gemspec"
|
3
|
+
File.open(gemspec_file, 'w+'){|gs| gs.puts(GEMSPEC.to_ruby) }
|
4
|
+
end
|
5
|
+
|
6
|
+
desc "package and install from gemspec"
|
7
|
+
task :install => [:gemspec] do
|
8
|
+
sh "gem build #{GEMSPEC.name}.gemspec"
|
9
|
+
sh "gem install #{GEMSPEC.name}-#{GEMSPEC.version}.gem"
|
10
|
+
end
|
11
|
+
|
12
|
+
desc "uninstall the gem"
|
13
|
+
task :uninstall => [:clean] do
|
14
|
+
sh %{gem uninstall -x #{GEMSPEC.name}}
|
15
|
+
end
|
16
|
+
|
17
|
+
Gem::PackageTask.new(GEMSPEC) do |pkg|
|
18
|
+
pkg.need_tar = true
|
19
|
+
end
|
data/tasks/manifest.rake
ADDED
data/tasks/release.rake
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
namespace :release do
|
2
|
+
task :prepare => [:reversion, :authors, :gemspec]
|
3
|
+
task :all => ['release:github', 'release:gemcutter']
|
4
|
+
|
5
|
+
desc 'Release on github'
|
6
|
+
task :github => :prepare do
|
7
|
+
name, version = GEMSPEC.name, GEMSPEC.version
|
8
|
+
|
9
|
+
sh('git', 'add',
|
10
|
+
'MANIFEST', 'CHANGELOG', 'AUTHORS',
|
11
|
+
"#{name}.gemspec",
|
12
|
+
"lib/#{name}/version.rb")
|
13
|
+
|
14
|
+
puts <<-INSTRUCTIONS
|
15
|
+
================================================================================
|
16
|
+
|
17
|
+
I added the relevant files, you can commit them, tag the commit, and push:
|
18
|
+
|
19
|
+
git commit -m 'Version #{version}'
|
20
|
+
git tag -a -m '#{version}' '#{version}'
|
21
|
+
git push
|
22
|
+
|
23
|
+
================================================================================
|
24
|
+
INSTRUCTIONS
|
25
|
+
end
|
26
|
+
|
27
|
+
desc 'Release on gemcutter'
|
28
|
+
task :gemcutter => ['release:prepare', :package] do
|
29
|
+
name, version = GEMSPEC.name, GEMSPEC.version
|
30
|
+
|
31
|
+
puts <<-INSTRUCTIONS
|
32
|
+
================================================================================
|
33
|
+
|
34
|
+
To publish to gemcutter do following:
|
35
|
+
|
36
|
+
gem push pkg/#{name}-#{version}.gem
|
37
|
+
|
38
|
+
================================================================================
|
39
|
+
INSTRUCTIONS
|
40
|
+
end
|
41
|
+
end
|
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pgpass
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '2012.01'
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Michael 'manveru' Fellinger
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-01-17 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bacon
|
16
|
+
requirement: &9109840 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.1.0
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *9109840
|
25
|
+
description:
|
26
|
+
email: mf@rubyists.com
|
27
|
+
executables: []
|
28
|
+
extensions: []
|
29
|
+
extra_rdoc_files: []
|
30
|
+
files:
|
31
|
+
- .gems
|
32
|
+
- .rvmrc
|
33
|
+
- .travis.yml
|
34
|
+
- AUTHORS
|
35
|
+
- CHANGELOG
|
36
|
+
- LICENSE
|
37
|
+
- MANIFEST
|
38
|
+
- README.md
|
39
|
+
- Rakefile
|
40
|
+
- lib/pgpass.rb
|
41
|
+
- lib/pgpass/version.rb
|
42
|
+
- pgpass.gemspec
|
43
|
+
- spec/pgpass.rb
|
44
|
+
- spec/sample/invalid_permission
|
45
|
+
- spec/sample/multiple
|
46
|
+
- spec/sample/simple
|
47
|
+
- tasks/authors.rake
|
48
|
+
- tasks/bacon.rake
|
49
|
+
- tasks/changelog.rake
|
50
|
+
- tasks/gem.rake
|
51
|
+
- tasks/manifest.rake
|
52
|
+
- tasks/release.rake
|
53
|
+
- tasks/reversion.rake
|
54
|
+
homepage: http://github.com/manveru/pgpass
|
55
|
+
licenses: []
|
56
|
+
post_install_message:
|
57
|
+
rdoc_options: []
|
58
|
+
require_paths:
|
59
|
+
- lib
|
60
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: 1.9.2
|
66
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
67
|
+
none: false
|
68
|
+
requirements:
|
69
|
+
- - ! '>='
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '0'
|
72
|
+
requirements: []
|
73
|
+
rubyforge_project:
|
74
|
+
rubygems_version: 1.8.10
|
75
|
+
signing_key:
|
76
|
+
specification_version: 3
|
77
|
+
summary: Finding, parsing, and using entries in .pgpass files
|
78
|
+
test_files: []
|