prick 0.29.2 → 0.30.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 +2 -0
- data/exe/prick +290 -518
- data/lib/prick/builder/batch.rb +1 -4
- data/lib/prick/builder/builder.rb +15 -9
- data/lib/prick/builder/node.rb +3 -2
- data/lib/prick/builder/node_pool.rb +3 -1
- data/lib/prick/builder/parser.rb +2 -1
- data/lib/prick/constants.rb +12 -12
- data/lib/prick/diff.rb +2 -2
- data/lib/prick/environment.rb +23 -10
- data/lib/prick/local/command.rb +8 -2
- data/lib/prick/local/fmt.rb +56 -0
- data/lib/prick/prick_version.rb +1 -1
- data/lib/prick/share/init/{.gitignore → dot.gitignore} +1 -1
- data/lib/prick/share/init/prick.environment.yml +16 -0
- data/lib/prick/share/init/prick.yml +3 -3
- data/lib/prick/share/init/schema/prick/build.yml +11 -2
- data/lib/prick/share/init/schema/prick/tables.sql +30 -9
- data/lib/prick/share/init/schema/prick/views.sql +6 -0
- data/lib/prick/state.rb +297 -95
- data/lib/prick/subcommand/prick-build.rb +26 -20
- data/lib/prick/subcommand/prick-clean.rb +5 -5
- data/lib/prick/subcommand/prick-create.rb +41 -6
- data/lib/prick/subcommand/prick-drop.rb +57 -14
- data/lib/prick/subcommand/prick-fox.rb +1 -1
- data/lib/prick/subcommand/prick-init.rb +25 -18
- data/lib/prick/subcommand/prick-list.rb +99 -0
- data/lib/prick/subcommand/prick-make.rb +8 -8
- data/lib/prick/subcommand/prick-migrate.rb +8 -7
- data/lib/prick/subcommand/prick-release.rb +4 -2
- data/lib/prick/subcommand/prick-set.rb +52 -0
- data/lib/prick/subcommand/prick-setup.rb +3 -13
- data/lib/prick/subcommand/prick-teardown.rb +13 -9
- data/lib/prick/subcommand/subcommand.rb +12 -0
- data/lib/prick/version.rb +1 -1
- data/lib/prick.rb +54 -15
- metadata +9 -5
- data/lib/prick/share/init/schema/prick/data.sql +0 -6
- data/prick.environments.yml +0 -14
data/exe/prick
CHANGED
@@ -10,16 +10,14 @@ begin
|
|
10
10
|
compile_cache_iseq: true, # Compile Ruby code into ISeq cache, breaks coverage reporting.
|
11
11
|
compile_cache_yaml: true # Compile YAML into a cache
|
12
12
|
)
|
13
|
-
# Bootsnap.instrumentation = ->(event, path) { puts "#{event} #{path}" }
|
13
|
+
# Bootsnap.instrumentation = ->(event, path) { puts "#{event} #{path}" }
|
14
14
|
end
|
15
15
|
|
16
16
|
require 'shellopts'
|
17
|
-
require_relative '../lib/prick.rb'
|
18
|
-
|
19
|
-
include ShellOpts
|
20
|
-
include Prick
|
21
17
|
|
22
|
-
|
18
|
+
# Start time of prick. Used in make and build to compute duration of the whole
|
19
|
+
# build process
|
20
|
+
TIME = Time.now
|
23
21
|
|
24
22
|
SPEC = %(
|
25
23
|
@ Prick project command
|
@@ -33,63 +31,91 @@ SPEC = %(
|
|
33
31
|
-C,directory=EDIR
|
34
32
|
Change to directory DIR before doing anything else
|
35
33
|
|
36
|
-
-
|
37
|
-
Override
|
34
|
+
-p,project-file=PRICK-FILE
|
35
|
+
Override project file. Default is 'prick.yml'
|
38
36
|
|
39
|
-
-
|
40
|
-
Override
|
37
|
+
-e,environment-file=ENVIRONMENT-FILE
|
38
|
+
Override the environment file. Default is 'prick.environment.yml'
|
41
39
|
|
42
|
-
-
|
43
|
-
Override
|
40
|
+
-s,state-file=STATE-FILE
|
41
|
+
Override state file. Default is '.prick-state.yml'
|
44
42
|
|
45
|
-
-
|
46
|
-
|
43
|
+
init! -n,name=NAME -t,title=TITLE DIRECTORY #@ Initialize new Prick project directory
|
44
|
+
Initializes a prick project and checks it into git. If a directory is
|
45
|
+
given the directory will be created and the project initialized in it.
|
46
|
+
Default name and title is derived from the directory name
|
47
47
|
|
48
|
-
|
49
|
-
|
48
|
+
setup! -- [OWNER@]DATABASE [ENVIRONMENT] @ Create and set current database
|
49
|
+
Create database and owner and set the current database
|
50
50
|
|
51
|
-
|
52
|
-
|
51
|
+
teardown! -- [DATABASE...] @ Remove database and owner
|
52
|
+
Drop database, database users, and database owner if possible and not the
|
53
|
+
current user. DATABASE defaults to the current database in which case the
|
54
|
+
state file is also removed
|
53
55
|
|
54
|
-
|
55
|
-
|
56
|
+
clean! -- [DATABASE] @ Empty database and remove users
|
57
|
+
Empty the database and drop related users except the database owner and
|
58
|
+
the prick schema. The public schema is recreated automatically
|
56
59
|
|
57
|
-
|
58
|
-
|
59
|
-
accessible as $ENVIRONMENT in build.yml files and can be used to do
|
60
|
-
conditional builds. There are no built-in values for the environment but
|
61
|
-
'production' and 'development' will be typical choices. Defaults to
|
62
|
-
'development'
|
60
|
+
get.database!
|
61
|
+
Print the name of the current database
|
63
62
|
|
64
|
-
|
65
|
-
|
63
|
+
get.username!
|
64
|
+
Print the name of the current database owner
|
66
65
|
|
67
|
-
|
68
|
-
|
66
|
+
get.environment!
|
67
|
+
Print the current environment
|
69
68
|
|
70
|
-
|
71
|
-
|
69
|
+
set! -- VARIABLE [VALUE [OPT]] @ Switch database/environment
|
70
|
+
Switch database and/or environment or assign a value to the corresponding
|
71
|
+
database variable Currently only 'database', 'environment', and
|
72
|
+
'duration' can be used as arguments. 'duration' not meant for the
|
73
|
+
end-user but for make scripts that enclose the prick command and that
|
74
|
+
would like to record the total time used. Prints the value of the
|
75
|
+
variable if VALUE is absent
|
72
76
|
|
73
|
-
create.
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
Create an object. Fails if migration exist unless the --force flag is given
|
77
|
+
create.database! -- [[OWNER@]DATABASE [ENVIRONMENT]] @ Create database
|
78
|
+
Create database and owner if needed. OWNER defaults to the database
|
79
|
+
name and DATABASE defaults to the project name. ENVIRONMENT defaults to
|
80
|
+
the current environment or to the prick default environment if there is
|
81
|
+
no current environment
|
79
82
|
|
80
|
-
|
83
|
+
It is an error if the database exists but not if the owner exists. Note
|
84
|
+
that you can have multiple databases and switch between them using the
|
85
|
+
'set database' subcommand
|
86
|
+
|
87
|
+
create.migration! -f,force -o,file=FILE -- VERSION @ Create migration
|
81
88
|
Create a migration from VERSION to the current and write it to
|
82
89
|
migration/VERSION. Fails if migration exist unless the --force flag is
|
83
90
|
given. If --file is given, the migration is written to FILE instead of
|
84
|
-
the migration directory
|
85
|
-
|
91
|
+
the migration directory
|
92
|
+
|
93
|
+
create.users!
|
94
|
+
create.schema!
|
95
|
+
create.data!
|
96
|
+
create.all!
|
97
|
+
TODO
|
98
|
+
|
99
|
+
drop.schema! -- [SCHEMA...]
|
100
|
+
@ Drop schemas
|
101
|
+
|
102
|
+
Drops the given schemas or all schemas if called without arguments
|
103
|
+
|
104
|
+
drop.users!
|
105
|
+
@ Drop database users
|
106
|
+
|
107
|
+
Drops all database users except the database owner
|
108
|
+
|
109
|
+
drop.data!
|
110
|
+
@ Drop data
|
111
|
+
|
112
|
+
TODO
|
86
113
|
|
87
|
-
drop!
|
88
|
-
|
114
|
+
drop.owner!
|
115
|
+
Drop database owner
|
89
116
|
|
90
|
-
|
91
|
-
|
92
|
-
'schema' is not implemented
|
117
|
+
drop.database!
|
118
|
+
Drop database
|
93
119
|
|
94
120
|
build! -f,force -t,time --dump=KIND? -- [SCHEMA]
|
95
121
|
Build the project. If SCHEMA is defined, later schemas are excluded.
|
@@ -112,6 +138,9 @@ SPEC = %(
|
|
112
138
|
|
113
139
|
# TODO: A --clean option that resets data
|
114
140
|
|
141
|
+
version!
|
142
|
+
Print project version
|
143
|
+
|
115
144
|
release! -- KIND
|
116
145
|
Create a release of the given kind. KIND can be 'major', 'minor', or
|
117
146
|
'patch'. Release checks that the current repo is clean and up to date
|
@@ -120,146 +149,277 @@ SPEC = %(
|
|
120
149
|
migrate! -f,file=FILE
|
121
150
|
Execute a migration
|
122
151
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
152
|
+
list.environments! -l,long
|
153
|
+
List available environments (environments with a comment field)
|
154
|
+
|
155
|
+
list.databases! -l,long
|
156
|
+
List Prick databases. The --long option creates a table-like output
|
157
|
+
|
158
|
+
list.users!
|
159
|
+
List database users in the current environment
|
160
|
+
|
161
|
+
list.owners! -l,long
|
162
|
+
List database owners
|
163
|
+
|
164
|
+
list.variables! -l,long -a,all
|
165
|
+
List variables for the current environment
|
129
166
|
|
130
167
|
dump.migration! --force -- VERSION
|
168
|
+
|
169
|
+
dump.type!
|
170
|
+
Dumps a PgGraph object
|
171
|
+
|
172
|
+
dump.variable! -x,export -l,local -- [VARIABLE...]
|
173
|
+
Dumps a bash source snippets that sets and optionally exports values from
|
174
|
+
the configuration, environment, and state. Environment is only dumped if
|
175
|
+
the current environment is defined in the state file. The state file may
|
176
|
+
be absent in which case the related variables are also left undefined
|
177
|
+
|
178
|
+
dump.value! -- VARIABLE...
|
179
|
+
Dumps values of the given variables. Multiple variables can be read into bash
|
180
|
+
variables using read:
|
181
|
+
|
182
|
+
read name title <<< $(prick dump value PRICK_NAME PRICK_TITLE)
|
183
|
+
|
184
|
+
dump.node!
|
185
|
+
dump.build!
|
186
|
+
dump.data! @ TODO
|
187
|
+
dump.schema! @ TODO
|
188
|
+
dump.database! @ TODO
|
189
|
+
TODO
|
131
190
|
)
|
132
191
|
|
133
|
-
|
192
|
+
def require_db(database = Prick.state&.database, exist: true)
|
193
|
+
database or raise ArgumentError
|
194
|
+
dba = State.connection
|
195
|
+
if exist
|
196
|
+
dba.rdbms.exist?(database) or Prick.error "Can't find database '#{database}'"
|
197
|
+
if Prick.state&.conn&.name == database
|
198
|
+
close_conn = false
|
199
|
+
conn = Prick.state.conn
|
200
|
+
else
|
201
|
+
close_conn = true
|
202
|
+
conn = PgConn.new(database)
|
203
|
+
end
|
204
|
+
conn.schema.exist?("prick") or Prick.error "Database '#{database}' is not a Prick database"
|
205
|
+
conn.close if close_conn # Close session explicitly so we can drop database if required
|
206
|
+
else
|
207
|
+
!dba.rdbms.exist?(database) or Prick.error "Database '#{database}' exists"
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
def parse_database_args(state, args)
|
212
|
+
arg, environment = args.expect(0..2)
|
213
|
+
if arg
|
214
|
+
if arg =~ /^(.*)@(.*)$/
|
215
|
+
username, database = $1, $2
|
216
|
+
else
|
217
|
+
database = arg
|
218
|
+
username = database
|
219
|
+
end
|
220
|
+
else
|
221
|
+
database = state.name
|
222
|
+
username = database
|
223
|
+
end
|
224
|
+
database or Prick.error "Database is undefined"
|
225
|
+
[username, database, environment]
|
226
|
+
end
|
227
|
+
|
228
|
+
begin
|
229
|
+
# Parse command line
|
230
|
+
opts, args = ShellOpts.process(SPEC, ARGV, exception: true)
|
231
|
+
|
232
|
+
# Honor -C option
|
233
|
+
begin
|
234
|
+
Dir.chdir(opts.directory) if opts.directory?
|
235
|
+
rescue Errno::ENOENT
|
236
|
+
raise ShellOpts::Error, "Can't cd to '#{opts.directory}'"
|
237
|
+
end
|
238
|
+
rescue ShellOpts::Error => ex
|
239
|
+
ShellOpts.error(ex.message)
|
240
|
+
end
|
241
|
+
|
242
|
+
# Require prick only after -C directory option because some constants depends
|
243
|
+
# on the current directory
|
244
|
+
require_relative '../lib/prick.rb'
|
245
|
+
include Prick
|
134
246
|
|
135
247
|
begin
|
136
248
|
# Handle verbose and quiet
|
137
249
|
$verbose = opts.verbose?
|
138
250
|
$quiet = opts.quiet?
|
139
251
|
|
140
|
-
#
|
141
|
-
|
142
|
-
if File.exist?(opts.directory)
|
143
|
-
begin
|
144
|
-
Dir.chdir(opts.directory)
|
145
|
-
rescue Errno::ENOENT
|
146
|
-
raise Prick::Error, "Can't cd to '#{opts.directory}'"
|
147
|
-
end
|
148
|
-
else
|
149
|
-
raise Prick::Error, "Can't find directory: #{opts.directory}"
|
150
|
-
end
|
151
|
-
end
|
252
|
+
# Expect a sub-command. TODO: Make this a built-in in ShellOpts#subcommand!
|
253
|
+
cmd = opts.subcommand! or Prick.error "Subcomand expected"
|
152
254
|
|
153
|
-
#
|
154
|
-
|
255
|
+
# Handle -p, -e, and -c. TODO: Take -C into account for relative paths. Low-hanging fruit
|
256
|
+
project_file = opts.project_file || PRICK_PROJECT_PATH
|
257
|
+
environment_file = opts.environment_file || PRICK_ENVIRONMENT_PATH
|
258
|
+
state_file = opts.state_file || PRICK_STATE_PATH
|
155
259
|
|
156
|
-
# Process init command
|
157
|
-
if opts.subcommand == :init
|
158
|
-
dir,
|
159
|
-
|
160
|
-
if opts.database.nil? || opts.username.nil?
|
161
|
-
puts
|
162
|
-
puts "Please check database/username in #{PRICK_CONTEXT_FILE}"
|
163
|
-
end
|
260
|
+
# Process init command and exit
|
261
|
+
if opts.subcommand == :init!
|
262
|
+
dir, name = Prick::SubCommand.init(project_file, args.expect(0..1), cmd.name, cmd.title)
|
263
|
+
Prick.mesg "Initialized Prick project '#{name}' in #{File.absolute_path(dir)}/"
|
164
264
|
exit
|
165
265
|
end
|
166
266
|
|
167
|
-
# Check
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
267
|
+
# Check for prick project
|
268
|
+
if ![:teardown!, :clean!].include?(opts.subcommand) || args.size == 0
|
269
|
+
# We test for the presense of the schema directory to verify we're in a
|
270
|
+
# prick directory. Checking for a configuration file doesn't work because
|
271
|
+
# they can be placed elsewhere. TODO: This require us to check for project file manually
|
272
|
+
# File.directory? "schema" or Prick.error "Not in a prick project directory"
|
273
|
+
File.directory?(SCHEMA_DIR) or Prick.error "Not in a prick project directory"
|
274
|
+
File.exist?(project_file) or Prick.error "Can't find project file '#{project_file}'"
|
275
|
+
end
|
173
276
|
|
174
277
|
# Load state
|
175
|
-
state = Prick.state = State.
|
176
|
-
|
177
|
-
# Set database, username and environment
|
178
|
-
database = state.database = opts.database || state.database
|
179
|
-
username = state.username = opts.username || state.username
|
180
|
-
environment = state.environment = opts.environment || state.environment
|
278
|
+
state = Prick.state = State.new(project_file, environment_file, state_file)
|
181
279
|
|
182
|
-
#
|
183
|
-
|
280
|
+
# Lazyness
|
281
|
+
database = state.database
|
282
|
+
username = state.username
|
283
|
+
environment = state.environment
|
184
284
|
|
185
285
|
# Process subcommands
|
186
286
|
case opts.subcommand
|
187
287
|
when :version!
|
188
288
|
puts "#{Prick.state.name}-#{Prick.state.version}"
|
189
289
|
|
190
|
-
when :env!
|
191
|
-
env = args.expect(1)
|
192
|
-
Prick.state.environment = env
|
193
|
-
Prick.state.save
|
194
|
-
|
195
290
|
when :setup!
|
196
|
-
Prick
|
291
|
+
state.project_loaded? or Prick.error "No #{project_file} found"
|
292
|
+
username, database, environment = parse_database_args(state, args)
|
293
|
+
require_db(database, exist: false)
|
294
|
+
Prick::SubCommand.setup(database, username, environment)
|
197
295
|
|
296
|
+
# FIXME Ensure that we never drop the current user
|
198
297
|
when :teardown!
|
199
|
-
|
298
|
+
if args.empty?
|
299
|
+
Prick::SubCommand.teardown(database, remove_state_file: true)
|
300
|
+
else
|
301
|
+
Prick::SubCommand.teardown(args)
|
302
|
+
end
|
303
|
+
|
304
|
+
when :get!
|
305
|
+
case cmd.subcommand
|
306
|
+
when :database!; puts database
|
307
|
+
when :username!; puts username
|
308
|
+
when :environment!; puts environment
|
309
|
+
else
|
310
|
+
raise ArgumentError
|
311
|
+
end
|
312
|
+
|
313
|
+
when :set!
|
314
|
+
variable, *args = args.expect(1..3)
|
315
|
+
require_db(database) if variable == "duration"
|
316
|
+
Prick::SubCommand.set(variable, *args) or error "Illegal variable name '#{variable}'"
|
200
317
|
|
201
318
|
when :clean!
|
319
|
+
database = args.expect(0..1) || database
|
320
|
+
require_db(database)
|
202
321
|
Prick::SubCommand.clean(database)
|
203
322
|
|
204
323
|
when :create!
|
205
|
-
create_command = opts.create!
|
324
|
+
create_command = opts.create! # Because we need easy access to subcommand options
|
206
325
|
case create_command.subcommand
|
207
|
-
when :
|
326
|
+
when :database!
|
327
|
+
database, username, environment = parse_database_args(state, args)
|
328
|
+
require_db(database, exist: false)
|
329
|
+
Prick::SubCommand.create_database(database, username, environment)
|
330
|
+
when :migration!
|
331
|
+
require_db
|
208
332
|
arg = args.expect(1)
|
209
|
-
version = PrickVersion.try(arg) or
|
333
|
+
version = PrickVersion.try(arg) or Prick.error "Illegal version: #{arg}"
|
210
334
|
Prick::SubCommand.create_migration(
|
211
335
|
username, version,
|
212
336
|
force: create_command.subcommand!.force?,
|
213
337
|
file: create_command.subcommand!.file)
|
338
|
+
when :users, :schema, :data, :all
|
339
|
+
raise NotImplementedError
|
214
340
|
else
|
215
|
-
raise
|
341
|
+
raise ArgumentError
|
216
342
|
end
|
217
343
|
|
218
344
|
when :build!
|
345
|
+
require_db
|
219
346
|
dump = cmd.dump? ? cmd.dump("batches")&.to_sym || :batches : nil
|
220
347
|
# exclude = cmd.exclude? ? cmd.exclude.split(",") : []
|
221
348
|
Prick::SubCommand.build(
|
222
349
|
database, username, args.expect(0..1), force: cmd.force?, timer: cmd.time?, dump: dump)
|
223
350
|
|
224
351
|
when :make!
|
352
|
+
require_db
|
225
353
|
dump = cmd.dump? ? cmd.dump("batches")&.to_sym || :batches : nil
|
226
354
|
Prick::SubCommand.make(database, username, args.expect(0..1), timer: cmd.time?, dump: dump)
|
227
355
|
|
228
356
|
when :fox!
|
357
|
+
require_db
|
229
358
|
Prick::SubCommand.fox(database, username, args)
|
230
359
|
|
231
360
|
when :drop!
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
361
|
+
require_db if cmd.subcommand != :owner!
|
362
|
+
if cmd.subcommand == :schema!
|
363
|
+
schemas = args.to_a
|
364
|
+
else
|
365
|
+
args.expect(0)
|
366
|
+
end
|
367
|
+
case cmd.subcommand
|
368
|
+
when :all!
|
369
|
+
Prick::SubCommand.drop_all(database, username)
|
370
|
+
when :users!
|
236
371
|
Prick::SubCommand.drop_users(database)
|
237
|
-
when :
|
238
|
-
Prick::SubCommand.
|
239
|
-
when :database
|
372
|
+
when :owner!
|
373
|
+
Prick::SubCommand.drop_owner(username)
|
374
|
+
when :database!
|
240
375
|
Prick::SubCommand.drop_database(database)
|
241
|
-
when :data
|
376
|
+
when :data!
|
242
377
|
raise NotImplementedError
|
378
|
+
when :schema!
|
379
|
+
Prick::SubCommand.drop_schema(database, schemas)
|
243
380
|
else
|
244
|
-
|
381
|
+
Prick.error "Unknown subject: #{subject}"
|
245
382
|
end
|
246
383
|
|
247
384
|
when :release!
|
248
385
|
kind = args.expect(1).to_sym
|
249
386
|
constrain? kind, :major, :minor, :patch or
|
250
|
-
|
387
|
+
Prick.failure "Expected 'major', 'minor', or 'patch' argument, got '#{kind}'"
|
251
388
|
Prick::SubCommand.release(kind)
|
252
389
|
|
253
390
|
when :migrate!
|
391
|
+
require_db
|
254
392
|
args.expect(0)
|
255
393
|
Prick::SubCommand.migrate(database, username, file: cmd.file)
|
256
394
|
|
395
|
+
when :list!
|
396
|
+
format = (cmd.subcommand!.long? ? :long : :short) if cmd.subcommand != :users!
|
397
|
+
case cmd.subcommand
|
398
|
+
when :environments!; Prick::SubCommand.list_environments(format: format)
|
399
|
+
when :databases!; Prick::SubCommand.list_databases(format: format)
|
400
|
+
when :variables!;
|
401
|
+
all = cmd.subcommand!.all?
|
402
|
+
Prick::SubCommand.list_variables(format: format, all: all)
|
403
|
+
when :users!; Prick::SubCommand.list_users
|
404
|
+
when :owners!; Prick::SubCommand.list_owners(format: format)
|
405
|
+
else
|
406
|
+
Prick.error "Unknown subcommand: #{cmd.subcommand}"
|
407
|
+
end
|
408
|
+
|
257
409
|
when :dump!
|
258
410
|
subject = cmd.subcommand!
|
259
411
|
case cmd.subcommand
|
412
|
+
when :node!
|
413
|
+
conn = PgConn.new(database, username)
|
414
|
+
builder = Prick::Build::Builder.new(conn, Prick::SCHEMA_DIR)
|
415
|
+
builder.root.dump
|
416
|
+
when :build!
|
417
|
+
conn = PgConn.new(database, username)
|
418
|
+
builder = Prick::Build::Builder.new(conn, Prick::SCHEMA_DIR)
|
419
|
+
# FIXME Nothing happens here
|
260
420
|
when :migration!
|
261
421
|
arg = args.expect(1)
|
262
|
-
version = PrickVersion.try(arg) or
|
422
|
+
version = PrickVersion.try(arg) or Prick.error "Illegal version number: #{arg}"
|
263
423
|
Prick::SubCommand.create_migration(username, version, force: subject.force?, file: "/dev/stdout")
|
264
424
|
when :type!
|
265
425
|
conn = PgConn.new(database, username)
|
@@ -269,15 +429,25 @@ begin
|
|
269
429
|
graph.dump
|
270
430
|
when :data!, :schema!, :database!
|
271
431
|
raise NotImplementedError
|
272
|
-
when :
|
273
|
-
|
432
|
+
when :variable!
|
433
|
+
scope =
|
434
|
+
case [subject.export?, subject.local?]
|
435
|
+
in [true, false]; :global
|
436
|
+
in [false, true]; :local
|
437
|
+
in [false, false]; nil
|
438
|
+
else
|
439
|
+
Prick.error "Conflicting options - --export and --local"
|
440
|
+
end
|
441
|
+
puts state.bash_source(args.first ? args : nil, scope: scope)
|
442
|
+
exit
|
443
|
+
when :value!
|
444
|
+
puts args.expect(1..).map { |var| Array(state.bash_environment[var]).join(' ') }
|
274
445
|
else
|
275
|
-
|
446
|
+
object = args.extract(1) # Fails if object is absent
|
447
|
+
Prick.error "Unknown dump object: #{object}"
|
276
448
|
end
|
277
|
-
|
278
|
-
|
279
449
|
else
|
280
|
-
|
450
|
+
Prick.failure "Internal error: Unhandled command - #{opts.subcommand.inspect}"
|
281
451
|
end
|
282
452
|
|
283
453
|
rescue Prick::Build::PostgresError => ex
|
@@ -295,409 +465,11 @@ rescue Prick::Build::PostgresError => ex
|
|
295
465
|
end
|
296
466
|
exit 1
|
297
467
|
|
298
|
-
rescue RuntimeError, IOError, ShellOpts::Failure, Prick::Fail, Prick::Build::PostgresError => ex
|
299
|
-
ShellOpts.failure(ex.message)
|
300
|
-
|
301
468
|
rescue ShellOpts::Error, Prick::Error => ex
|
469
|
+
raise
|
302
470
|
ShellOpts.error(ex.message)
|
303
|
-
end
|
304
|
-
|
305
|
-
|
306
|
-
__END__
|
307
|
-
|
308
|
-
-n,name=NAME
|
309
|
-
Name of project. Defauls to the environment variable `PRICK_PROJECT` if
|
310
|
-
set and else the name of the current directory
|
311
|
-
|
312
|
-
init! -u,user=USER [NAME]
|
313
|
-
Initialize a project in the given directory. The USER is the postgres
|
314
|
-
user and defaults to the project name
|
315
|
-
|
316
|
-
info!
|
317
|
-
Print project information
|
318
|
-
|
319
|
-
list.releases! -m,migrations -c,cancelled
|
320
|
-
List releases. Include migration releases if the --migration option is
|
321
|
-
present and also include cancelled releases if the --cancelled option is
|
322
|
-
present
|
323
|
-
|
324
|
-
list.migrations!
|
325
|
-
List migrations
|
326
|
-
|
327
|
-
list.upgrades! [FROM [TO]]
|
328
|
-
List available upgrades
|
329
|
-
|
330
|
-
list.cache!
|
331
|
-
List cache files
|
332
|
-
|
333
|
-
build! -d,database=DATABASE -s,state=FILE -C,no-cache [TAG]
|
334
|
-
Drop all users associated with the database before building the current
|
335
|
-
database from the content in the schemas/ directory. With a tag the
|
336
|
-
version is built into the associated versioned database and the result is
|
337
|
-
saved to cache unless the -C option is given. The -d option overrides the
|
338
|
-
default database and the -s option overrides the default state file
|
339
|
-
(fox.state)
|
340
|
-
|
341
|
-
make! -d,database=DATABASE -C,no-cache [TAG]
|
342
|
-
Build the current database from the content in the schemas/ directory.
|
343
|
-
With a tag the associated versioned database is loaded from cache if
|
344
|
-
present. The -C option ignores the cache and the -d option overrides
|
345
|
-
the default database
|
346
|
-
|
347
|
-
make.clean! -a,all
|
348
|
-
Drop versioned databases and remove cached and other temporary files.
|
349
|
-
Also drop the project database if the -a option is given
|
350
|
-
|
351
|
-
load! -d,database=DATABASE VERSION|FILE
|
352
|
-
Load the cached version or the file into the associated versioned
|
353
|
-
database. It is an error if the version hasn't been cached. The --database
|
354
|
-
argument overrides the database
|
355
|
-
|
356
|
-
save! VERSION [FILE]
|
357
|
-
Save the versioned database associated with version to the cache or the
|
358
|
-
given file
|
359
|
-
|
360
|
-
drop! -a,all [DATABASE]
|
361
|
-
Drop the given database or all versioned databases. Users with a username
|
362
|
-
on the form <database>__<username> are also dropped. The --all option
|
363
|
-
also drops the project database
|
364
|
-
|
365
|
-
drop.users! [DATABASE]
|
366
|
-
Drop users with a username on the form <database>__<username>
|
367
|
-
|
368
|
-
diff! -m,mark -t,tables -T,notables
|
369
|
-
diff [FROM-DATABASE|FROM-VERSION [TO-DATABASE|TO-VERSION]]
|
370
|
-
Create a schema diff between the given databases or versions. Default
|
371
|
-
to-version is the current schema and default from-version is the base
|
372
|
-
version of this branch/tag
|
373
|
-
|
374
|
-
migrate!
|
375
|
-
Not yet implemented
|
376
|
-
|
377
|
-
prepare!
|
378
|
-
Prepare a release. Just a shorthand for 'prick prepare release'
|
379
|
-
|
380
|
-
prepare.release! [FORK]
|
381
|
-
Populate the current migration directory with migration files
|
382
|
-
|
383
|
-
prepare.feature! NAME
|
384
|
-
Create and populate a feature as a subdirectory of the current directory.
|
385
|
-
Also prepares the current release directory
|
386
471
|
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
prepare.schema! NAME
|
391
|
-
Create and populate a new schema directory. Existing files and
|
392
|
-
directories are kept
|
393
|
-
|
394
|
-
prepare.diff! [VERSION]
|
395
|
-
Not yet implemented
|
396
|
-
|
397
|
-
include.feature! FEATURE
|
398
|
-
Include the given feature in the current pre-release
|
399
|
-
|
400
|
-
check!
|
401
|
-
Check that the current migration applied to the base version yields the
|
402
|
-
same result as loading the current schema
|
403
|
-
|
404
|
-
create.release! [RELEASE]
|
405
|
-
Prepare a release and create release directory and migration file before
|
406
|
-
tagging and branching to a release branch. The RELEASE argument can be
|
407
|
-
left out if the current branch is a prerelease branch
|
408
|
-
|
409
|
-
create.prerelease! RELEASE
|
410
|
-
Prepare a release and create release directory and migration file before
|
411
|
-
branching to a prerelease branch
|
412
|
-
|
413
|
-
create.feature! NAME
|
414
|
-
Prepare a feature before branching to a feature branch
|
415
|
-
|
416
|
-
cancel!
|
417
|
-
Cancel a release. Just a shorthand for 'prick cancel release'
|
418
|
-
|
419
|
-
cancel.release!
|
420
|
-
Cancel a release. Since tags are immutable, the release is cancelled by
|
421
|
-
added a special cancel-tag to the release that makes prick ignore it
|
422
|
-
|
423
|
-
generate.migration!
|
424
|
-
Create a script to migrate the database
|
425
|
-
|
426
|
-
generate.schema!
|
427
|
-
Create a script to create the database
|
428
|
-
|
429
|
-
upgrade!
|
430
|
-
Migrate the database to match the current schema
|
431
|
-
|
432
|
-
backup! [FILE]
|
433
|
-
Saves a backup of the database to the given file or to the var/spool
|
434
|
-
directory
|
435
|
-
|
436
|
-
restore! [FILE]
|
437
|
-
Restore the database from the given backup file or from the latest backup
|
438
|
-
in the var/spool directory
|
439
|
-
)
|
440
|
-
|
441
|
-
__END__
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
DEFAULT_STATE_FILE = "fox.state"
|
449
|
-
|
450
|
-
opts, args = ShellOpts.process(SPEC, ARGV)
|
451
|
-
|
452
|
-
# Handle --help
|
453
|
-
if opts.help?
|
454
|
-
ShellOpts.help
|
455
|
-
exit
|
456
|
-
end
|
457
|
-
|
458
|
-
# Handle --version
|
459
|
-
if opts.version?
|
460
|
-
puts "prick-#{VERSION}"
|
461
|
-
exit
|
462
|
-
end
|
463
|
-
|
464
|
-
begin
|
465
|
-
# Honor -C option
|
466
|
-
if opts.directory?
|
467
|
-
if File.exist?(opts.directory)
|
468
|
-
begin
|
469
|
-
Dir.chdir(opts.directory)
|
470
|
-
rescue Errno::ENOENT
|
471
|
-
raise Prick::Error, "Can't cd to '#{opts.directory}'"
|
472
|
-
end
|
473
|
-
else
|
474
|
-
raise Prick::Error, "Can't find directory: #{opts.directory}"
|
475
|
-
end
|
476
|
-
end
|
477
|
-
|
478
|
-
# Create program object
|
479
|
-
program = Program.new(quiet: opts.quiet?, verbose: opts.verbose?)
|
480
|
-
$verbose = opts.verbose? ? opts.verbose : nil
|
481
|
-
|
482
|
-
# Handle init command
|
483
|
-
if opts.subcommand == :init
|
484
|
-
directory = args.expect(0..1)
|
485
|
-
name = opts.name || (directory && File.basename(directory)) || File.basename(Dir.getwd)
|
486
|
-
user = opts.init!.user || name
|
487
|
-
program.init(name, user, directory || ".")
|
488
|
-
exit 0
|
489
|
-
end
|
490
|
-
|
491
|
-
# Change to parent directory containing the Prick version file if not found
|
492
|
-
# in the current directory
|
493
|
-
program.current_directory = Dir.getwd
|
494
|
-
while Dir.getwd != "/" && !File.exist?(PRICK_VERSION_FILE)
|
495
|
-
Dir.chdir("..")
|
496
|
-
end
|
497
|
-
|
498
|
-
# Check prick version
|
499
|
-
file = PrickVersion.new
|
500
|
-
file.exist? or raise Prick::Error, "Can't find prick version file '#{file.path}'"
|
501
|
-
VERSION == file.read.to_s or
|
502
|
-
raise Prick::Fail, ".prick-version required prick-#{file.read} but you're using prick-#{VERSION}"
|
503
|
-
|
504
|
-
# TODO: Check for dirty detached head
|
505
|
-
|
506
|
-
# Expect a sub-command
|
507
|
-
opts.subcommand or raise Prick::Error, "Subcomand expected"
|
508
|
-
|
509
|
-
case opts.subcommand
|
510
|
-
when :info
|
511
|
-
args.expect(0)
|
512
|
-
program.info
|
513
|
-
|
514
|
-
when :list
|
515
|
-
command = opts.list!
|
516
|
-
case command.subcommand
|
517
|
-
when :releases;
|
518
|
-
obj = command.releases!
|
519
|
-
program.list_releases(migrations: obj.migrations?, cancelled: obj.cancelled?)
|
520
|
-
when :migrations; program.list_migrations
|
521
|
-
when :upgrades; program.list_upgrades(*args.expect(0..2).compact)
|
522
|
-
when :cache;
|
523
|
-
args.expect(0)
|
524
|
-
program.list_cache
|
525
|
-
when NilClass; raise Prick::Error, "list requires a releases|migrations|upgrades sub-command"
|
526
|
-
else
|
527
|
-
raise Prick::Internal, "Subcommand #{opts.subcommand}.#{command.subcommand} is not matched"
|
528
|
-
end
|
529
|
-
|
530
|
-
when :build
|
531
|
-
version = args.expect(0..1)
|
532
|
-
state_file = File.expand_path(opts.build!.state || DEFAULT_STATE_FILE)
|
533
|
-
FileUtils.rm_f(state_file)
|
534
|
-
program.build(opts.build!.database, version, state_file, opts.build!.no_cache?)
|
535
|
-
|
536
|
-
when :make
|
537
|
-
command = opts.make!
|
538
|
-
case command.subcommand
|
539
|
-
when :clean
|
540
|
-
args.expect(0)
|
541
|
-
program.make_clean(command.clean!.all?)
|
542
|
-
else
|
543
|
-
version = args.expect(0..1)
|
544
|
-
program.make(opts.make!.database, version, opts.make!.no_cache?)
|
545
|
-
end
|
546
|
-
|
547
|
-
when :load
|
548
|
-
version_or_file = args.expect(1)
|
549
|
-
program.load(opts.load!.database, version_or_file)
|
550
|
-
|
551
|
-
when :save
|
552
|
-
version, file = args.expect(1..2)
|
553
|
-
program.save(version, file)
|
554
|
-
|
555
|
-
when :drop
|
556
|
-
command = opts.drop!
|
557
|
-
case command.subcommand
|
558
|
-
when :users
|
559
|
-
database = args.extract(0..1) || program.project.database.name
|
560
|
-
args.expect(0)
|
561
|
-
program.drop_users(database)
|
562
|
-
else
|
563
|
-
program.drop(args.expect(0..1), opts.drop!.all?)
|
564
|
-
end
|
565
|
-
|
566
|
-
when :diff
|
567
|
-
mark = opts.diff!.mark
|
568
|
-
tables = opts.diff!.tables
|
569
|
-
no_tables = opts.diff!.notables
|
570
|
-
tables.nil? && no_tables.nil? || tables ^ no_tables or
|
571
|
-
raise Error, "--tables and --no-tables options are exclusive"
|
572
|
-
select = tables ? :tables : (no_tables ? :no_tables : :all)
|
573
|
-
from, to = args.expect(0..2)
|
574
|
-
program.diff(from, to, mark, select)
|
575
|
-
|
576
|
-
when :migrate
|
577
|
-
raise NotYet
|
578
|
-
|
579
|
-
when :prepare
|
580
|
-
cmd = opts.prepare!.subcommand || :release
|
581
|
-
case cmd
|
582
|
-
when :release; program.prepare_release(args.expect(0..1))
|
583
|
-
when :feature; program.prepare_feature(args.expect(1))
|
584
|
-
when :migration; program.prepare_migration(args.expect(0..1))
|
585
|
-
when :schema; program.prepare_schema(args.expect(1))
|
586
|
-
when :diff; program.prepare_diff(args.expect(0..1))
|
587
|
-
else
|
588
|
-
raise Prick::Internal, "Subcommand #{opts.subcommand}.#{cmd} is not matched"
|
589
|
-
end
|
590
|
-
|
591
|
-
when :include
|
592
|
-
cmd = opts.include!.subcommand || :feature
|
593
|
-
case cmd
|
594
|
-
when :feature; program.include_feature(args.expect(1))
|
595
|
-
else
|
596
|
-
raise Prick::Internal, "Subcommand #{opts.subcommand}.#{cmd} is not matched"
|
597
|
-
end
|
598
|
-
|
599
|
-
when :check
|
600
|
-
args.expect(0)
|
601
|
-
program.check
|
602
|
-
|
603
|
-
when :create
|
604
|
-
cmd = opts.create!.subcommand || :release
|
605
|
-
case cmd
|
606
|
-
when :release; program.create_release(args.expect(0..1))
|
607
|
-
when :prerelease; program.create_prerelease(args.expect(0..1))
|
608
|
-
when :feature; program.create_feature(args.expect(1))
|
609
|
-
else
|
610
|
-
raise Prick::Internal, "Subcommand #{opts.subcommand}.#{cmd} is not matched"
|
611
|
-
end
|
612
|
-
|
613
|
-
when :cancel
|
614
|
-
cmd = opts.cancel!.subcommand
|
615
|
-
case cmd
|
616
|
-
when :release; program.cancel_release(args.expect(1))
|
617
|
-
when nil; raise Prick::Error, "'cancel' subcommand requires a release argument"
|
618
|
-
else
|
619
|
-
raise Prick::Internal, "Subcommand #{opts.subcommand}.#{cmd} is not matched"
|
620
|
-
end
|
621
|
-
|
622
|
-
when :generate
|
623
|
-
cmd = opts.generate!.subcommand
|
624
|
-
case cmd
|
625
|
-
when :schema; program.generate_schema
|
626
|
-
when :migration; program.generate_migration
|
627
|
-
when nil; raise Prick::Error, "'generate' subcommand requires a 'schema' or 'migration' argument"
|
628
|
-
else
|
629
|
-
raise Prick::Internal, "Subcommand #{opts.subcommand}.#{cmd} is not matched"
|
630
|
-
end
|
631
|
-
|
632
|
-
when :upgrade
|
633
|
-
args.expect(0)
|
634
|
-
program.upgrade
|
635
|
-
|
636
|
-
when :backup
|
637
|
-
program.backup(args.expect(0..1))
|
638
|
-
|
639
|
-
when :restore
|
640
|
-
program.restore(args.expect(0..1))
|
641
|
-
else
|
642
|
-
raise Prick::Internal, "Subcommand #{opts.subcommand} is not matched"
|
643
|
-
end
|
644
|
-
|
645
|
-
rescue Prick::Fail => ex # Handling of Fail has to come first because Fail < Error
|
646
|
-
ShellOpts.fail(ex.message)
|
647
|
-
rescue Prick::Error => ex
|
648
|
-
ShellOpts.error(ex.message)
|
472
|
+
rescue RuntimeError, IOError, ShellOpts::Failure, Prick::Failure, Prick::Build::PostgresError => ex
|
473
|
+
ShellOpts.failure(ex.message)
|
649
474
|
end
|
650
475
|
|
651
|
-
__END__
|
652
|
-
|
653
|
-
# Awaits support for sections in ShellOpts
|
654
|
-
HELP = %(
|
655
|
-
OPTIONS
|
656
|
-
-n, --name=NAME
|
657
|
-
-C, --directory=DIR
|
658
|
-
-h, --help
|
659
|
-
-v, --verbose
|
660
|
-
--version
|
661
|
-
|
662
|
-
COMMANDS
|
663
|
-
INITIALIZATION
|
664
|
-
init --user=USER [DIR]
|
665
|
-
|
666
|
-
INFO COMMANDS
|
667
|
-
info
|
668
|
-
list releases --migrations --cancelled
|
669
|
-
list migrations
|
670
|
-
list upgrades --all
|
671
|
-
|
672
|
-
BUILDING
|
673
|
-
build -d DATABASE -C --nocache [TAG]
|
674
|
-
make -d DATABASE -C --nocache [TAG]
|
675
|
-
make clean -a
|
676
|
-
load -d DATABASE VERSION|FILE
|
677
|
-
save VERSION [FILE]
|
678
|
-
drop --all [DATABASE]
|
679
|
-
diff [FROM-DATABASE|FROM-VERSION [TO-DATABASE|TO-VERSION]]
|
680
|
-
migrate
|
681
|
-
|
682
|
-
PREPARING RELEASES
|
683
|
-
prepare release [FORK]
|
684
|
-
prepare feature NAME
|
685
|
-
prepare migration FROM
|
686
|
-
prepare schema NAME
|
687
|
-
prepare diff [VERSION]
|
688
|
-
include feature FEATURE
|
689
|
-
check
|
690
|
-
|
691
|
-
CREATING RELEASES
|
692
|
-
create release [RELEASE]
|
693
|
-
create prerelease RELEASE
|
694
|
-
create feature NAME
|
695
|
-
cancel release RELEASE
|
696
|
-
|
697
|
-
DEPLOYING RELEASES
|
698
|
-
generate migration
|
699
|
-
generate schema
|
700
|
-
upgrade
|
701
|
-
backup [FILE]
|
702
|
-
restore [FILE]
|
703
|
-
)
|