pgpass 2012.01
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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: []
|