pgbundle 0.0.13 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Build Status](https://travis-ci.org/adjust/pgbundle.svg?branch=master)](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:
|