prick 0.19.0 → 0.20.1
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 +4 -4
- data/Gemfile +10 -4
- data/README.md +7 -7
- data/Rakefile +3 -1
- data/TODO +13 -11
- data/bin/console +2 -1
- data/doc/build-yml.txt +14 -0
- data/exe/prick +237 -19
- data/lib/builder/batch.rb +147 -0
- data/lib/builder/builder.rb +122 -0
- data/lib/builder/node.rb +189 -0
- data/lib/builder/node_pool.rb +105 -0
- data/lib/builder/parser.rb +120 -0
- data/lib/local/command.rb +193 -0
- data/lib/{prick → local}/git.rb +148 -22
- data/lib/local/timer.rb +98 -0
- data/lib/prick/constants.rb +54 -66
- data/lib/prick/diff.rb +28 -18
- data/lib/prick/prick_version.rb +161 -0
- data/lib/prick/state.rb +80 -165
- data/lib/prick/version.rb +2 -163
- data/lib/prick.rb +38 -24
- data/lib/share/init/.gitignore +10 -0
- data/lib/share/init/.prick-context +2 -0
- data/lib/share/init/.rspec +3 -0
- data/{share/schema/schema/public → lib/share/init/migration}/.keep +0 -0
- data/lib/share/init/prick.yml +6 -0
- data/lib/share/init/schema/.keep +0 -0
- data/lib/share/init/schema/build.yml +2 -0
- data/lib/share/init/schema/prick/.keep +0 -0
- data/lib/share/init/schema/prick/build.yml +5 -0
- data/lib/share/init/schema/prick/data.sql +6 -0
- data/{share/schema → lib/share/init}/schema/prick/tables.sql +2 -3
- data/lib/share/init/schema/public/.keep +0 -0
- data/lib/share/init/spec/prick_helper.rb +1 -0
- data/lib/share/init/spec/prick_spec.rb +6 -0
- data/lib/share/init/spec/spec_helper.rb +50 -0
- data/lib/share/migrate/migration/build.yml +4 -0
- data/lib/share/migrate/migration/diff.after-tables.sql +0 -0
- data/lib/share/migrate/migration/diff.before-tables.sql +0 -0
- data/lib/share/migrate/migration/diff.tables.sql +0 -0
- data/lib/subcommand/prick-build.rb +55 -0
- data/lib/subcommand/prick-create.rb +78 -0
- data/lib/subcommand/prick-drop.rb +25 -0
- data/lib/subcommand/prick-fox.rb +62 -0
- data/lib/subcommand/prick-init.rb +46 -0
- data/lib/subcommand/prick-make.rb +202 -0
- data/lib/subcommand/prick-migrate.rb +37 -0
- data/lib/subcommand/prick-release.rb +23 -0
- data/lib/subcommand/prick-setup.rb +20 -0
- data/lib/subcommand/prick-teardown.rb +18 -0
- data/prick.gemspec +32 -21
- metadata +95 -76
- data/.gitignore +0 -29
- data/.travis.yml +0 -7
- data/doc/create_release.txt +0 -17
- data/doc/flow.txt +0 -98
- data/doc/migra +0 -1
- data/doc/migrations.txt +0 -172
- data/doc/notes.txt +0 -116
- data/doc/prick.txt +0 -114
- data/doc/sh.prick +0 -316
- data/lib/ext/algorithm.rb +0 -14
- data/lib/ext/fileutils.rb +0 -26
- data/lib/ext/forward_method.rb +0 -18
- data/lib/ext/pg.rb +0 -18
- data/lib/ext/shortest_path.rb +0 -44
- data/lib/prick/archive.rb +0 -124
- data/lib/prick/branch.rb +0 -265
- data/lib/prick/builder.rb +0 -246
- data/lib/prick/cache.rb +0 -34
- data/lib/prick/command.rb +0 -104
- data/lib/prick/database.rb +0 -82
- data/lib/prick/dsort.rb +0 -151
- data/lib/prick/ensure.rb +0 -119
- data/lib/prick/exceptions.rb +0 -25
- data/lib/prick/head.rb +0 -189
- data/lib/prick/migration.rb +0 -70
- data/lib/prick/program.rb +0 -287
- data/lib/prick/project.rb +0 -626
- data/lib/prick/rdbms.rb +0 -137
- data/lib/prick/schema.rb +0 -27
- data/lib/prick/share.rb +0 -64
- data/libexec/strip-comments +0 -33
- data/make_releases +0 -72
- data/make_schema +0 -10
- data/share/diff/diff.after-tables.sql +0 -4
- data/share/diff/diff.before-tables.sql +0 -4
- data/share/diff/diff.tables.sql +0 -8
- data/share/features/diff.sql +0 -2
- data/share/features/feature/diff.sql +0 -2
- data/share/features/feature/migrate.sql +0 -2
- data/share/features/features.sql +0 -2
- data/share/features/features.yml +0 -2
- data/share/features/migrations.sql +0 -4
- data/share/gitignore +0 -2
- data/share/migration/diff.tables.sql +0 -8
- data/share/migration/features.yml +0 -6
- data/share/migration/migrate.sql +0 -3
- data/share/migration/migrate.yml +0 -8
- data/share/migration/tables.sql +0 -3
- data/share/schema/build.yml +0 -14
- data/share/schema/schema/build.yml +0 -3
- data/share/schema/schema/prick/build.yml +0 -14
- data/share/schema/schema/prick/data.sql +0 -7
- data/share/schema/schema/prick/schema.sql +0 -3
- data/share/schema/schema/public/build.yml +0 -13
- data/share/schema/schema.sql +0 -3
- data/test_assorted +0 -192
- data/test_feature +0 -112
- data/test_refactor +0 -34
- data/test_single_dev +0 -83
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2abdd6978f9dce4cf9570d2ad5165fef65541ed5e69bd6150086a30b232498a5
|
|
4
|
+
data.tar.gz: bb1accf8f541d7197c73b14407401d91d5e3b9475b205bad46bea8851d2825c6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 951dee9f87d7ba9475bf70512b35d29720a30ec5371e2c03c00575c21a94163f3aa43bf28bfbb6a5fe80e0da63cb1154bd84f29ae671651b7aa54de0e45630e2
|
|
7
|
+
data.tar.gz: cc5ef462d6c9ae5e1add6bb9fc53ffc4a6684c64020d24fad39327cd80218f01c031060f7c2e14a125a94caad305c658994e2ea53845f211909a4764a72f8d75
|
data/Gemfile
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
source "https://rubygems.org"
|
|
4
4
|
|
|
5
|
-
# Specify your gem's dependencies in
|
|
5
|
+
# Specify your gem's dependencies in prick_build.gemspec
|
|
6
6
|
gemspec
|
|
7
7
|
|
|
8
|
-
gem "rake", "~>
|
|
8
|
+
gem "rake", "~> 13.0"
|
|
9
9
|
gem "rspec", "~> 3.0"
|
|
10
|
+
|
|
11
|
+
gem 'shellopts', :github => 'clrgit/shellopts', branch: "master"
|
|
12
|
+
gem 'pg_graph', :github => 'clrgit/pg_graph', branch: "master"
|
|
13
|
+
gem 'pg_meta', :github => 'clrgit/pg_meta', branch: "master"
|
|
14
|
+
gem 'pg_conn', :github => 'clrgit/pg_conn', branch: "master"
|
|
15
|
+
|
data/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
#
|
|
1
|
+
# PrickBuild
|
|
2
2
|
|
|
3
|
-
Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/
|
|
3
|
+
Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/prick_build`. To experiment with that code, run `bin/console` for an interactive prompt.
|
|
4
4
|
|
|
5
5
|
TODO: Delete this and the text above, and describe your gem
|
|
6
6
|
|
|
@@ -9,16 +9,16 @@ TODO: Delete this and the text above, and describe your gem
|
|
|
9
9
|
Add this line to your application's Gemfile:
|
|
10
10
|
|
|
11
11
|
```ruby
|
|
12
|
-
gem '
|
|
12
|
+
gem 'prick_build'
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
And then execute:
|
|
16
16
|
|
|
17
|
-
$ bundle
|
|
17
|
+
$ bundle install
|
|
18
18
|
|
|
19
19
|
Or install it yourself as:
|
|
20
20
|
|
|
21
|
-
$ gem install
|
|
21
|
+
$ gem install prick_build
|
|
22
22
|
|
|
23
23
|
## Usage
|
|
24
24
|
|
|
@@ -28,8 +28,8 @@ TODO: Write usage instructions here
|
|
|
28
28
|
|
|
29
29
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
30
30
|
|
|
31
|
-
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and
|
|
31
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
|
32
32
|
|
|
33
33
|
## Contributing
|
|
34
34
|
|
|
35
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/
|
|
35
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/prick_build.
|
data/Rakefile
CHANGED
data/TODO
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
|
|
2
|
-
o
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
o
|
|
8
|
-
|
|
9
|
-
o
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
2
|
+
o Store fox.state, reflections, and reflections in the database so third-party
|
|
3
|
+
programs can use them when testing
|
|
4
|
+
o 'prick make <resource>' should build everything up the resource, then commit
|
|
5
|
+
before trying to build the resource upon the database. Then it is easy to
|
|
6
|
+
re-run the failed (sql-)script in psql to see why it failed
|
|
7
|
+
o 'prick make' should build everything up a touched file, then commit before
|
|
8
|
+
proceeding
|
|
9
|
+
o Build functions after schema so that there are no order dependencies on
|
|
10
|
+
functions. Problem is to detect function files
|
|
11
|
+
o Build views after schema so that there are no order dependencies on
|
|
12
|
+
views. Problem is to detect view files
|
|
13
13
|
|
|
14
|
+
+ prick release major|minor|patch
|
|
15
|
+
+ Check modification time of build.yml files too
|
data/bin/console
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
|
|
3
4
|
require "bundler/setup"
|
|
4
|
-
require "
|
|
5
|
+
require "prick_build"
|
|
5
6
|
|
|
6
7
|
# You can add fixtures and/or initialization code here to make experimenting
|
|
7
8
|
# with your gem easier. You can also use a different console, if you like.
|
data/doc/build-yml.txt
ADDED
data/exe/prick
CHANGED
|
@@ -1,39 +1,250 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
require 'prick/program.rb'
|
|
3
|
+
#$LOAD_PATH.unshift "/home/clr/prj/shellopts/lib"
|
|
5
4
|
|
|
6
|
-
require '
|
|
5
|
+
require 'bootsnap'
|
|
6
|
+
begin
|
|
7
|
+
cache_dir = "/run/user/" + `id -u`.chomp
|
|
8
|
+
Bootsnap.setup(
|
|
9
|
+
cache_dir: cache_dir, # Path to your cache
|
|
10
|
+
development_mode: true, # Current working environment, e.g. RACK_ENV, RAILS_ENV, etc
|
|
11
|
+
load_path_cache: true, # Optimize the LOAD_PATH with a cache
|
|
12
|
+
compile_cache_iseq: true, # Compile Ruby code into ISeq cache, breaks coverage reporting.
|
|
13
|
+
compile_cache_yaml: true # Compile YAML into a cache
|
|
14
|
+
)
|
|
15
|
+
Bootsnap.instrumentation = ->(event, path) { puts "#{event} #{path}" }
|
|
16
|
+
end
|
|
7
17
|
|
|
8
|
-
require '
|
|
18
|
+
require 'prick.rb'
|
|
19
|
+
require 'shellopts'
|
|
9
20
|
|
|
10
21
|
include ShellOpts
|
|
11
22
|
include Prick
|
|
12
23
|
|
|
24
|
+
TIME = false
|
|
13
25
|
|
|
14
26
|
SPEC = %(
|
|
15
|
-
|
|
16
|
-
Name of project. Defauls to the environment variable `PRICK_PROJECT` if
|
|
17
|
-
set and else the name of the current directory
|
|
18
|
-
|
|
19
|
-
-C,directory=DIR
|
|
20
|
-
Change to directory DIR before doing anything else
|
|
21
|
-
|
|
22
|
-
-h,help COMMAND...
|
|
23
|
-
Print this page
|
|
27
|
+
@ Prick project command
|
|
24
28
|
|
|
25
29
|
+v,verbose
|
|
26
|
-
Be verbose. Repeated
|
|
30
|
+
Be verbose. Repeated -v options increase the verbosity level
|
|
27
31
|
|
|
28
32
|
-q,quiet
|
|
29
33
|
Be quiet
|
|
30
34
|
|
|
31
|
-
|
|
32
|
-
|
|
35
|
+
-C,directory=EDIR
|
|
36
|
+
Change to directory DIR before doing anything else
|
|
37
|
+
|
|
38
|
+
-d,database=DATABASE
|
|
39
|
+
Override database name from prick.yml
|
|
40
|
+
|
|
41
|
+
-U,username=USERNAME
|
|
42
|
+
Override username from from prick.yml
|
|
43
|
+
|
|
44
|
+
version!
|
|
45
|
+
Print project version
|
|
46
|
+
|
|
47
|
+
init! -n,name=NAME -t,title=TITLE [DIRECTORY]
|
|
48
|
+
Initializes a prick project
|
|
49
|
+
|
|
50
|
+
setup!
|
|
51
|
+
Create the database user (if necessary) and an empty database
|
|
52
|
+
|
|
53
|
+
teardown!
|
|
54
|
+
Drop the database and the database user. TODO: Also run teardown scripts
|
|
55
|
+
|
|
56
|
+
create.data!
|
|
57
|
+
create.schema!
|
|
58
|
+
create.database!
|
|
59
|
+
create.users!
|
|
60
|
+
create.all!
|
|
61
|
+
Create an object. Fails if migration exist unless the --force flag is given
|
|
62
|
+
|
|
63
|
+
create.migration! -f,force -o,file=FILE -- VERSION
|
|
64
|
+
Create a migration from VERSION to the current and write it to
|
|
65
|
+
migration/VERSION. Fails if migration exist unless the --force flag is
|
|
66
|
+
given. If --file is given, the migration is written to FILE instead of
|
|
67
|
+
the migration directory. This doesn't require you to be on a release
|
|
68
|
+
branch and can be used to create ad-hoc migration scripts
|
|
69
|
+
|
|
70
|
+
drop! -- [KIND]
|
|
71
|
+
@ Drop objects
|
|
72
|
+
|
|
73
|
+
Kind can be 'users', 'data', 'schema', 'database' (the default), or 'all'. It is
|
|
74
|
+
not an error if the object doesn't exist. TODO Only 'users' is currently defined
|
|
75
|
+
|
|
76
|
+
build! -t,time --dump=KIND? -- [SCHEMA]
|
|
77
|
+
Build the project. If SCHEMA is defined, later schemas are excluded.
|
|
78
|
+
KIND can be 'nodes', 'allnodes' or 'batches' (the default)
|
|
79
|
+
|
|
80
|
+
make! -t,time --dump=KIND? -- [SCHEMA]
|
|
81
|
+
@ Only rebuild changed files
|
|
82
|
+
|
|
83
|
+
Checks file timestamps against the time of the last build and only
|
|
84
|
+
rebuild affected parts of the project. KIND can be 'nodes', 'allnodes' or
|
|
85
|
+
'batches'
|
|
86
|
+
|
|
87
|
+
fox! -- FILE...
|
|
88
|
+
Load fox file data. Data are reset to their initial state after build
|
|
89
|
+
before the fox data are loaded
|
|
90
|
+
|
|
91
|
+
release! -- KIND
|
|
92
|
+
Create a release of the given kind. KIND can be 'major', 'minor', or
|
|
93
|
+
'patch'. Release checks that the current repo is clean and up to date
|
|
94
|
+
with the origin
|
|
95
|
+
|
|
96
|
+
migrate! -f,file=FILE
|
|
97
|
+
Execute a migration
|
|
98
|
+
|
|
99
|
+
dump.type!
|
|
100
|
+
dump.data!
|
|
101
|
+
dump.schema!
|
|
102
|
+
dump.database!
|
|
103
|
+
TODO
|
|
104
|
+
|
|
105
|
+
dump.migration! --force -- VERSION
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
opts, args = ShellOpts.process(SPEC, ARGV, exception: true)
|
|
109
|
+
|
|
110
|
+
begin
|
|
111
|
+
# Handle verbose and quiet
|
|
112
|
+
$verbose = opts.verbose
|
|
113
|
+
$quiet = opts.quiet?
|
|
114
|
+
|
|
115
|
+
# Honor -C option
|
|
116
|
+
if opts.directory?
|
|
117
|
+
if File.exist?(opts.directory)
|
|
118
|
+
begin
|
|
119
|
+
Dir.chdir(opts.directory)
|
|
120
|
+
rescue Errno::ENOENT
|
|
121
|
+
raise Prick::Error, "Can't cd to '#{opts.directory}'"
|
|
122
|
+
end
|
|
123
|
+
else
|
|
124
|
+
raise Prick::Error, "Can't find directory: #{opts.directory}"
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Get subcommand
|
|
129
|
+
cmd = opts.subcommand!
|
|
130
|
+
|
|
131
|
+
# Process init command
|
|
132
|
+
if opts.subcommand == :init
|
|
133
|
+
dir, state = Prick::SubCommand.init(args.expect(0..1), cmd.name, cmd.title, opts.database, opts.username)
|
|
134
|
+
puts "Initialized prick project '#{state.name}' in #{dir}"
|
|
135
|
+
if opts.database.nil? || opts.username.nil?
|
|
136
|
+
puts
|
|
137
|
+
puts "Please check database/username in #{PRICK_CONTEXT_FILE}"
|
|
138
|
+
end
|
|
139
|
+
exit
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# Check state
|
|
143
|
+
File.exist?(PRICK_PROJECT_FILE) or raise Prick::Error, "Not in a prick project directory"
|
|
144
|
+
|
|
145
|
+
# Load state
|
|
146
|
+
Prick.state = State.load
|
|
147
|
+
|
|
148
|
+
# Handle -d and -U options
|
|
149
|
+
database = opts.database || Prick.state.database
|
|
150
|
+
username = opts.username || Prick.state.username
|
|
151
|
+
|
|
152
|
+
# Expect a sub-command
|
|
153
|
+
cmd = opts.subcommand! or raise Prick::Error, "Subcomand expected"
|
|
154
|
+
|
|
155
|
+
# Process subcommands
|
|
156
|
+
case opts.subcommand
|
|
157
|
+
when :version!
|
|
158
|
+
puts "#{Prick.state.name}-#{Prick.state.version}"
|
|
159
|
+
|
|
160
|
+
when :setup!
|
|
161
|
+
Prick::SubCommand.setup(database, username)
|
|
162
|
+
|
|
163
|
+
when :teardown!
|
|
164
|
+
Prick::SubCommand.teardown(database, username)
|
|
165
|
+
|
|
166
|
+
when :create!
|
|
167
|
+
create_command = opts.create!
|
|
168
|
+
case create_command.subcommand
|
|
169
|
+
when :migration
|
|
170
|
+
arg = args.expect(1)
|
|
171
|
+
version = PrickVersion.try(arg) or raise Prick::Error, "Illegal version: #{arg}"
|
|
172
|
+
Prick::SubCommand.create_migration(
|
|
173
|
+
username, version,
|
|
174
|
+
force: create_command.subcommand!.force?,
|
|
175
|
+
file: create_command.subcommand!.file)
|
|
176
|
+
else
|
|
177
|
+
raise NotImplementedError
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
when :build!
|
|
181
|
+
dump = cmd.dump("batches")&.to_sym
|
|
182
|
+
Prick::SubCommand.build(database, username, args.expect(0..1), timer: cmd.time?, dump: dump)
|
|
183
|
+
|
|
184
|
+
when :make!
|
|
185
|
+
dump = cmd.dump("batches")&.to_sym
|
|
186
|
+
Prick::SubCommand.make(database, username, args.expect(0..1), timer: cmd.time?, dump: dump)
|
|
187
|
+
|
|
188
|
+
when :fox!
|
|
189
|
+
Prick::SubCommand.fox(database, username, args)
|
|
33
190
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
191
|
+
when :drop!
|
|
192
|
+
case subject = args.expect(1).to_sym
|
|
193
|
+
when :all
|
|
194
|
+
Prick::SubCommand.drop_all(database)
|
|
195
|
+
when :users
|
|
196
|
+
Prick::SubCommand.drop_users(database)
|
|
197
|
+
when :database
|
|
198
|
+
Prick::SubCommand.drop_database(database)
|
|
199
|
+
when :data, :schema, :database, :all
|
|
200
|
+
raise NotImplementedError
|
|
201
|
+
else
|
|
202
|
+
raise Prick::Error, "Unknown subject: #{subject}"
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
when :release!
|
|
206
|
+
kind = args.expect(1).to_sym
|
|
207
|
+
constrain? kind, :major, :minor, :patch or
|
|
208
|
+
raise Prick::Fail, "Expected 'major', 'minor', or 'patch' argument, got '#{kind}'"
|
|
209
|
+
Prick::SubCommand.release(kind)
|
|
210
|
+
|
|
211
|
+
when :migrate!
|
|
212
|
+
args.expect(0)
|
|
213
|
+
Prick::SubCommand.migrate(database, username, file: cmd.file)
|
|
214
|
+
|
|
215
|
+
when :dump!
|
|
216
|
+
subject = cmd.subcommand!
|
|
217
|
+
case cmd.subcommand
|
|
218
|
+
when :migration
|
|
219
|
+
arg = args.expect(1)
|
|
220
|
+
version = PrickVersion.try(arg) or raise "Illegal version number: #{arg}"
|
|
221
|
+
Prick::SubCommand.create_migration(username, version, force: subject.force?, file: "/dev/stdout")
|
|
222
|
+
when :data, :schema, :database
|
|
223
|
+
raise NotImplementedError
|
|
224
|
+
else
|
|
225
|
+
raise Prick::Error, "Unknown subject: #{subject}"
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
else
|
|
229
|
+
raise Prick::Fail, "Internal error: Unhandled command - #{opts.subcommand.inspect}"
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
rescue ShellOpts::Failure, Prick::Fail, Prick::Build::PostgresError => ex
|
|
233
|
+
ShellOpts.failure(ex.message)
|
|
234
|
+
|
|
235
|
+
rescue ShellOpts::Error, Prick::Error => ex
|
|
236
|
+
ShellOpts.error(ex.message)
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
__END__
|
|
240
|
+
|
|
241
|
+
-n,name=NAME
|
|
242
|
+
Name of project. Defauls to the environment variable `PRICK_PROJECT` if
|
|
243
|
+
set and else the name of the current directory
|
|
244
|
+
|
|
245
|
+
init! -u,user=USER [NAME]
|
|
246
|
+
Initialize a project in the given directory. The USER is the postgres
|
|
247
|
+
user and defaults to the project name
|
|
37
248
|
|
|
38
249
|
info!
|
|
39
250
|
Print project information
|
|
@@ -160,6 +371,13 @@ SPEC = %(
|
|
|
160
371
|
in the var/spool directory
|
|
161
372
|
)
|
|
162
373
|
|
|
374
|
+
__END__
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
|
|
163
381
|
DEFAULT_STATE_FILE = "fox.state"
|
|
164
382
|
|
|
165
383
|
opts, args = ShellOpts.process(SPEC, ARGV)
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
module Prick
|
|
2
|
+
module Build
|
|
3
|
+
class BuildBatch
|
|
4
|
+
include Timer
|
|
5
|
+
|
|
6
|
+
attr_reader :builder
|
|
7
|
+
forward_to :builder, :conn
|
|
8
|
+
|
|
9
|
+
def kind() @nodes.first&.kind end
|
|
10
|
+
attr_reader :nodes
|
|
11
|
+
|
|
12
|
+
def initialize(builder)
|
|
13
|
+
@builder = builder
|
|
14
|
+
@nodes = []
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def execute(&block)
|
|
18
|
+
name = self.class.to_s.sub(/.*::/, "").split(/(?=[A-Z])/).map(&:downcase).join(" ")
|
|
19
|
+
time "Execute #{name} (nodes: #{nodes.size})" do
|
|
20
|
+
yield
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def dump
|
|
25
|
+
puts kind.upcase
|
|
26
|
+
indent { nodes.each(&:dump) }
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
class SqlBatch < BuildBatch
|
|
31
|
+
def execute
|
|
32
|
+
super {
|
|
33
|
+
begin
|
|
34
|
+
sql = []
|
|
35
|
+
if nodes.first.is_a?(ExeNode)
|
|
36
|
+
time "Execute script" do
|
|
37
|
+
sql = [nodes.first.source]
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
conn.execute sql + nodes[sql.size..-1].map(&:source)
|
|
41
|
+
|
|
42
|
+
rescue PG::SyntaxError, PG::Error => ex
|
|
43
|
+
error, line, pos = parse_pg_message(ex.message)
|
|
44
|
+
if line
|
|
45
|
+
if line < nodes.first.lines
|
|
46
|
+
node = nodes.first;
|
|
47
|
+
else
|
|
48
|
+
line -= nodes.first.lines
|
|
49
|
+
node = nodes[1..-1].find { |node|
|
|
50
|
+
line -= 1
|
|
51
|
+
if line < node.lines
|
|
52
|
+
line -= 2
|
|
53
|
+
true
|
|
54
|
+
else
|
|
55
|
+
line -= node.lines
|
|
56
|
+
false
|
|
57
|
+
end
|
|
58
|
+
}
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
if node.is_a?(SqlNode)
|
|
62
|
+
message = ["prick: #{error} in #{node.path}", line, pos].compact.join(":")
|
|
63
|
+
else
|
|
64
|
+
message = "prick: #{error} from #{node.path}"
|
|
65
|
+
end
|
|
66
|
+
else
|
|
67
|
+
raise
|
|
68
|
+
end
|
|
69
|
+
raise PostgresError.new(message)
|
|
70
|
+
end
|
|
71
|
+
}
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
private
|
|
75
|
+
# Returns [error, line, pos] tuple
|
|
76
|
+
def parse_pg_message(message)
|
|
77
|
+
message =~ /ERROR:\s*(.*?)\n(LINE (\d+): ).*?\n(\s*\^)/m or return nil
|
|
78
|
+
[$1, $3.to_i, $4.size - $2.size]
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
class ModuleBatch < BuildBatch
|
|
83
|
+
def execute
|
|
84
|
+
super {
|
|
85
|
+
nodes.each { |node|
|
|
86
|
+
sql = node&.call
|
|
87
|
+
conn.execute sql if sql
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
class FoxBatch < BuildBatch
|
|
94
|
+
# Inlining Fox instead of using command line program as it saves some deciseconds
|
|
95
|
+
def execute
|
|
96
|
+
t_type = t_fox = t_exe = nil
|
|
97
|
+
|
|
98
|
+
super {
|
|
99
|
+
timer = Timer.new "Execute fox batch (nodes: #{nodes.size}, clean: #{builder.clean})"
|
|
100
|
+
t_type = Timer.new " Load data model"
|
|
101
|
+
|
|
102
|
+
files = nodes.map(&:path)
|
|
103
|
+
|
|
104
|
+
# Load meta object
|
|
105
|
+
meta = PgMeta.new(conn)
|
|
106
|
+
|
|
107
|
+
# Create type object
|
|
108
|
+
type = PgGraph::Type.new(meta, builder.reflections_file)
|
|
109
|
+
|
|
110
|
+
t_type.stop
|
|
111
|
+
t_fox = Timer.new " Parse files"
|
|
112
|
+
|
|
113
|
+
# Create fox object
|
|
114
|
+
fox = FixtureFox::Fox.new(type)
|
|
115
|
+
|
|
116
|
+
# Parse files
|
|
117
|
+
for file in files
|
|
118
|
+
source, lines = fox.tokenize(file)
|
|
119
|
+
fox.parse(source, lines)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Analyze
|
|
123
|
+
fox.assign_types
|
|
124
|
+
fox.generate
|
|
125
|
+
|
|
126
|
+
# Dump state file
|
|
127
|
+
fox.write_state(FOX_STATE_PATH)
|
|
128
|
+
|
|
129
|
+
t_fox.stop
|
|
130
|
+
t_exe = Timer.new " Execute SQL"
|
|
131
|
+
|
|
132
|
+
delete = builder.clean ? :none : :touched
|
|
133
|
+
begin
|
|
134
|
+
conn.execute fox.to_sql(format: :exec, delete: delete)
|
|
135
|
+
conn.execute "update prick.versions set built_at = now() at time zone 'UTC'"
|
|
136
|
+
rescue PG::SyntaxError, PG::Error => ex
|
|
137
|
+
raise PostgresError, "prick: #{error} from #{node.path}"
|
|
138
|
+
end
|
|
139
|
+
}
|
|
140
|
+
t_type.emit
|
|
141
|
+
t_fox.emit
|
|
142
|
+
t_exe.emit
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
require 'local/command'
|
|
2
|
+
|
|
3
|
+
require 'builder/node.rb'
|
|
4
|
+
require 'builder/node_pool.rb'
|
|
5
|
+
require 'builder/batch.rb'
|
|
6
|
+
require 'builder/parser.rb'
|
|
7
|
+
|
|
8
|
+
include Constrain
|
|
9
|
+
|
|
10
|
+
module Prick
|
|
11
|
+
module Build
|
|
12
|
+
class Error < StandardError; end
|
|
13
|
+
class PostgresError < Error; end
|
|
14
|
+
|
|
15
|
+
class Builder
|
|
16
|
+
# PgConn object
|
|
17
|
+
attr_reader :conn
|
|
18
|
+
|
|
19
|
+
# Root schema directory
|
|
20
|
+
attr_reader :dir
|
|
21
|
+
|
|
22
|
+
# Reflections YAML file
|
|
23
|
+
attr_reader :reflections_file
|
|
24
|
+
|
|
25
|
+
# True if database is initially clean - ie. all tables are empty
|
|
26
|
+
attr_accessor :clean
|
|
27
|
+
|
|
28
|
+
# Root build node
|
|
29
|
+
attr_reader :root
|
|
30
|
+
|
|
31
|
+
# Pool of nodes. Initialized by #load_pool
|
|
32
|
+
attr_reader :pool
|
|
33
|
+
|
|
34
|
+
forward_to :pool, :nodes, :decl_nodes, :init_nodes, :term_nodes,
|
|
35
|
+
:seed_nodes, :fox_seed_nodes, :sql_seed_nodes,
|
|
36
|
+
:schemas
|
|
37
|
+
|
|
38
|
+
def batches() @batches ||= group end
|
|
39
|
+
|
|
40
|
+
def initialize(conn, dir, clean = true, touched: false)
|
|
41
|
+
@conn = conn
|
|
42
|
+
@dir = dir
|
|
43
|
+
@reflections_file = REFLECTIONS_PATH
|
|
44
|
+
@clean = clean
|
|
45
|
+
@pool = NodePool.new
|
|
46
|
+
@root = Parser.parse(conn, dir)
|
|
47
|
+
load_pool(@root) # Collect nodes into pool
|
|
48
|
+
@batches = nil # Initialized by #group
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Group sources into batches
|
|
52
|
+
def group
|
|
53
|
+
@batches = []
|
|
54
|
+
kind = nil
|
|
55
|
+
batch = nil
|
|
56
|
+
|
|
57
|
+
for node in [init_nodes, decl_nodes, fox_seed_nodes, sql_seed_nodes, term_nodes].flatten
|
|
58
|
+
case node.kind
|
|
59
|
+
when :module
|
|
60
|
+
if batch&.kind != :module
|
|
61
|
+
@batches << batch if batch
|
|
62
|
+
batch = ModuleBatch.new(self)
|
|
63
|
+
end
|
|
64
|
+
when :exe # Exe sources always create a new batch
|
|
65
|
+
@batches << batch if batch
|
|
66
|
+
batch = SqlBatch.new(self)
|
|
67
|
+
when batch&.kind
|
|
68
|
+
;
|
|
69
|
+
when :sql || node.kind == :inline
|
|
70
|
+
if batch&.kind != :exe
|
|
71
|
+
@batches << batch if batch
|
|
72
|
+
batch = SqlBatch.new(self)
|
|
73
|
+
end
|
|
74
|
+
when :inline
|
|
75
|
+
@batches << batch if batch
|
|
76
|
+
batch = SqlBatch.new(self)
|
|
77
|
+
when :fox
|
|
78
|
+
@batches << batch if batch
|
|
79
|
+
batch = FoxBatch.new(self)
|
|
80
|
+
when :yml
|
|
81
|
+
next
|
|
82
|
+
else
|
|
83
|
+
raise Error, "Unexpected node kind: #{node.kind}"
|
|
84
|
+
end
|
|
85
|
+
batch.nodes << node
|
|
86
|
+
end
|
|
87
|
+
@batches << batch if batch
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def execute(conn, create_schemas: schemas)
|
|
91
|
+
group if batches.nil?
|
|
92
|
+
conn.exec create_schemas.grep_v("public").map { |schema| "create schema #{schema}" }
|
|
93
|
+
for batch in batches
|
|
94
|
+
batch.execute
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# def setup
|
|
99
|
+
# end
|
|
100
|
+
|
|
101
|
+
# def teardown
|
|
102
|
+
# end
|
|
103
|
+
|
|
104
|
+
def dump
|
|
105
|
+
batches ? batches.each(&:dump) : pool.dump
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
private
|
|
109
|
+
def load_pool(build_node)
|
|
110
|
+
pool.add(build_node.init_nodes)
|
|
111
|
+
build_node.decl_nodes.each { |node|
|
|
112
|
+
pool.add node
|
|
113
|
+
load_pool(node) if node.kind == :yml
|
|
114
|
+
}
|
|
115
|
+
pool.add(build_node.seed_nodes)
|
|
116
|
+
pool.add(build_node.term_nodes)
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
|