pgbundle 0.0.13 → 0.1.0
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.
- checksums.yaml +5 -5
- data/.travis.yml +11 -3
- data/CHANGELOG.md +5 -0
- data/README.md +142 -13
- data/bin/pgbundle +28 -20
- data/cibuild.sh +28 -0
- data/lib/pgbundle.rb +16 -2
- data/lib/pgbundle/base_source.rb +4 -0
- data/lib/pgbundle/database.rb +38 -14
- data/lib/pgbundle/definition.rb +2 -2
- data/lib/pgbundle/dsl.rb +4 -3
- data/lib/pgbundle/extension.rb +30 -6
- data/lib/pgbundle/git_source.rb +43 -0
- data/lib/pgbundle/github_source.rb +4 -30
- data/lib/pgbundle/path_source.rb +3 -0
- data/lib/pgbundle/pgxn_source.rb +61 -0
- data/lib/pgbundle/version.rb +1 -1
- data/pgbundle.gemspec +3 -3
- data/spec/Pgfile +2 -1
- data/spec/dsl_spec.rb +2 -2
- data/spec/extension_spec.rb +16 -0
- data/spec/spec_helper.rb +9 -5
- metadata +31 -28
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 15dfb28b9fdc9700e097a5a57391cf3177ddb20fbcb12535335df559429e2ce5
|
4
|
+
data.tar.gz: e961ee85cbea6731f1a8358f1291ac102ad39b15c7e7540cd323716bbedfde4b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d2f24410fe6dd3bedf3622786caac2ec63055f2bda8452b2445fe55261c222a9e40e09582d155e5b70518cbb3b2ad1be148905f0ed37027e1236f8f8edef48a7
|
7
|
+
data.tar.gz: 99bb423f0d8a0daac1c8b3f1cd4e45820e223260749793007a6d4b4034edaaa89e56c5c43f485f7d9c1b7b524a0f6e73673353c92cdf2b0855a59865e1da65e7
|
data/.travis.yml
CHANGED
@@ -1,11 +1,19 @@
|
|
1
1
|
language: ruby
|
2
2
|
rvm:
|
3
|
-
- 1.9.3
|
4
3
|
- rbx-2
|
5
4
|
- 2.0.0
|
6
5
|
- 2.1.1
|
6
|
+
- 2.2.3
|
7
7
|
matrix:
|
8
8
|
allow_failures:
|
9
9
|
- rvm: rbx-2
|
10
|
-
|
11
|
-
|
10
|
+
before_install:
|
11
|
+
- wget https://gist.github.com/petere/5893799/raw/apt.postgresql.org.sh
|
12
|
+
- wget https://gist.github.com/petere/6023944/raw/pg-travis-test.sh
|
13
|
+
- sudo sh ./apt.postgresql.org.sh
|
14
|
+
env:
|
15
|
+
- PGVERSION=9.1
|
16
|
+
- PGVERSION=9.2
|
17
|
+
- PGVERSION=9.3
|
18
|
+
- PGVERSION=9.4
|
19
|
+
script: bash ./cibuild.sh
|
data/CHANGELOG.md
ADDED
data/README.md
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
[](https://travis-ci.org/adjust/pgbundle)
|
2
|
+
|
1
3
|
# pgbundle
|
2
4
|
|
3
5
|
bundling postgres extension
|
@@ -11,35 +13,162 @@ bundling postgres extension
|
|
11
13
|
define your dependent postgres extensions in a Pgfile like this:
|
12
14
|
|
13
15
|
```
|
14
|
-
#Pgfile
|
16
|
+
# Pgfile
|
15
17
|
|
16
18
|
database 'my_database', host: 'my.db.server', use_sudo: true, system_user: 'postgres'
|
17
19
|
|
18
20
|
pgx 'hstore'
|
19
21
|
pgx 'my_extension', '1.0.2', github: me/my_extension
|
20
22
|
pgx 'my_other_extionsion', :git => 'https://github.com/me/my_other_extionsion.git'
|
21
|
-
pgx 'my_ltree_dependend_extension', github: me/my_ltree_dependend_extension,
|
23
|
+
pgx 'my_ltree_dependend_extension', github: me/my_ltree_dependend_extension, requires: 'ltree'
|
24
|
+
```
|
25
|
+
|
26
|
+
**database**
|
27
|
+
|
28
|
+
`database` defines on which database(s) the extensions should be installed. The first
|
29
|
+
argument is the database name the additional options may specify your setup but
|
30
|
+
come with reasonable default values.
|
31
|
+
|
32
|
+
option | default | desciption
|
33
|
+
------- | ------- | -----------
|
34
|
+
user | 'postgres' | the database user (needs privilege to `CREATE EXTENSION`)
|
35
|
+
host | 'localhost' | the database host (needs to be accessible from where `pgbundle` runs)
|
36
|
+
use_sudo | false | if true use `sudo` to run `make install` if needed
|
37
|
+
system_user | 'postgres' | the (os) system user that is allowed to install an extension (through make)
|
38
|
+
port | 5432 | the database port
|
39
|
+
force_ssh | false | run commands via ssh even if host is `localhost`
|
40
|
+
slave | false | defines if the database runs as a read-only slave thus skips any `CREATE` command
|
41
|
+
|
42
|
+
**pgx**
|
43
|
+
|
44
|
+
The `pgx` command defines you actual Extension. The first argument specifies the Extension name,
|
45
|
+
the second optional parameter defines the required Version. If the Extension is not yet
|
46
|
+
installed on the server you may wish to define how `pgbundle` can find it's source to build
|
47
|
+
and install it. And which Extensions may be required
|
48
|
+
|
49
|
+
option | description
|
50
|
+
------ | -----------
|
51
|
+
git | any git repository pgbundle can clone from
|
52
|
+
github | any github repository in the form `user/repository`
|
53
|
+
branch | an optional branch name for git or github sources defaults to `master`
|
54
|
+
requires | an optional extension that the extension depends on
|
55
|
+
path | any absolute or relative local path e.g. './foo/bar'
|
56
|
+
pgxn | any repository available on http://pgxn.org/
|
57
|
+
flags | optional string used for make results in "make flags && make flags install"
|
58
|
+
|
59
|
+
|
60
|
+
Some Extensions may require other Extensions to allow `pgbundle` to resolve dependencies
|
61
|
+
and install it in the right order you can define them with `requires`.
|
62
|
+
If the required Extension is not yet available on the target server or the Extension
|
63
|
+
requires a specific Version you should define it as well.
|
64
|
+
E.g.
|
65
|
+
|
66
|
+
```
|
67
|
+
# Pgfile
|
68
|
+
|
69
|
+
database ...
|
70
|
+
|
71
|
+
pgx 'foo', '0.1.2', github: me/foo
|
72
|
+
|
73
|
+
# set foo as dependency for bar
|
74
|
+
pgx 'bar', '1.2.3', github: me/bar, requires: 'foo'
|
75
|
+
|
76
|
+
# set bar and boo as dependency for baz
|
77
|
+
# will automatically set foo as dependency as well
|
78
|
+
pgx 'baz', '0.2.3', github: me/baz, requires: ['bar', 'boo']
|
79
|
+
# installs jsquery with flag 'USE_PGXS=1'
|
80
|
+
# i.e. running make USE_PGXS=1 && make USE_PGXS=1 install
|
81
|
+
pgx 'jsquery', github: 'postgrespro/jsquery', flags: 'USE_PGXS=1'
|
82
|
+
```
|
83
|
+
|
84
|
+
## pgbundle commands
|
85
|
+
|
86
|
+
`pgbundle` comes with four commands. If the optional `pgfile` is not given it assumes
|
87
|
+
to find a file named `Pgfile` in the current directory.
|
88
|
+
|
89
|
+
**check**
|
90
|
+
|
91
|
+
checks availability of required extensions.
|
92
|
+
|
93
|
+
```
|
94
|
+
pgbundle check [pgfile]
|
22
95
|
```
|
23
96
|
|
24
|
-
|
97
|
+
`check` does not change anything on your system, it only checks which
|
98
|
+
of your specified extensions are available and which are missing.
|
99
|
+
It returns with exitcode `1` if any Extension is missing and `0` otherwise.
|
25
100
|
|
26
|
-
pgbundle install
|
27
101
|
|
28
|
-
|
102
|
+
**install**
|
29
103
|
|
30
|
-
|
104
|
+
installs extensions
|
31
105
|
|
32
|
-
|
106
|
+
```
|
107
|
+
pgbundle install [pgfile] [-f]
|
108
|
+
```
|
109
|
+
|
110
|
+
`install` tries to install missing Extensions. If `--force` is given it installs
|
111
|
+
all Extension even if they are already installed.
|
112
|
+
|
113
|
+
**create**
|
114
|
+
|
115
|
+
create the extension at the desired version
|
116
|
+
|
117
|
+
```
|
118
|
+
pgbundle create [pgfile]
|
119
|
+
```
|
33
120
|
|
34
|
-
|
121
|
+
`create` runs the `CREATE EXTENSION` command on the specified databases. If a version
|
122
|
+
is specified in the `Pgfile` it tries to install with `CREATE EXTENSION VERSION version`.
|
123
|
+
If the Extension is already created but with a wrong version, it will run
|
124
|
+
`ALTER EXTENSION extension_name UPDATE TO new_version`.
|
35
125
|
|
36
|
-
|
126
|
+
**init**
|
127
|
+
|
128
|
+
write an initial pgfile to stdout
|
129
|
+
|
130
|
+
```
|
131
|
+
pgbundle init db_name -u user -h host -p port
|
132
|
+
```
|
133
|
+
|
134
|
+
`init` is there to help you get started. If you have already a database with installed
|
135
|
+
Extensions you get the content for an initial `Pgfile`. Pgbundle will figure out
|
136
|
+
which Extension at which Version are already in use and print a reasonable starting
|
137
|
+
point for you Pgfile.
|
138
|
+
However this is only to help you get started you may wish to specify sources and
|
139
|
+
dependencies correctly.
|
140
|
+
|
141
|
+
### How it works
|
142
|
+
|
143
|
+
You may already have noticed that using Extensions on postgres requires two different
|
144
|
+
steps. Building the extension on the database cluster with `make install`
|
145
|
+
and creating the extension into the database with `CREATE/ALTER EXTENSION`.
|
146
|
+
Pgbundle reflects that with the two different commands `install` and `create`.
|
147
|
+
|
148
|
+
Usually `pgbundle` runs along with your application on your application server
|
149
|
+
which often is different from your database machine. Thus the `install` step
|
150
|
+
will (if necessary) try to download the source code of the extension into a
|
151
|
+
temporary folder and then copy it to your database servers into `/tmp/pgbundle`.
|
152
|
+
From there it will run `make clean && make && make install` for each database.
|
153
|
+
You may specify as which user you want these commands to run with the `system_user`
|
154
|
+
option. Although for security reasons not recommended you can specify to run the
|
155
|
+
install step with sudo `use_sudo: true`, but we suggest to give write permission
|
156
|
+
for the postgres system user to the install targets. If you are not sure which these
|
157
|
+
are run
|
158
|
+
|
159
|
+
```
|
160
|
+
pg_config
|
161
|
+
```
|
37
162
|
|
38
|
-
|
163
|
+
and find the `LIBDIR`, `SHAREDIR` and `DOCDIR`
|
39
164
|
|
40
|
-
|
165
|
+
#### master - slave
|
41
166
|
|
42
|
-
|
167
|
+
Every serious production database cluster usually has a slave often ran as Hot Standby.
|
168
|
+
You should make sure that all your Extension are also installed on all slaves.
|
169
|
+
Because database slaves run as read-only servers any attempt to `CREATE` or `ALTER`
|
170
|
+
Extension will fail, these commands should only run on the master server and will
|
171
|
+
be replicated to the slave from there. You can tell `pgbundle` that it should skip
|
172
|
+
these steps with `slave: true`.
|
43
173
|
|
44
|
-
pgbundle init my_project -u postgres -h localhost
|
45
174
|
|
data/bin/pgbundle
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
require 'thor'
|
3
3
|
require 'thor/group'
|
4
4
|
require 'pgbundle'
|
5
|
-
require 'pry'
|
6
5
|
|
7
6
|
module PgBundle
|
8
7
|
class Cli < Thor
|
@@ -10,17 +9,21 @@ module PgBundle
|
|
10
9
|
method_options %w( force -f ) => :boolean
|
11
10
|
def install(pgfile = 'Pgfile')
|
12
11
|
if options.force?
|
13
|
-
installed =
|
12
|
+
installed = definitions(pgfile).inject({}){|m, d| m[d.database] = d.install!; m}
|
14
13
|
else
|
15
|
-
|
16
|
-
|
14
|
+
definitions(pgfile).each do |d|
|
15
|
+
d.available_extensions.each do |dep|
|
16
|
+
say_status('exists', "#{d.database}: #{dep.name}")
|
17
|
+
end
|
17
18
|
end
|
18
19
|
|
19
|
-
installed =
|
20
|
+
installed = definitions(pgfile).inject({}){|m, d| m[d.database] = d.install; m}
|
20
21
|
end
|
21
22
|
|
22
|
-
installed.each do |
|
23
|
-
|
23
|
+
installed.each do |db, deps|
|
24
|
+
deps.each do |d|
|
25
|
+
say_status('install', "#{db}: #{d.name}", :yellow)
|
26
|
+
end
|
24
27
|
end
|
25
28
|
rescue InstallError, ExtensionCreateError, CircularDependencyError => e
|
26
29
|
say_status('error', e.message, :red)
|
@@ -30,15 +33,17 @@ module PgBundle
|
|
30
33
|
desc 'check', 'checks availability of required extensions'
|
31
34
|
def check(pgfile = 'Pgfile')
|
32
35
|
missing = false
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
36
|
+
definitions(pgfile).each do |df|
|
37
|
+
df.check.each do |d|
|
38
|
+
if d[:created]
|
39
|
+
say_status('created', "#{df.database}: #{d[:name]}")
|
40
|
+
else
|
41
|
+
unless d[:installed]
|
42
|
+
say_status('missing', "#{df.database}: #{d[:name]}", :red)
|
43
|
+
missing = true
|
44
|
+
end
|
45
|
+
say_status('installed', "#{df.database}: #{d[:name]}", :yellow) if d[:installed]
|
40
46
|
end
|
41
|
-
say_status('installed', d[:name], :yellow) if d[:installed]
|
42
47
|
end
|
43
48
|
end
|
44
49
|
exit 1 if missing
|
@@ -46,14 +51,17 @@ module PgBundle
|
|
46
51
|
|
47
52
|
desc 'create', 'create the extension at the desired version'
|
48
53
|
def create(pgfile = 'Pgfile')
|
49
|
-
|
50
|
-
|
54
|
+
definitions(pgfile).each do |df|
|
55
|
+
df.create.each do | d |
|
56
|
+
say_status('created', "#{df.database}: #{d.name}")
|
57
|
+
end
|
51
58
|
end
|
52
59
|
end
|
53
60
|
|
54
61
|
desc 'init', 'write an initial pgfile to stdout'
|
55
62
|
method_options %w( user -u ) => :string
|
56
63
|
method_options %w( host -h ) => :string
|
64
|
+
method_options %w( port -p ) => :string
|
57
65
|
def init(db_name)
|
58
66
|
definition = PgBundle::Definition.new
|
59
67
|
definition.database = PgBundle::Database.new(db_name, options)
|
@@ -62,9 +70,9 @@ module PgBundle
|
|
62
70
|
end
|
63
71
|
|
64
72
|
no_commands do
|
65
|
-
def
|
66
|
-
|
67
|
-
|
73
|
+
def definitions(pgfile)
|
74
|
+
definitions = Dsl.new.eval_pgfile(pgfile)
|
75
|
+
definitions.map(&:link_dependencies)
|
68
76
|
end
|
69
77
|
end
|
70
78
|
end
|
data/cibuild.sh
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
set -eux
|
4
|
+
|
5
|
+
sudo apt-get update
|
6
|
+
|
7
|
+
packages="postgresql-$PGVERSION postgresql-server-dev-$PGVERSION postgresql-common"
|
8
|
+
|
9
|
+
# bug: http://www.postgresql.org/message-id/20130508192711.GA9243@msgid.df7cb.de
|
10
|
+
sudo update-alternatives --remove-all postmaster.1.gz
|
11
|
+
|
12
|
+
# stop all existing instances (because of https://github.com/travis-ci/travis-cookbooks/pull/221)
|
13
|
+
sudo service postgresql stop
|
14
|
+
# and make sure they don't come back
|
15
|
+
echo 'exit 0' | sudo tee /etc/init.d/postgresql
|
16
|
+
sudo chmod a+x /etc/init.d/postgresql
|
17
|
+
|
18
|
+
sudo apt-get -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" install $packages
|
19
|
+
|
20
|
+
status=0
|
21
|
+
sudo pg_createcluster --start $PGVERSION test -p 55435 -- -A trust
|
22
|
+
# make all PG_CONFIG=/usr/lib/postgresql/$PGVERSION/bin/pg_config
|
23
|
+
# sudo make install PG_CONFIG=/usr/lib/postgresql/$PGVERSION/bin/pg_config
|
24
|
+
# PGPORT=55435 make installcheck PGUSER=postgres PG_CONFIG=/usr/lib/postgresql/$PGVERSION/bin/pg_config || status=$?
|
25
|
+
|
26
|
+
# if test -f regression.diffs; then cat regression.diffs; fi
|
27
|
+
# exit $status
|
28
|
+
PGPORT=55435 rake
|
data/lib/pgbundle.rb
CHANGED
@@ -7,7 +7,9 @@ module PgBundle
|
|
7
7
|
autoload :Extension, 'pgbundle/extension'
|
8
8
|
autoload :BaseSource, 'pgbundle/base_source'
|
9
9
|
autoload :PathSource, 'pgbundle/path_source'
|
10
|
+
autoload :GitSource, 'pgbundle/git_source'
|
10
11
|
autoload :GithubSource, 'pgbundle/github_source'
|
12
|
+
autoload :PgxnSource, 'pgbundle/pgxn_source'
|
11
13
|
|
12
14
|
class PgfileError < StandardError
|
13
15
|
end
|
@@ -44,6 +46,12 @@ module PgBundle
|
|
44
46
|
end
|
45
47
|
end
|
46
48
|
|
49
|
+
class ReadOnlyDb < ExtensionCreateError
|
50
|
+
def initialize(db, base_name)
|
51
|
+
super "Can't install Extension #{base_name}, Database #{db} is read only"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
47
55
|
class MissingDependency < ExtensionCreateError
|
48
56
|
def initialize(base_name, dependen_msg)
|
49
57
|
required = dependen_msg[/required extension \"(.*?)\" is not installed/, 1]
|
@@ -52,8 +60,14 @@ module PgBundle
|
|
52
60
|
end
|
53
61
|
|
54
62
|
class GitCommandError < InstallError
|
55
|
-
def initialize(dest)
|
56
|
-
super "Failed to load git repository cmd: '#{dest}'"
|
63
|
+
def initialize(dest, details = nil)
|
64
|
+
super "Failed to load git repository cmd: '#{dest}'\n failed: #{details}"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
class PgxnError < InstallError
|
69
|
+
def initialize(dest, message = nil)
|
70
|
+
super "Failed to load from pgxn: '#{dest}'\n failed: #{message}"
|
57
71
|
end
|
58
72
|
end
|
59
73
|
end
|
data/lib/pgbundle/base_source.rb
CHANGED
data/lib/pgbundle/database.rb
CHANGED
@@ -1,29 +1,49 @@
|
|
1
1
|
require 'pg'
|
2
2
|
require 'net/ssh'
|
3
|
-
|
3
|
+
|
4
4
|
module PgBundle
|
5
5
|
# The Database class defines on which database the extensions should be installed
|
6
6
|
# Note to install an extension the code must be compiled on the database server
|
7
7
|
# on a typical environment ssh access is needed if the database host differs from
|
8
8
|
# the Pgfile host
|
9
9
|
class Database
|
10
|
-
attr_accessor :name, :user, :host, :system_user, :use_sudo, :port, :force_ssh
|
10
|
+
attr_accessor :name, :user, :password, :host, :system_user, :use_sudo, :port, :force_ssh
|
11
|
+
|
11
12
|
def initialize(name, opts = {})
|
12
13
|
@name = name
|
13
14
|
@user = opts[:user] || 'postgres'
|
15
|
+
@password = opts[:password]
|
14
16
|
@host = opts[:host] || 'localhost'
|
15
17
|
@use_sudo = opts[:use_sudo] || false
|
16
18
|
@system_user = opts[:system_user] || 'postgres'
|
17
19
|
@port = opts[:port] || 5432
|
18
20
|
@force_ssh = opts[:force_ssh] || false
|
21
|
+
@slave = opts[:slave] || false
|
19
22
|
end
|
20
23
|
|
21
24
|
def connection
|
22
25
|
@connection ||= begin
|
23
|
-
PG.connect(
|
26
|
+
PG.connect(connection_opts)
|
24
27
|
end
|
25
28
|
end
|
26
29
|
|
30
|
+
def connection_opts
|
31
|
+
{
|
32
|
+
dbname: name,
|
33
|
+
user: user,
|
34
|
+
password: password,
|
35
|
+
host: host,
|
36
|
+
port: port
|
37
|
+
}.compact
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_s
|
41
|
+
"host: #{@host}:#{port} db: #{@name}"
|
42
|
+
end
|
43
|
+
|
44
|
+
def slave?
|
45
|
+
@slave
|
46
|
+
end
|
27
47
|
# executes the given sql on the database connections
|
28
48
|
# redirects all noise to /dev/null
|
29
49
|
def execute(sql)
|
@@ -52,19 +72,22 @@ module PgBundle
|
|
52
72
|
end
|
53
73
|
|
54
74
|
# loads the source, runs make install and removes the source afterwards
|
55
|
-
def make_install(source, ext_name)
|
75
|
+
def make_install(source, ext_name, flags)
|
76
|
+
run("mkdir -p -m 0777 /tmp/pgbundle/")
|
56
77
|
remove_source(ext_name)
|
57
78
|
source.load(host, system_user, load_destination(ext_name))
|
58
|
-
run(make_install_cmd(ext_name))
|
79
|
+
run(make_install_cmd(ext_name, flags))
|
59
80
|
remove_source(ext_name)
|
81
|
+
source.clean
|
60
82
|
end
|
61
83
|
|
62
84
|
# loads the source and runs make uninstall
|
63
|
-
def make_uninstall(source, ext_name)
|
85
|
+
def make_uninstall(source, ext_name, flags)
|
64
86
|
remove_source(ext_name)
|
65
87
|
source.load(host, system_user, load_destination(ext_name))
|
66
|
-
run(make_uninstall_cmd(ext_name))
|
88
|
+
run(make_uninstall_cmd(ext_name, flags))
|
67
89
|
remove_source(ext_name)
|
90
|
+
source.clean
|
68
91
|
end
|
69
92
|
|
70
93
|
def drop_extension(name)
|
@@ -90,17 +113,17 @@ module PgBundle
|
|
90
113
|
run("rm -rf #{load_destination(name)}")
|
91
114
|
end
|
92
115
|
|
93
|
-
def make_install_cmd(name)
|
116
|
+
def make_install_cmd(name, flags)
|
94
117
|
<<-CMD.gsub(/\s+/, ' ').strip
|
95
118
|
cd #{load_destination(name)} &&
|
96
|
-
#{sudo} make clean &&
|
97
|
-
#{sudo} make &&
|
98
|
-
#{sudo} make install
|
119
|
+
#{sudo} make #{flags} clean &&
|
120
|
+
#{sudo} make #{flags} &&
|
121
|
+
#{sudo} make #{flags} install
|
99
122
|
CMD
|
100
123
|
end
|
101
124
|
|
102
|
-
def make_uninstall_cmd(name)
|
103
|
-
"cd #{load_destination(name)} && #{sudo} make uninstall"
|
125
|
+
def make_uninstall_cmd(name, flags)
|
126
|
+
"cd #{load_destination(name)} && #{sudo} make #{flags} uninstall"
|
104
127
|
end
|
105
128
|
|
106
129
|
def run(cmd)
|
@@ -112,7 +135,8 @@ module PgBundle
|
|
112
135
|
end
|
113
136
|
|
114
137
|
def local(cmd)
|
115
|
-
%x(#{cmd})
|
138
|
+
res = %x((#{cmd}) 2>&1 )
|
139
|
+
raise res unless $?.success?
|
116
140
|
end
|
117
141
|
|
118
142
|
def remote(cmd)
|
data/lib/pgbundle/definition.rb
CHANGED
@@ -49,7 +49,7 @@ module PgBundle
|
|
49
49
|
end
|
50
50
|
|
51
51
|
def init
|
52
|
-
["database '#{database.name}', host: '#{database.host}', user: #{database.user}, system_user: #{database.system_user}, use_sudo: #{database.use_sudo}"] +
|
52
|
+
["database '#{database.name}', host: '#{database.host}', user: '#{database.user}', system_user: '#{database.system_user}', use_sudo: #{database.use_sudo}"] +
|
53
53
|
database.current_definition.map do |r|
|
54
54
|
name, version = r['name'], r['version']
|
55
55
|
requires = r['requires'] ? ", requires: " + r['requires'].gsub(/[{},]/,{'{' => '%w(', '}' =>')', ','=> ' '}) : ''
|
@@ -57,7 +57,7 @@ module PgBundle
|
|
57
57
|
end
|
58
58
|
end
|
59
59
|
|
60
|
-
# returns an array hashes with dependency information
|
60
|
+
# returns an array of hashes with dependency information
|
61
61
|
# [{name: 'foo', installed: true, created: false }]
|
62
62
|
def check
|
63
63
|
link_dependencies
|
data/lib/pgbundle/dsl.rb
CHANGED
@@ -4,13 +4,14 @@ module PgBundle
|
|
4
4
|
class Dsl
|
5
5
|
def initialize
|
6
6
|
@definition = Definition.new
|
7
|
-
@
|
7
|
+
@databases = []
|
8
8
|
end
|
9
9
|
|
10
10
|
def eval_pgfile(pgfile, contents=nil)
|
11
11
|
contents ||= File.read(pgfile.to_s)
|
12
12
|
instance_eval(contents)
|
13
|
-
@
|
13
|
+
raise PgfileError, "no databases defined" if @databases.size == 0
|
14
|
+
@databases.map{|d| df = @definition.clone; df.database = d; df}
|
14
15
|
rescue SyntaxError => e
|
15
16
|
syntax_msg = e.message.gsub("#{pgfile}:", 'on line ')
|
16
17
|
raise PgfileError, "Pgfile syntax error #{syntax_msg}"
|
@@ -24,7 +25,7 @@ module PgBundle
|
|
24
25
|
|
25
26
|
def database(*args)
|
26
27
|
opts = extract_options!(args)
|
27
|
-
@
|
28
|
+
@databases << Database.new(args.first, opts)
|
28
29
|
end
|
29
30
|
|
30
31
|
def pgx(*args)
|
data/lib/pgbundle/extension.rb
CHANGED
@@ -10,11 +10,13 @@ module PgBundle
|
|
10
10
|
# or install it along with it's dependencies
|
11
11
|
# extension.install(database)
|
12
12
|
class Extension
|
13
|
-
attr_accessor :name, :version, :source, :resolving_dependencies
|
13
|
+
attr_accessor :name, :version, :source, :resolving_dependencies,:flags
|
14
14
|
def initialize(*args)
|
15
15
|
opts = args.last.is_a?(Hash) ? args.pop : {}
|
16
16
|
@name, @version = args
|
17
|
+
validate(opts)
|
17
18
|
self.dependencies = opts[:requires]
|
19
|
+
self.flags = opts[:flags]
|
18
20
|
set_source(opts)
|
19
21
|
end
|
20
22
|
|
@@ -108,7 +110,6 @@ module PgBundle
|
|
108
110
|
unless dependencies.empty?
|
109
111
|
install_dependencies(database, force)
|
110
112
|
end
|
111
|
-
|
112
113
|
make_install(database, force)
|
113
114
|
raise ExtensionNotFound.new(name, version) unless installed?(database)
|
114
115
|
|
@@ -126,6 +127,7 @@ module PgBundle
|
|
126
127
|
# create the extension along with it's dependencies in a transaction
|
127
128
|
def create_with_dependencies(database)
|
128
129
|
return true if created?(database)
|
130
|
+
return false if database.slave?
|
129
131
|
|
130
132
|
database.transaction do |con|
|
131
133
|
begin
|
@@ -181,6 +183,21 @@ module PgBundle
|
|
181
183
|
|
182
184
|
private
|
183
185
|
|
186
|
+
# validates the options hash
|
187
|
+
def validate(opts)
|
188
|
+
opts = opts.clone
|
189
|
+
opts.delete(:requires)
|
190
|
+
opts.delete(:branch)
|
191
|
+
opts.delete(:flags)
|
192
|
+
if opts.size > 1
|
193
|
+
fail PgfileError.new "multiple sources given for #{name} #{opts}"
|
194
|
+
end
|
195
|
+
|
196
|
+
unless opts.empty? || [:path, :git, :github, :pgxn].include?(opts.keys.first)
|
197
|
+
fail PgfileError.new "invalid source #{opts.keys.first} for #{name}"
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
184
201
|
# adds dependencies that are required but not defined yet
|
185
202
|
def add_missing_required_dependencies(database)
|
186
203
|
requires = requires(database)
|
@@ -218,12 +235,12 @@ module PgBundle
|
|
218
235
|
# loads the source and runs make uninstall
|
219
236
|
# returns: self
|
220
237
|
def make_uninstall(database)
|
221
|
-
database.make_uninstall(source, name)
|
238
|
+
database.make_uninstall(source, name, flags)
|
222
239
|
self
|
223
240
|
end
|
224
241
|
|
225
242
|
def drop_extension(database)
|
226
|
-
database.drop_extension(name)
|
243
|
+
database.drop_extension(name) unless database.slave?
|
227
244
|
end
|
228
245
|
|
229
246
|
# loads the source and runs make install
|
@@ -233,7 +250,7 @@ module PgBundle
|
|
233
250
|
|
234
251
|
fail SourceNotFound, name if source.nil?
|
235
252
|
|
236
|
-
database.make_install(source, name)
|
253
|
+
database.make_install(source, name, flags)
|
237
254
|
self
|
238
255
|
end
|
239
256
|
|
@@ -266,6 +283,7 @@ module PgBundle
|
|
266
283
|
|
267
284
|
# hard checks that the dependency can be created running CREATE command in a transaction
|
268
285
|
def creatable!(database)
|
286
|
+
return false if database.slave?
|
269
287
|
database.transaction_rollback do |con|
|
270
288
|
begin
|
271
289
|
create_dependencies(con)
|
@@ -274,6 +292,8 @@ module PgBundle
|
|
274
292
|
raise ExtensionNotFound.new(name, version)
|
275
293
|
rescue PG::UndefinedObject => err
|
276
294
|
raise MissingDependency.new(name, err.message)
|
295
|
+
rescue PG::ReadOnlySqlTransaction
|
296
|
+
raise ReadOnlyDb.new(database, name)
|
277
297
|
end
|
278
298
|
end
|
279
299
|
|
@@ -286,7 +306,7 @@ module PgBundle
|
|
286
306
|
database.execute 'BEGIN'
|
287
307
|
begin
|
288
308
|
database.execute update_stmt
|
289
|
-
rescue PG::UndefinedFile, PG::UndefinedObject => err
|
309
|
+
rescue PG::UndefinedFile, PG::UndefinedObject, PG::ReadOnlySqlTransaction => err
|
290
310
|
@error = err.message
|
291
311
|
result = false
|
292
312
|
end
|
@@ -298,8 +318,12 @@ module PgBundle
|
|
298
318
|
def set_source(opts)
|
299
319
|
if opts[:path]
|
300
320
|
@source = PathSource.new(opts[:path])
|
321
|
+
elsif opts[:git]
|
322
|
+
@source = GitSource.new(opts[:git], opts[:branch])
|
301
323
|
elsif opts[:github]
|
302
324
|
@source = GithubSource.new(opts[:github], opts[:branch])
|
325
|
+
elsif opts[:pgxn]
|
326
|
+
@source = PgxnSource.new(name, version)
|
303
327
|
end
|
304
328
|
end
|
305
329
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'tmpdir'
|
2
|
+
module PgBundle
|
3
|
+
# The GithubSource class defines a Github Source
|
4
|
+
class GitSource < BaseSource
|
5
|
+
attr_reader :branch
|
6
|
+
|
7
|
+
def initialize(path, branch = 'master')
|
8
|
+
@branch = branch || 'master'
|
9
|
+
super(path)
|
10
|
+
end
|
11
|
+
|
12
|
+
def load(host, user, dest)
|
13
|
+
clone
|
14
|
+
if host == 'localhost'
|
15
|
+
copy_local("#{clone_dir}/", dest)
|
16
|
+
else
|
17
|
+
copy_to_remote(host, user, "#{clone_dir}/", dest)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def clean
|
22
|
+
FileUtils.remove_dir(clone_dir, true)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def clone
|
28
|
+
res = %x((rm -rf #{clone_dir} && #{git_command} && rm -rf #{clone_dir}/.git}) 2>&1)
|
29
|
+
unless $?.success?
|
30
|
+
fail GitCommandError, git_command, res
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# git clone user@git-server:project_name.git -b branch_name /some/folder
|
35
|
+
def git_command
|
36
|
+
"git clone #{path} -b #{branch} --quiet --depth=1 #{clone_dir}"
|
37
|
+
end
|
38
|
+
|
39
|
+
def clone_dir
|
40
|
+
@clone_dir ||= Dir.mktmpdir
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -1,39 +1,13 @@
|
|
1
1
|
require 'tmpdir'
|
2
2
|
module PgBundle
|
3
3
|
# The GithubSource class defines a Github Source
|
4
|
-
class GithubSource <
|
4
|
+
class GithubSource < GitSource
|
5
5
|
attr_reader :branch
|
6
6
|
|
7
7
|
def initialize(path, branch = 'master')
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
def load(host, user, dest)
|
13
|
-
clone
|
14
|
-
if host == 'localhost'
|
15
|
-
copy_local("#{clone_dir}/", dest)
|
16
|
-
else
|
17
|
-
copy_to_remote(host, user, "#{clone_dir}/", dest)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
private
|
22
|
-
|
23
|
-
def clone
|
24
|
-
%x((rm -rf #{clone_dir} && #{git_command} && rm -rf #{clone_dir}/.git}) 2>&1)
|
25
|
-
unless $?.success?
|
26
|
-
fail GitCommandError, git_command
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
# git clone user@git-server:project_name.git -b branch_name /some/folder
|
31
|
-
def git_command
|
32
|
-
"git clone git@github.com:#{path}.git -b #{branch} --quiet --depth=1 #{clone_dir}"
|
33
|
-
end
|
34
|
-
|
35
|
-
def clone_dir
|
36
|
-
@clone_dir ||= Dir.mktmpdir
|
8
|
+
branch = branch || 'master'
|
9
|
+
path = "git@github.com:#{path}.git"
|
10
|
+
super(path, branch)
|
37
11
|
end
|
38
12
|
end
|
39
13
|
end
|
data/lib/pgbundle/path_source.rb
CHANGED
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'tmpdir'
|
2
|
+
require 'open-uri'
|
3
|
+
require 'zip'
|
4
|
+
|
5
|
+
module PgBundle
|
6
|
+
# The GithubSource class defines a Github Source
|
7
|
+
class PgxnSource < BaseSource
|
8
|
+
|
9
|
+
def initialize(dist, version)
|
10
|
+
@dist, @version = dist, version
|
11
|
+
path = "http://master.pgxn.org/dist/%{dist}/%{version}/%{dist}-%{version}.zip" % {dist: dist, version: version}
|
12
|
+
super(path)
|
13
|
+
end
|
14
|
+
|
15
|
+
def load(host, user, dest)
|
16
|
+
download
|
17
|
+
unzip
|
18
|
+
if host == 'localhost'
|
19
|
+
copy_local("#{download_dir}/#{@dist}-#{@version}", dest)
|
20
|
+
else
|
21
|
+
copy_to_remote(host, user, "#{download_dir}/#{@dist}-#{@version}", dest)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def clean
|
26
|
+
FileUtils.remove_dir(download_dir, true)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def download
|
32
|
+
begin
|
33
|
+
File.open(zipfile, "wb") do |saved_file|
|
34
|
+
open(@path, "rb") do |read_file|
|
35
|
+
saved_file.write(read_file.read)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
rescue OpenURI::HTTPError => e
|
39
|
+
raise PgxnError.new(path, e.message)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def zipfile
|
44
|
+
"#{download_dir}/#{@dist}.zip"
|
45
|
+
end
|
46
|
+
|
47
|
+
def unzip
|
48
|
+
Zip::ZipFile.open(zipfile) do |zip_file|
|
49
|
+
zip_file.each do |f|
|
50
|
+
f_path=File.join(download_dir, f.name)
|
51
|
+
FileUtils.mkdir_p(File.dirname(f_path))
|
52
|
+
zip_file.extract(f, f_path) unless File.exist?(f_path)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def download_dir
|
58
|
+
@clone_dir ||= Dir.mktmpdir
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/lib/pgbundle/version.rb
CHANGED
data/pgbundle.gemspec
CHANGED
@@ -21,10 +21,10 @@ Gem::Specification.new do |spec|
|
|
21
21
|
spec.add_dependency 'thor'
|
22
22
|
spec.add_dependency 'net-ssh'
|
23
23
|
spec.add_dependency 'net-scp'
|
24
|
+
spec.add_dependency 'zip'
|
24
25
|
#https://bitbucket.org/ged/ruby-pg/wiki/Home
|
25
26
|
spec.add_dependency 'pg', '> 0.17'
|
26
27
|
spec.add_development_dependency 'rspec', '~> 2.14.0'
|
27
|
-
spec.add_development_dependency "bundler", "
|
28
|
-
spec.add_development_dependency "rake"
|
29
|
-
spec.add_development_dependency "pry"
|
28
|
+
spec.add_development_dependency "bundler", ">= 1.5.0"
|
29
|
+
spec.add_development_dependency "rake", "<= 11.0.0"
|
30
30
|
end
|
data/spec/Pgfile
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
-
database 'pgbundle_test', host: 'localhost'
|
1
|
+
database 'pgbundle_test', host: 'localhost'
|
2
2
|
|
3
3
|
pgx 'hstore'
|
4
4
|
pgx 'bar', path: './spec/sample_extensions/bar', requires: 'ltree'
|
5
5
|
pgx 'baz', '0.0.2', path: './spec/sample_extensions/baz', requires: 'foo'
|
6
6
|
pgx 'foo', '0.0.1', path: './spec/sample_extensions/foo'
|
7
7
|
pgx 'myext', github: 'adjust/numhstore', branch: 'topic'
|
8
|
+
pgx 'jsquery', github: 'postgrespro/jsquery', flags: 'USE_PGXS=1'
|
data/spec/dsl_spec.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe PgBundle::Dsl do
|
4
|
-
subject { PgBundle::Dsl.new.eval_pgfile(File.expand_path('../Pgfile', __FILE__)) }
|
4
|
+
subject { PgBundle::Dsl.new.eval_pgfile(File.expand_path('../Pgfile', __FILE__)).first }
|
5
5
|
|
6
6
|
its(:database) { should be_a PgBundle::Database }
|
7
|
-
its('database.
|
7
|
+
its('database.host') { should eq 'localhost' }
|
8
8
|
its(:extensions) { should be_a Hash }
|
9
9
|
|
10
10
|
context 'parsing options' do
|
data/spec/extension_spec.rb
CHANGED
@@ -65,6 +65,22 @@ describe PgBundle::Extension do
|
|
65
65
|
end
|
66
66
|
end
|
67
67
|
|
68
|
+
context 'installing from github' do
|
69
|
+
subject { PgBundle::Extension.new('ltree', '1.0', git: 'https://github.com/adjust/ltree.git') }
|
70
|
+
|
71
|
+
before do
|
72
|
+
allow_any_instance_of(PgBundle::GithubSource)
|
73
|
+
.to receive(:clone_dir)
|
74
|
+
.and_return('/tmp/pgbundle/tree_tmp')
|
75
|
+
|
76
|
+
subject.install(database, true)
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'cleans the tmp directory after install' do
|
80
|
+
expect(Dir.exists?('/tmp/pgbundle/tree_tmp')).to be_false
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
68
84
|
context 'require not found' do
|
69
85
|
subject { PgBundle::Extension.new('foo', '0.0.2', path: './spec/sample_extensions/foo', requires: PgBundle::Extension.new('noope')) }
|
70
86
|
|
data/spec/spec_helper.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'pgbundle'
|
3
3
|
require 'pg'
|
4
|
-
require 'pry'
|
5
4
|
|
6
5
|
Dir.glob('spec/support/**/*.rb').each { |f| require f }
|
7
6
|
|
@@ -12,14 +11,19 @@ RSpec.configure do |config|
|
|
12
11
|
config.filter_run focus: true
|
13
12
|
config.run_all_when_everything_filtered = true
|
14
13
|
config.before(:suite) do
|
15
|
-
|
14
|
+
system "mkdir -p -m 0777 /tmp/pgbundle/"
|
15
|
+
conn = PG.connect(dbname: 'postgres', user: 'postgres', host: 'localhost', port: ENV['PGPORT'] || 5432)
|
16
16
|
conn.exec('CREATE DATABASE pgbundle_test')
|
17
17
|
conn.close
|
18
18
|
end
|
19
19
|
|
20
20
|
config.after(:suite) do
|
21
|
-
conn = PG.connect(dbname: 'postgres', user: 'postgres')
|
22
|
-
|
21
|
+
conn = PG.connect(dbname: 'postgres', user: 'postgres', host: 'localhost', port: ENV['PGPORT'] || 5432)
|
22
|
+
if ENV['PGVERSION']=='9.1'
|
23
|
+
conn.exec("SELECT pg_terminate_backend(procpid) from pg_stat_activity WHERE datname ='pgbundle_test'")
|
24
|
+
else
|
25
|
+
conn.exec("SELECT pg_terminate_backend(pid) from pg_stat_activity WHERE datname ='pgbundle_test'")
|
26
|
+
end
|
23
27
|
conn.exec('DROP DATABASE IF EXISTS pgbundle_test')
|
24
28
|
conn.close
|
25
29
|
end
|
@@ -42,6 +46,6 @@ RSpec.configure do |config|
|
|
42
46
|
end
|
43
47
|
|
44
48
|
def database
|
45
|
-
@db ||= PgBundle::Database.new('pgbundle_test')
|
49
|
+
@db ||= PgBundle::Database.new('pgbundle_test', user: 'postgres', host: 'localhost', port: ENV['PGPORT'] || 5432, use_sudo: ENV['TRAVIS'])
|
46
50
|
end
|
47
51
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pgbundle
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Manuel Kniep
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-08-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: zip
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: pg
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -82,46 +96,32 @@ dependencies:
|
|
82
96
|
version: 2.14.0
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
98
|
name: bundler
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
86
|
-
requirements:
|
87
|
-
- - "~>"
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: '1.5'
|
90
|
-
type: :development
|
91
|
-
prerelease: false
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
93
|
-
requirements:
|
94
|
-
- - "~>"
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: '1.5'
|
97
|
-
- !ruby/object:Gem::Dependency
|
98
|
-
name: rake
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
101
|
- - ">="
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version:
|
103
|
+
version: 1.5.0
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - ">="
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version:
|
110
|
+
version: 1.5.0
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
|
-
name:
|
112
|
+
name: rake
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
|
-
- - "
|
115
|
+
- - "<="
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version:
|
117
|
+
version: 11.0.0
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
|
-
- - "
|
122
|
+
- - "<="
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version:
|
124
|
+
version: 11.0.0
|
125
125
|
description: bundler like postgres extension manager
|
126
126
|
email:
|
127
127
|
- manuel@adjust.com
|
@@ -132,19 +132,23 @@ extra_rdoc_files: []
|
|
132
132
|
files:
|
133
133
|
- ".gitignore"
|
134
134
|
- ".travis.yml"
|
135
|
+
- CHANGELOG.md
|
135
136
|
- Gemfile
|
136
137
|
- LICENSE.txt
|
137
138
|
- README.md
|
138
139
|
- Rakefile
|
139
140
|
- bin/pgbundle
|
141
|
+
- cibuild.sh
|
140
142
|
- lib/pgbundle.rb
|
141
143
|
- lib/pgbundle/base_source.rb
|
142
144
|
- lib/pgbundle/database.rb
|
143
145
|
- lib/pgbundle/definition.rb
|
144
146
|
- lib/pgbundle/dsl.rb
|
145
147
|
- lib/pgbundle/extension.rb
|
148
|
+
- lib/pgbundle/git_source.rb
|
146
149
|
- lib/pgbundle/github_source.rb
|
147
150
|
- lib/pgbundle/path_source.rb
|
151
|
+
- lib/pgbundle/pgxn_source.rb
|
148
152
|
- lib/pgbundle/version.rb
|
149
153
|
- pgbundle.gemspec
|
150
154
|
- spec/Pgfile
|
@@ -169,7 +173,7 @@ homepage: http://github.com/adjust/pgbundle
|
|
169
173
|
licenses:
|
170
174
|
- MIT
|
171
175
|
metadata: {}
|
172
|
-
post_install_message:
|
176
|
+
post_install_message:
|
173
177
|
rdoc_options: []
|
174
178
|
require_paths:
|
175
179
|
- lib
|
@@ -184,9 +188,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
184
188
|
- !ruby/object:Gem::Version
|
185
189
|
version: '0'
|
186
190
|
requirements: []
|
187
|
-
|
188
|
-
|
189
|
-
signing_key:
|
191
|
+
rubygems_version: 3.1.2
|
192
|
+
signing_key:
|
190
193
|
specification_version: 4
|
191
194
|
summary: bundling postgres extension
|
192
195
|
test_files:
|