prick 0.33.0 → 0.35.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 +4 -4
- data/TODO +1 -0
- data/exe/prick +29 -11
- data/lib/prick/builder/batch.rb +8 -12
- data/lib/prick/builder/builder.rb +46 -15
- data/lib/prick/builder/node.rb +9 -2
- data/lib/prick/builder/parser.rb +86 -60
- data/lib/prick/environment.rb +1 -2
- data/lib/prick/state.rb +4 -1
- data/lib/prick/subcommand/prick-build.rb +6 -5
- data/lib/prick/subcommand/prick-make.rb +6 -6
- data/lib/prick/subcommand/prick-run.rb +113 -0
- data/lib/prick/version.rb +1 -1
- data/lib/prick.rb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b8acf851da65b094d2abab5a6d9469f20a974732b9e8a8f5bbc4542f72bf8dae
|
4
|
+
data.tar.gz: d7ce7beb146b47aea6f25a93771b206a41434bd2ecbd3a1df33b8580374e29ea
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b861e5129259bcb0dd384ba7e3c2db09c826cd50105ec514bda309268779e56458a99a3ef8ca1b83226accf7ce6569b957790e5c4374473a3cfb3700ba5ef380
|
7
|
+
data.tar.gz: 6c1b7227ffa63e49825f4acb503d855b9110f18224c1b3f2f7b27b72a92ac0eb3865ea8926470995a71988cb64ab9aa4a5bb26420adafd152364fd31ee28d23a
|
data/TODO
CHANGED
data/exe/prick
CHANGED
@@ -119,20 +119,27 @@ SPEC = %(
|
|
119
119
|
|
120
120
|
TODO
|
121
121
|
|
122
|
-
build! -f,force -t,time --dump=KIND? -- [SCHEMA]
|
123
|
-
Build the project. If SCHEMA is defined, later schemas are excluded.
|
124
|
-
|
122
|
+
build! --step -f,force -t,time --dump=KIND? -- [SCHEMA]
|
123
|
+
Build the project. If SCHEMA is defined, later schemas are excluded. KIND
|
124
|
+
can be 'nodes', 'allnodes' or 'batches' (the default). Schemas marked
|
125
|
+
with 'no refresh' is not built unless the --force is present
|
125
126
|
|
126
|
-
|
127
|
-
present
|
128
|
-
|
129
|
-
make! -t,time --dump=KIND? -- [SCHEMA]
|
127
|
+
make! --step -t,time --dump=KIND? -- [SCHEMA]
|
130
128
|
@ Only rebuild changed files
|
131
129
|
|
132
130
|
Checks file timestamps against the time of the last build and only
|
133
131
|
rebuild affected parts of the project. KIND can be 'nodes', 'allnodes' or
|
134
132
|
'batches' (the default)
|
135
133
|
|
134
|
+
run! --step -t,time --dump=KIND? --schema=SCHEMA -- PATH
|
135
|
+
@ Execute path in Prick environment
|
136
|
+
|
137
|
+
Execute a single directory or file within the Prick environment. If given
|
138
|
+
a directory argument, the directory is searched for a build.yml file. If
|
139
|
+
given a file argument, the file should be a .sql, .fox, or build file
|
140
|
+
|
141
|
+
The --schema option sets the current schema before executing the PATH
|
142
|
+
|
136
143
|
bash! --main
|
137
144
|
Emit a bash script to build the database. The script is constructed from
|
138
145
|
the build attributes in the environment file
|
@@ -354,12 +361,22 @@ begin
|
|
354
361
|
dump = cmd.dump? ? cmd.dump("batches")&.to_sym || :batches : nil
|
355
362
|
# exclude = cmd.exclude? ? cmd.exclude.split(",") : []
|
356
363
|
Prick::SubCommand.build(
|
357
|
-
database, username, args.expect(0..1),
|
364
|
+
database, username, args.expect(0..1),
|
365
|
+
force: cmd.force?, step: cmd.step?, timer: cmd.time?, dump: dump)
|
358
366
|
|
359
367
|
when :make!
|
360
368
|
require_db
|
361
369
|
dump = cmd.dump? ? cmd.dump("batches")&.to_sym || :batches : nil
|
362
|
-
Prick::SubCommand.make(
|
370
|
+
Prick::SubCommand.make(
|
371
|
+
database, username, args.expect(0..1),
|
372
|
+
step: cmd.step?, timer: cmd.time?, dump: dump)
|
373
|
+
|
374
|
+
when :run!
|
375
|
+
require_db
|
376
|
+
dump = cmd.dump? ? cmd.dump("batches")&.to_sym || :batches : nil
|
377
|
+
Prick::SubCommand.run(
|
378
|
+
database, username, args.expect(1),
|
379
|
+
step: cmd.step?, timer: cmd.time?, dump: dump, schema: cmd.schema)
|
363
380
|
|
364
381
|
when :bash!
|
365
382
|
Prick::SubCommand.bash(main: cmd.main?)
|
@@ -479,7 +496,8 @@ rescue ShellOpts::Error, Prick::Error => ex
|
|
479
496
|
raise
|
480
497
|
ShellOpts.error(ex.message)
|
481
498
|
|
482
|
-
|
483
|
-
|
499
|
+
# FIXME
|
500
|
+
#rescue RuntimeError, IOError, ShellOpts::Failure, Prick::Failure, Prick::Build::PostgresError => ex
|
501
|
+
# ShellOpts.failure(ex.message)
|
484
502
|
end
|
485
503
|
|
data/lib/prick/builder/batch.rb
CHANGED
@@ -28,7 +28,8 @@ module Prick
|
|
28
28
|
end
|
29
29
|
|
30
30
|
class SqlBatch < BuildBatch
|
31
|
-
def execute
|
31
|
+
def execute
|
32
|
+
# puts "#execute"
|
32
33
|
super {
|
33
34
|
begin
|
34
35
|
sql = []
|
@@ -41,22 +42,16 @@ module Prick
|
|
41
42
|
sql = [node.source]
|
42
43
|
end
|
43
44
|
|
44
|
-
if
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
end
|
49
|
-
else
|
50
|
-
node = nil
|
51
|
-
conn.execute sql + nodes[sql.size..-1].map(&:source), silent: true
|
45
|
+
conn.execute sql, silent: true if !sql.empty?
|
46
|
+
for node in nodes # This is marginally faster than concatenating all nodes
|
47
|
+
# puts node.source
|
48
|
+
conn.execute node.source, silent: true
|
52
49
|
end
|
53
50
|
|
54
51
|
rescue PG::Error => ex
|
55
52
|
error, line, char = conn.err
|
56
53
|
file = nil
|
57
|
-
if
|
58
|
-
;
|
59
|
-
elsif line
|
54
|
+
if line
|
60
55
|
# Locate error node and make line number relative
|
61
56
|
if line < nodes.first.lines
|
62
57
|
node = nodes.first
|
@@ -81,6 +76,7 @@ module Prick
|
|
81
76
|
elsif node
|
82
77
|
message = "#{error} from #{node.path}"
|
83
78
|
else
|
79
|
+
raise ArgumentError, "Oops"
|
84
80
|
message = conn.errmsg + " in SQL batch"
|
85
81
|
end
|
86
82
|
raise PostgresError.new(message, file, line, char)
|
@@ -27,9 +27,12 @@ module Prick
|
|
27
27
|
# PgConn object
|
28
28
|
attr_reader :conn
|
29
29
|
|
30
|
-
#
|
30
|
+
# Schema directory
|
31
31
|
attr_reader :dir
|
32
32
|
|
33
|
+
# Path to file or directory
|
34
|
+
attr_reader :path
|
35
|
+
|
33
36
|
# Reflections YAML file
|
34
37
|
attr_reader :reflections_file
|
35
38
|
|
@@ -39,6 +42,12 @@ module Prick
|
|
39
42
|
# Root build node
|
40
43
|
attr_reader :root
|
41
44
|
|
45
|
+
# True if this is a single-file build
|
46
|
+
attr_reader :single
|
47
|
+
|
48
|
+
# True if SQL entries should be single-stepped. Default false
|
49
|
+
attr_reader :step
|
50
|
+
|
42
51
|
# Pool of nodes. Initialized by #load_pool
|
43
52
|
attr_reader :pool
|
44
53
|
|
@@ -49,21 +58,31 @@ module Prick
|
|
49
58
|
:pg_graph_ignore_schemas,
|
50
59
|
:refresh_schemas, :keep_schemas
|
51
60
|
|
52
|
-
def batches() @batches
|
61
|
+
def batches() @batches || create_batches end
|
62
|
+
|
63
|
+
def initialize(conn, path, clean = true, single: false, touched: false, load_pool: true, step: false)
|
64
|
+
File.exist?(path) or raise Error, "Can't find #{path}"
|
65
|
+
single || File.directory?(path) or raise Error, "Can't find directory #{path}"
|
53
66
|
|
54
|
-
def initialize(conn, dir, clean = true, touched: false)
|
55
67
|
@conn = conn
|
56
|
-
@
|
68
|
+
@path = path
|
57
69
|
@reflections_file = REFLECTIONS_PATH
|
58
70
|
@clean = clean
|
71
|
+
@single = single
|
72
|
+
@step = step
|
73
|
+
@root = Parser.parse(conn, path, single: single)
|
74
|
+
@pool = nil # Initialized by #load_pool
|
75
|
+
@batches = nil # Initialized by #create_batches
|
76
|
+
self.load_pool if load_pool
|
77
|
+
end
|
78
|
+
|
79
|
+
def load_pool
|
59
80
|
@pool = NodePool.new
|
60
|
-
@root
|
61
|
-
load_pool(@root) # Collect nodes into pool
|
62
|
-
@batches = nil # Initialized by #group
|
81
|
+
load_pool_impl(@root)
|
63
82
|
end
|
64
83
|
|
65
84
|
# Group sources into batches
|
66
|
-
def
|
85
|
+
def create_batches
|
67
86
|
@batches = []
|
68
87
|
kind = nil
|
69
88
|
batch = nil
|
@@ -78,8 +97,11 @@ module Prick
|
|
78
97
|
when :exe # Exe sources always create a new batch
|
79
98
|
@batches << batch if batch
|
80
99
|
batch = SqlBatch.new(self)
|
81
|
-
when batch&.kind
|
82
|
-
|
100
|
+
when batch&.kind # Same kind as current batch
|
101
|
+
if node.kind == :sql && step
|
102
|
+
@batches << batch if batch
|
103
|
+
batch = SqlBatch.new(self)
|
104
|
+
end
|
83
105
|
when :sql || node.kind == :inline
|
84
106
|
if batch&.kind != :exe
|
85
107
|
@batches << batch if batch
|
@@ -98,22 +120,30 @@ module Prick
|
|
98
120
|
end
|
99
121
|
batch.nodes << node
|
100
122
|
end
|
101
|
-
|
102
123
|
@batches << batch if batch
|
124
|
+
|
125
|
+
@batches
|
103
126
|
end
|
104
127
|
|
105
128
|
def execute(conn, create_schemas: schemas)
|
129
|
+
# Load pool
|
130
|
+
load_pool if pool.nil?
|
131
|
+
|
106
132
|
# Group batches
|
107
|
-
|
133
|
+
create_batches if batches.nil?
|
108
134
|
|
109
135
|
# Register build in database
|
110
136
|
Prick.state.save_build_begin
|
111
137
|
|
112
138
|
# Create schemas
|
113
|
-
conn.exec create_schemas.map { |schema| "create schema #{schema}" }
|
139
|
+
conn.exec create_schemas.map { |schema| "create schema #{schema}" } if !single
|
114
140
|
|
115
141
|
# Execute batch groups
|
116
142
|
t0 = Time.now
|
143
|
+
# for batch in batches
|
144
|
+
# puts "Executing #{batch.class} batch"
|
145
|
+
# batch.execute
|
146
|
+
# end
|
117
147
|
batches.each(&:execute)
|
118
148
|
t1 = Time.now
|
119
149
|
|
@@ -123,15 +153,16 @@ module Prick
|
|
123
153
|
end
|
124
154
|
|
125
155
|
def dump
|
156
|
+
load_pool if pool.nil?
|
126
157
|
batches ? batches.each(&:dump) : pool.dump
|
127
158
|
end
|
128
159
|
|
129
160
|
private
|
130
|
-
def
|
161
|
+
def load_pool_impl(build_node)
|
131
162
|
pool.add(build_node.init_nodes)
|
132
163
|
build_node.decl_nodes.each { |node|
|
133
164
|
pool.add node
|
134
|
-
|
165
|
+
load_pool_impl(node) if node.kind == :yml
|
135
166
|
}
|
136
167
|
pool.add(build_node.seed_nodes)
|
137
168
|
pool.add(build_node.term_nodes)
|
data/lib/prick/builder/node.rb
CHANGED
@@ -10,6 +10,8 @@ module Prick
|
|
10
10
|
|
11
11
|
def name() @name = File.basename(path) end
|
12
12
|
|
13
|
+
# Note that schema defaults to 'public' which may not be what you want in
|
14
|
+
# some cases
|
13
15
|
def schema() @schema ||= parent&.schema || "public" end
|
14
16
|
def schema=(s) @schema = s end
|
15
17
|
|
@@ -36,6 +38,7 @@ module Prick
|
|
36
38
|
constrain path, String, NilClass
|
37
39
|
@parent, @phase, @kind, @path = parent, phase, kind, path
|
38
40
|
@args = args&.empty? ? nil : args
|
41
|
+
@has_schema = false
|
39
42
|
@schema = nil
|
40
43
|
@source = nil
|
41
44
|
@source_lines = nil
|
@@ -43,7 +46,7 @@ module Prick
|
|
43
46
|
|
44
47
|
def to_s() @to_s ||= [path, args].compact.join(" ") end
|
45
48
|
def inspect() to_s end
|
46
|
-
def dump() puts "#{inspect} (#{schema})" end
|
49
|
+
def dump() puts "#{inspect} (#{@schema || 'nil'})" end
|
47
50
|
|
48
51
|
protected
|
49
52
|
def read_source
|
@@ -162,6 +165,9 @@ module Prick
|
|
162
165
|
|
163
166
|
# A build.yml file node
|
164
167
|
class BuildNode < Node
|
168
|
+
# True if the build file contains a 'schema' attribute
|
169
|
+
attr_accessor :has_schema
|
170
|
+
|
165
171
|
def nodes() @nodes ||= init_nodes + decl_nodes + seed_nodes + term_nodes end
|
166
172
|
|
167
173
|
attr_reader :decl_nodes
|
@@ -187,7 +193,8 @@ module Prick
|
|
187
193
|
def dump
|
188
194
|
puts "BuildNode #{path}"
|
189
195
|
indent {
|
190
|
-
puts "
|
196
|
+
puts "has_schema: #{has_schema}"
|
197
|
+
puts "schema: #{@schema || 'nil'}"
|
191
198
|
puts "refresh: #{refresh_schema.to_s}"
|
192
199
|
puts "pg_graph_ignore_schema: #{pg_graph_ignore_schema}"
|
193
200
|
decl_nodes.each(&:dump)
|
data/lib/prick/builder/parser.rb
CHANGED
@@ -1,30 +1,30 @@
|
|
1
1
|
module Prick
|
2
2
|
module Build
|
3
3
|
class Parser
|
4
|
-
def self.parse(conn,
|
5
|
-
Parser.new(conn).parse(
|
6
|
-
# [parser.unit, parser.schemas]
|
4
|
+
def self.parse(conn, path, single: true)
|
5
|
+
Parser.new(conn).parse(path, single: single).unit
|
7
6
|
end
|
8
7
|
|
9
8
|
attr_reader :conn
|
10
|
-
attr_reader :dir
|
11
9
|
attr_reader :unit # The singular RootBuildNode object
|
12
|
-
# attr_reader :schemas
|
13
10
|
|
14
11
|
def initialize(conn)
|
15
12
|
@conn = conn
|
16
13
|
@unit = nil
|
17
14
|
end
|
18
15
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
16
|
+
# Return a RootBuildNode object. #path can be a file or a directory
|
17
|
+
def parse(path, single: false)
|
18
|
+
File.exist?(path) or raise Error, "Can't find #{path}"
|
19
|
+
if single
|
20
|
+
parse_path(path)
|
21
|
+
else
|
22
|
+
parse_directory(nil, path)
|
23
|
+
end
|
23
24
|
self
|
24
25
|
end
|
25
26
|
|
26
27
|
private
|
27
|
-
|
28
28
|
# First built unit is a RootBuildNode, the rest are regular BuildNode objects
|
29
29
|
def make_build_unit(parent, path)
|
30
30
|
if @unit
|
@@ -34,47 +34,14 @@ module Prick
|
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
# Expand environments variables file name. Iterates through inherited
|
47
|
-
# environments if the file name contain the $ENVIRONMENT variable. Return
|
48
|
-
# nil if not found
|
49
|
-
#
|
50
|
-
# The hierarchy of environments is defined in the PRICK_ENVIRONMENT_FILE
|
51
|
-
#
|
52
|
-
def expand_filename(dir, filename)
|
53
|
-
envs = Prick.state.environments
|
54
|
-
env = envs[Prick.state.environment]
|
55
|
-
bash_vars = Prick.state.bash_environment
|
56
|
-
|
57
|
-
last = nil
|
58
|
-
for env in [env] + env.ancestors.reverse
|
59
|
-
bash_vars["ENVIRONMENT"] = env.name
|
60
|
-
file = expand_variables(filename, bash_vars)
|
61
|
-
last ||= (file != last and file) or return nil # return if no ENVIRONMENT substitution
|
62
|
-
path = (file.start_with?("/") ? file : File.join(dir, file))
|
63
|
-
|
64
|
-
# Check for file (may be executable)
|
65
|
-
return path if File.exist?(path)
|
66
|
-
|
67
|
-
# Check for executable in search path
|
68
|
-
path = find_executable(file) and return path if file !~ /\//
|
69
|
-
end
|
70
|
-
|
71
|
-
# Return nil if not found
|
72
|
-
return nil
|
73
|
-
end
|
74
|
-
|
75
|
-
# Expand $ENVIRONMENT variable
|
76
|
-
def expand_string(string)
|
77
|
-
expand_variables(string, Prick.state.bash_environment)
|
37
|
+
def parse_path(path, schema: nil)
|
38
|
+
File.exist?(path) or raise Error, "Can't find #{file}"
|
39
|
+
dir = File.dirname(path)
|
40
|
+
file = File.basename(path)
|
41
|
+
unit = make_build_unit(nil, nil)
|
42
|
+
unit.schema = schema if schema
|
43
|
+
entry = parse_build_entry(unit, dir, file)
|
44
|
+
unit
|
78
45
|
end
|
79
46
|
|
80
47
|
def parse_directory(parent, dir)
|
@@ -82,7 +49,7 @@ module Prick
|
|
82
49
|
if File.exist? build_file
|
83
50
|
parse_build_file(parent, dir, build_file)
|
84
51
|
else
|
85
|
-
raise Error, "Can't find build.yml in #{dir}"
|
52
|
+
raise Error, "Can't find build.yml in #{dir} while parsing #{parent}"
|
86
53
|
end
|
87
54
|
end
|
88
55
|
|
@@ -94,6 +61,7 @@ module Prick
|
|
94
61
|
entry.each { |key, value|
|
95
62
|
if key == "schema"
|
96
63
|
unit.schema = value
|
64
|
+
unit.has_schema = true
|
97
65
|
elsif key == "standard"
|
98
66
|
unit.pg_graph_ignore_schema = !value
|
99
67
|
elsif key == "refresh"
|
@@ -109,17 +77,22 @@ module Prick
|
|
109
77
|
end
|
110
78
|
}
|
111
79
|
else
|
112
|
-
|
113
|
-
if node.kind == :fox
|
114
|
-
unit.seed_nodes << node
|
115
|
-
else
|
116
|
-
unit.decl_nodes << node
|
117
|
-
end
|
80
|
+
parse_build_entry(unit, dir, entry)
|
118
81
|
end
|
119
82
|
}
|
120
83
|
unit
|
121
84
|
end
|
122
85
|
|
86
|
+
def parse_build_entry(unit, dir, file)
|
87
|
+
node = parse_entry(unit, :decl, dir, file) or return nil
|
88
|
+
if node.kind == :fox
|
89
|
+
unit.seed_nodes << node
|
90
|
+
else
|
91
|
+
unit.decl_nodes << node
|
92
|
+
end
|
93
|
+
node
|
94
|
+
end
|
95
|
+
|
123
96
|
# Returns path, filename, and an array of arguments. It is an error if
|
124
97
|
# the file can't be found unless #optional is true. In that case a nil
|
125
98
|
# value is returned
|
@@ -132,7 +105,7 @@ module Prick
|
|
132
105
|
args = expand_string(rest || '').split
|
133
106
|
path = expand_filename(dir, command)
|
134
107
|
path || optional or
|
135
|
-
raise Error, "Can't find file
|
108
|
+
raise Error, "Can't find file #{command} #{path} in #{dir}/ from #{unit}"
|
136
109
|
!path.nil? or return nil
|
137
110
|
else
|
138
111
|
raise Error, "Not a file name: '#{entry}'"
|
@@ -141,6 +114,7 @@ module Prick
|
|
141
114
|
end
|
142
115
|
|
143
116
|
def parse_entry(unit, phase, dir, entry)
|
117
|
+
# puts "#parse_entry(#{unit.inspect}, #{phase.inspect}, #{dir.inspect}, #{entry.inspect})"
|
144
118
|
if entry.is_a?(Hash)
|
145
119
|
entry.size == 1 or raise Error, "sql and module are single-line values"
|
146
120
|
key, value = entry.first
|
@@ -175,7 +149,9 @@ module Prick
|
|
175
149
|
SqlNode.new(unit, phase, path)
|
176
150
|
when /\.fox$/
|
177
151
|
FoxNode.new(unit, :seed, path)
|
178
|
-
when /build-.*\.yml$/
|
152
|
+
when /(?:^|\/)build-.*\.yml$/
|
153
|
+
parse_build_file(unit, dir, path)
|
154
|
+
when /(?:^|\/)build.yml$/ # Only used when building a single file
|
179
155
|
parse_build_file(unit, dir, path)
|
180
156
|
else
|
181
157
|
raise Error, "Expected executable, fox, or sql file: #{File.basename(path)} in #{dir}"
|
@@ -185,6 +161,56 @@ module Prick
|
|
185
161
|
end
|
186
162
|
end
|
187
163
|
end
|
164
|
+
|
165
|
+
# Search for an executable in path. Return nil if not found
|
166
|
+
#
|
167
|
+
# Note that "." is ignored in the search path
|
168
|
+
def find_executable(filename) # ChatGPT
|
169
|
+
Prick.state.executable_search_path.split(File::PATH_SEPARATOR).each do |directory|
|
170
|
+
next if directory == "."
|
171
|
+
path = File.join(directory, filename)
|
172
|
+
return path if File.file?(path) && File.executable?(path)
|
173
|
+
end
|
174
|
+
nil
|
175
|
+
end
|
176
|
+
|
177
|
+
# Expand environment variables in the given file name
|
178
|
+
#
|
179
|
+
# #expend_filename substitute '$<variable>' expressions in the filename
|
180
|
+
# with the corresponding value in the current environment. If the file
|
181
|
+
# was not found, inherited environments are processed hierarchly with the
|
182
|
+
# special environment variable ENVIRONMENT set to each PRICK_ENVIRONMENT
|
183
|
+
# value in the inherited environments
|
184
|
+
#
|
185
|
+
# Return the resulting path to the file and nil if not found
|
186
|
+
#
|
187
|
+
def expand_filename(dir, filename)
|
188
|
+
envs = Prick.state.environments
|
189
|
+
env = envs[Prick.state.environment]
|
190
|
+
bash_vars = Prick.state.bash_environment.dup
|
191
|
+
|
192
|
+
last = nil
|
193
|
+
for env in [env] + env.ancestors.reverse
|
194
|
+
bash_vars["ENVIRONMENT"] = env.name
|
195
|
+
file = expand_variables(filename, bash_vars)
|
196
|
+
# last ||= (file != last and file) or return nil # return if no ENVIRONMENT substitution
|
197
|
+
path = (file.start_with?("/") ? file : File.join(dir, file))
|
198
|
+
|
199
|
+
# Check for file (may be executable)
|
200
|
+
return path if File.exist?(path)
|
201
|
+
|
202
|
+
# Check for executable in search path if file doesn't contain a '/'
|
203
|
+
path = find_executable(file) and return path if file !~ /\//
|
204
|
+
end
|
205
|
+
|
206
|
+
# Return nil if not found
|
207
|
+
return nil
|
208
|
+
end
|
209
|
+
|
210
|
+
# Expand $ENVIRONMENT variable
|
211
|
+
def expand_string(string)
|
212
|
+
expand_variables(string, Prick.state.bash_environment)
|
213
|
+
end
|
188
214
|
end
|
189
215
|
end
|
190
216
|
end
|
data/lib/prick/environment.rb
CHANGED
@@ -245,13 +245,12 @@ module Prick
|
|
245
245
|
case types[ident]
|
246
246
|
when "BOOLEAN"
|
247
247
|
[TrueClass, FalseClass].include?(value.class) or raise "Illegal value for #{ident}: #{value}"
|
248
|
-
;
|
249
248
|
when "STRING"
|
250
249
|
; # nop
|
251
250
|
when "LIST"
|
252
251
|
value = value&.split || []
|
253
252
|
when "TEXT"
|
254
|
-
value = value.chomp
|
253
|
+
value = (value == false ? "false" : value.chomp)
|
255
254
|
when nil
|
256
255
|
ShellOpts.error "Unknown variable '#{ident}'"
|
257
256
|
else
|
data/lib/prick/state.rb
CHANGED
@@ -14,6 +14,9 @@ module Prick
|
|
14
14
|
# directory through the -C option or the 'init' command
|
15
15
|
def prick_dir() @prick_dir ||= Dir.getwd end
|
16
16
|
|
17
|
+
# Prick schema dir
|
18
|
+
def schema_dir() @schema_dir ||= File.join(prick_dir, SCHEMA_DIR) end
|
19
|
+
|
17
20
|
# Project file. Default 'prick.yml'
|
18
21
|
attr_reader :project_file
|
19
22
|
|
@@ -186,7 +189,7 @@ module Prick
|
|
186
189
|
hash.merge!({
|
187
190
|
"DATABASE" => Prick.state.database, # FIXME: Yt
|
188
191
|
"USERNAME" => Prick.state.username, # FIXME: Yt
|
189
|
-
"ENVIRONMENT" => Prick.state.environment.to_s, # FIXME: Yt
|
192
|
+
"ENVIRONMENT" => Prick.state.environment.to_s, # FIXME: Yt except in build.yml parser
|
190
193
|
"PRICK_NAME" => Prick.state.name,
|
191
194
|
"PRICK_TITLE" => Prick.state.title,
|
192
195
|
"PRICK_VERSION" => Prick.state.version,
|
@@ -5,8 +5,9 @@ require_relative '../builder/builder.rb'
|
|
5
5
|
module Prick::SubCommand
|
6
6
|
def self.build(
|
7
7
|
database, username, schema,
|
8
|
-
builddir:
|
9
|
-
|
8
|
+
builddir: Prick.state.schema_dir,
|
9
|
+
force: false, # Build all schemas
|
10
|
+
step: false, timer: nil, dump: nil)
|
10
11
|
|
11
12
|
Timer.on! if timer
|
12
13
|
|
@@ -29,7 +30,7 @@ module Prick::SubCommand
|
|
29
30
|
end
|
30
31
|
conn = Prick.state.connection
|
31
32
|
|
32
|
-
builder = Prick::Build::Builder.new(conn, builddir)
|
33
|
+
builder = Prick::Build::Builder.new(conn, builddir, step: step)
|
33
34
|
|
34
35
|
if exist # Empty (part of) the database
|
35
36
|
if force
|
@@ -49,8 +50,8 @@ module Prick::SubCommand
|
|
49
50
|
# Remove keep-schemas from list of schemas
|
50
51
|
refresh_schemas -= keep_schemas
|
51
52
|
|
52
|
-
# Also remove keep-schemas from the build pool. Why don't we
|
53
|
-
# the pool tracker's list of keep schemas?
|
53
|
+
# Also remove keep-schemas from the build pool. TODO Why don't we
|
54
|
+
# use the pool tracker's list of keep schemas?
|
54
55
|
builder.pool.delete_schema(keep_schemas)
|
55
56
|
|
56
57
|
# Drop refresh schemes
|
@@ -3,9 +3,9 @@
|
|
3
3
|
require_relative '../builder/builder.rb'
|
4
4
|
|
5
5
|
module Prick::SubCommand
|
6
|
-
def self.make(database, username, schema, timer: nil, dump: nil)
|
6
|
+
def self.make(database, username, schema, step: false, timer: nil, dump: nil)
|
7
7
|
Timer.on! if timer
|
8
|
-
time "Prick::Command#make" do
|
8
|
+
Timer.time "Prick::Command#make" do
|
9
9
|
begin
|
10
10
|
super_conn = State.connection
|
11
11
|
conn = nil
|
@@ -14,7 +14,7 @@ module Prick::SubCommand
|
|
14
14
|
clean = false
|
15
15
|
create_schemas = []
|
16
16
|
|
17
|
-
time "Load build object" do
|
17
|
+
Timer.time "Load build object" do
|
18
18
|
if super_conn.rdbms.exist? database
|
19
19
|
conn = Prick.state.connection
|
20
20
|
if conn.schema.exist_relation?("prick", "versions") && !conn.empty?("prick.versions")
|
@@ -26,7 +26,7 @@ module Prick::SubCommand
|
|
26
26
|
clean = true
|
27
27
|
end
|
28
28
|
|
29
|
-
builder = Prick::Build::Builder.new(conn, "schema", clean)
|
29
|
+
builder = Prick::Build::Builder.new(conn, "schema", clean, step: step)
|
30
30
|
|
31
31
|
if schema
|
32
32
|
after_schemas = builder.pool.after_schema(schema)
|
@@ -43,7 +43,7 @@ module Prick::SubCommand
|
|
43
43
|
after_schemas.each { |delete_schema| builder.pool.delete_schema(delete_schema) }
|
44
44
|
end
|
45
45
|
|
46
|
-
touched_nodes = builder.nodes.select { |node| File.mtime(node.path) > last_built_at }
|
46
|
+
touched_nodes = builder.nodes.select { |node| last_built_at.nil? || File.mtime(node.path) > last_built_at }
|
47
47
|
touched_phases = touched_nodes.map(&:phase).uniq.compact
|
48
48
|
touched_kinds = touched_nodes.map(&:kind).uniq.compact
|
49
49
|
touched_schema = touched_nodes.first&.schema
|
@@ -78,7 +78,7 @@ module Prick::SubCommand
|
|
78
78
|
end
|
79
79
|
exit if dump
|
80
80
|
|
81
|
-
time "Execute build object" do
|
81
|
+
Timer.time "Execute build object" do
|
82
82
|
builder.execute(conn, create_schemas: create_schemas)
|
83
83
|
end
|
84
84
|
|
@@ -0,0 +1,113 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require_relative '../builder/builder.rb'
|
4
|
+
|
5
|
+
module Prick::SubCommand
|
6
|
+
def self.run(database, username, path, step: false, timer: nil, dump: nil, schema: nil)
|
7
|
+
|
8
|
+
Timer.on! if timer
|
9
|
+
|
10
|
+
Timer.time "Prick::Command#build" do
|
11
|
+
begin
|
12
|
+
super_conn = State.connection # Used to create new databases (doesn't make a
|
13
|
+
# difference right now as the database user is
|
14
|
+
# a superuser anyway
|
15
|
+
conn = nil
|
16
|
+
builder = nil
|
17
|
+
|
18
|
+
constrain super_conn.rdbms.exist?(database), true # FIXME Same problem as below. Also in other commands
|
19
|
+
|
20
|
+
Timer.time "Load build object" do
|
21
|
+
if super_conn.rdbms.exist? database # FIXME Why create database? Setup should have done this
|
22
|
+
exist = true
|
23
|
+
else
|
24
|
+
super_conn.rdbms.create database, owner: username
|
25
|
+
exist = false
|
26
|
+
end
|
27
|
+
conn = Prick.state.connection
|
28
|
+
|
29
|
+
# Parse
|
30
|
+
builder = Prick::Build::Builder.new(conn, path, single: true, load_pool: false, step: step)
|
31
|
+
|
32
|
+
# Register if a build file is referenced and normalize path to
|
33
|
+
# include build.yml of directories
|
34
|
+
if File.directory?(path)
|
35
|
+
path = File.join(path, "build.yml")
|
36
|
+
is_build_file = true
|
37
|
+
elsif File.basename(path) == "build.yml"
|
38
|
+
is_build_file = true
|
39
|
+
else
|
40
|
+
is_build_file = false
|
41
|
+
end
|
42
|
+
|
43
|
+
# Read schema from build file if possible and decide if schema should
|
44
|
+
# be dropped beforehand
|
45
|
+
if is_build_file
|
46
|
+
if builder.root.has_schema
|
47
|
+
!schema or Prick.error "Can't use --schema when doing a schema build"
|
48
|
+
is_schema_rebuild = true
|
49
|
+
schema = build_node.schema
|
50
|
+
else
|
51
|
+
is_schema_rebuild = false
|
52
|
+
end
|
53
|
+
else
|
54
|
+
is_schema_rebuild = false
|
55
|
+
end
|
56
|
+
|
57
|
+
# Infer schema from path
|
58
|
+
if !schema
|
59
|
+
abspath = File.realpath(path)
|
60
|
+
schemapath = File.realpath(Prick.state.schema_dir)
|
61
|
+
if abspath =~ /^#{schemapath}\/([^\/]+)(?:\/.*)$/
|
62
|
+
schema = $1
|
63
|
+
else
|
64
|
+
Prick.error "Can't find schema" # No default schema to avoid unintended runs
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Write-back schema to builder
|
69
|
+
builder.root.schema = schema
|
70
|
+
|
71
|
+
# Drop schema if needed
|
72
|
+
if is_schema_rebuild
|
73
|
+
conn.schema.drop schema, cascade: true
|
74
|
+
end
|
75
|
+
|
76
|
+
# Create schema if absent
|
77
|
+
if !conn.schema.exist?(schema)
|
78
|
+
conn.schema.create(schema)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
if dump
|
83
|
+
builder.load_pool
|
84
|
+
case dump
|
85
|
+
when :nodes; builder.nodes.reject { |node| node.is_a?(Build::BuildNode) }.map &:dump
|
86
|
+
when :allnodes; builder.nodes.map &:dump
|
87
|
+
when :batches; builder.dump
|
88
|
+
else
|
89
|
+
Prick.error "Illegal dump type: #{dump.inspect}"
|
90
|
+
end
|
91
|
+
else
|
92
|
+
Timer.time "Execute build object" do
|
93
|
+
builder.execute conn
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# FIXME
|
98
|
+
# rescue Prick::Error => ex
|
99
|
+
# $stderr.puts ex.message
|
100
|
+
# exit 1
|
101
|
+
#
|
102
|
+
# rescue ::Command::Error => ex
|
103
|
+
# $stderr.puts ex.message
|
104
|
+
# exit 1
|
105
|
+
|
106
|
+
ensure
|
107
|
+
super_conn&.terminate
|
108
|
+
conn&.terminate
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
data/lib/prick/version.rb
CHANGED
data/lib/prick.rb
CHANGED
@@ -50,6 +50,7 @@ require_relative 'prick/subcommand/prick-list.rb'
|
|
50
50
|
require_relative 'prick/subcommand/prick-make.rb'
|
51
51
|
require_relative 'prick/subcommand/prick-migrate.rb'
|
52
52
|
require_relative 'prick/subcommand/prick-release.rb'
|
53
|
+
require_relative 'prick/subcommand/prick-run.rb'
|
53
54
|
require_relative 'prick/subcommand/prick-set.rb'
|
54
55
|
require_relative 'prick/subcommand/prick-setup.rb'
|
55
56
|
require_relative 'prick/subcommand/prick-teardown.rb'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: prick
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.35.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Claus Rasmussen
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-04-
|
11
|
+
date: 2024-04-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: semantic
|
@@ -230,6 +230,7 @@ files:
|
|
230
230
|
- lib/prick/subcommand/prick-make.rb
|
231
231
|
- lib/prick/subcommand/prick-migrate.rb
|
232
232
|
- lib/prick/subcommand/prick-release.rb
|
233
|
+
- lib/prick/subcommand/prick-run.rb
|
233
234
|
- lib/prick/subcommand/prick-set.rb
|
234
235
|
- lib/prick/subcommand/prick-setup.rb
|
235
236
|
- lib/prick/subcommand/prick-teardown.rb
|