prick 0.29.2 → 0.31.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 +294 -519
- data/idea.txt +38 -0
- 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 +30 -12
- 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 +304 -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 +42 -7
- data/lib/prick/subcommand/prick-drop.rb +41 -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 +14 -9
- 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,93 @@ 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. If the --force option is present, the
|
55
|
+
database is dropped even if it is not a Prick database
|
53
56
|
|
54
|
-
|
55
|
-
|
57
|
+
clean! -- [DATABASE] @ Empty database and remove users
|
58
|
+
Empty the database and drop related users except the database owner and
|
59
|
+
the prick schema. The public schema is recreated automatically
|
56
60
|
|
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'
|
61
|
+
get.database!
|
62
|
+
Print the name of the current database
|
63
63
|
|
64
|
-
|
65
|
-
|
64
|
+
get.username!
|
65
|
+
Print the name of the current database owner
|
66
66
|
|
67
|
-
|
68
|
-
|
67
|
+
get.environment!
|
68
|
+
Print the current environment
|
69
69
|
|
70
|
-
|
71
|
-
|
70
|
+
set! -- VARIABLE [VALUE [OPT]] @ Switch database/environment
|
71
|
+
Switch database and/or environment or assign a value to the corresponding
|
72
|
+
database variable Currently only 'database', 'environment', and
|
73
|
+
'duration' can be used as arguments. 'duration' not meant for the
|
74
|
+
end-user but for make scripts that enclose the prick command and that
|
75
|
+
would like to record the total time used. Prints the value of the
|
76
|
+
variable if VALUE is absent
|
72
77
|
|
73
|
-
create.
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
Create an object. Fails if migration exist unless the --force flag is given
|
78
|
+
create.database! -- [[OWNER@]DATABASE [ENVIRONMENT]] @ Create database
|
79
|
+
Create database and owner if needed. OWNER defaults to the database
|
80
|
+
name and DATABASE defaults to the project name. ENVIRONMENT defaults to
|
81
|
+
the current environment or to the prick default environment if there is
|
82
|
+
no current environment
|
79
83
|
|
80
|
-
|
84
|
+
It is an error if the database exists but not if the owner exists. Note
|
85
|
+
that you can have multiple databases and switch between them using the
|
86
|
+
'set database' subcommand
|
87
|
+
|
88
|
+
create.migration! -f,force -o,file=FILE -- VERSION @ Create migration
|
81
89
|
Create a migration from VERSION to the current and write it to
|
82
90
|
migration/VERSION. Fails if migration exist unless the --force flag is
|
83
91
|
given. If --file is given, the migration is written to FILE instead of
|
84
|
-
the migration directory
|
85
|
-
branch and can be used to create ad-hoc migration scripts
|
92
|
+
the migration directory
|
86
93
|
|
87
|
-
|
88
|
-
|
94
|
+
create.users!
|
95
|
+
create.schema!
|
96
|
+
create.data!
|
97
|
+
create.all!
|
98
|
+
TODO
|
99
|
+
|
100
|
+
drop.users! -- [DATABASE]
|
101
|
+
@ Drop database users
|
102
|
+
|
103
|
+
Drops all database users except the database owner
|
104
|
+
|
105
|
+
drop.owner! -- [DATABASE]
|
106
|
+
Drop database owner
|
89
107
|
|
90
|
-
|
91
|
-
|
92
|
-
|
108
|
+
drop.database! -- [DATABASE]
|
109
|
+
Drop database
|
110
|
+
|
111
|
+
drop.schema! -- [DATABASE] [SCHEMA...]
|
112
|
+
@ Drop schemas
|
113
|
+
|
114
|
+
Drops the given schemas or all schemas if called without arguments. The
|
115
|
+
'prick' schema is only deleted if named explicity
|
116
|
+
|
117
|
+
drop.data!
|
118
|
+
@ Drop data
|
119
|
+
|
120
|
+
TODO
|
93
121
|
|
94
122
|
build! -f,force -t,time --dump=KIND? -- [SCHEMA]
|
95
123
|
Build the project. If SCHEMA is defined, later schemas are excluded.
|
@@ -112,6 +140,9 @@ SPEC = %(
|
|
112
140
|
|
113
141
|
# TODO: A --clean option that resets data
|
114
142
|
|
143
|
+
version!
|
144
|
+
Print project version
|
145
|
+
|
115
146
|
release! -- KIND
|
116
147
|
Create a release of the given kind. KIND can be 'major', 'minor', or
|
117
148
|
'patch'. Release checks that the current repo is clean and up to date
|
@@ -120,146 +151,279 @@ SPEC = %(
|
|
120
151
|
migrate! -f,file=FILE
|
121
152
|
Execute a migration
|
122
153
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
154
|
+
list.environments! -l,long
|
155
|
+
List available environments (environments with a comment field)
|
156
|
+
|
157
|
+
list.databases! -l,long
|
158
|
+
List Prick databases. The --long option creates a table-like output
|
159
|
+
|
160
|
+
list.users!
|
161
|
+
List database users in the current environment
|
162
|
+
|
163
|
+
list.owners! -l,long
|
164
|
+
List database owners
|
165
|
+
|
166
|
+
list.variables! -l,long -a,all
|
167
|
+
List variables for the current environment
|
129
168
|
|
130
169
|
dump.migration! --force -- VERSION
|
170
|
+
|
171
|
+
dump.type!
|
172
|
+
Dumps a PgGraph object
|
173
|
+
|
174
|
+
dump.variable! -x,export -l,local -- [VARIABLE...]
|
175
|
+
Dumps a bash source snippets that sets and optionally exports values from
|
176
|
+
the configuration, environment, and state. Environment is only dumped if
|
177
|
+
the current environment is defined in the state file. The state file may
|
178
|
+
be absent in which case the related variables are also left undefined
|
179
|
+
|
180
|
+
dump.value! -- VARIABLE...
|
181
|
+
Dumps values of the given variables. Multiple variables can be read into bash
|
182
|
+
variables using read:
|
183
|
+
|
184
|
+
read name title <<< $(prick dump value PRICK_NAME PRICK_TITLE)
|
185
|
+
|
186
|
+
dump.node!
|
187
|
+
Dump build nodes
|
188
|
+
|
189
|
+
dump.build!
|
190
|
+
dump.data! @ TODO
|
191
|
+
dump.schema! @ TODO
|
192
|
+
dump.database! @ TODO
|
193
|
+
TODO
|
131
194
|
)
|
132
195
|
|
133
|
-
|
196
|
+
def require_db(database = Prick.state&.database, exist: true)
|
197
|
+
database or raise ArgumentError
|
198
|
+
dba = State.connection
|
199
|
+
if exist
|
200
|
+
dba.rdbms.exist?(database) or Prick.error "Can't find database '#{database}'"
|
201
|
+
if Prick.state&.connection&.name == database
|
202
|
+
close_conn = false
|
203
|
+
conn = Prick.state.conn
|
204
|
+
else
|
205
|
+
close_conn = true
|
206
|
+
conn = PgConn.new(database)
|
207
|
+
end
|
208
|
+
conn.schema.exist?("prick") or Prick.error "Database '#{database}' is not a Prick database"
|
209
|
+
conn.close if close_conn # Close session explicitly so we can drop database if required
|
210
|
+
else
|
211
|
+
!dba.rdbms.exist?(database) or Prick.error "Database '#{database}' exists"
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
def parse_database_args(state, args)
|
216
|
+
arg, environment = args.expect(0..2)
|
217
|
+
if arg
|
218
|
+
if arg =~ /^(.*)@(.*)$/
|
219
|
+
username, database = $1, $2
|
220
|
+
else
|
221
|
+
database = arg
|
222
|
+
username = database
|
223
|
+
end
|
224
|
+
else
|
225
|
+
database = state.name
|
226
|
+
username = database
|
227
|
+
end
|
228
|
+
database or Prick.error "Database is undefined"
|
229
|
+
[username, database, environment]
|
230
|
+
end
|
231
|
+
|
232
|
+
begin
|
233
|
+
# Parse command line
|
234
|
+
opts, args = ShellOpts.process(SPEC, ARGV, exception: true)
|
235
|
+
|
236
|
+
# Honor -C option
|
237
|
+
begin
|
238
|
+
Dir.chdir(opts.directory) if opts.directory?
|
239
|
+
rescue Errno::ENOENT
|
240
|
+
raise ShellOpts::Error, "Can't cd to '#{opts.directory}'"
|
241
|
+
end
|
242
|
+
rescue ShellOpts::Error => ex
|
243
|
+
ShellOpts.error(ex.message)
|
244
|
+
end
|
245
|
+
|
246
|
+
# Require prick only after -C directory option because some constants depends
|
247
|
+
# on the current directory
|
248
|
+
require_relative '../lib/prick.rb'
|
249
|
+
include Prick
|
134
250
|
|
135
251
|
begin
|
136
252
|
# Handle verbose and quiet
|
137
253
|
$verbose = opts.verbose?
|
138
254
|
$quiet = opts.quiet?
|
139
255
|
|
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
|
256
|
+
# Expect a sub-command. TODO: Make this a built-in in ShellOpts#subcommand!
|
257
|
+
cmd = opts.subcommand! or Prick.error "Subcomand expected"
|
152
258
|
|
153
|
-
#
|
154
|
-
|
259
|
+
# Handle -p, -e, and -c. TODO: Take -C into account for relative paths. Low-hanging fruit
|
260
|
+
project_file = opts.project_file || PRICK_PROJECT_PATH
|
261
|
+
environment_file = opts.environment_file || PRICK_ENVIRONMENT_PATH
|
262
|
+
state_file = opts.state_file || PRICK_STATE_PATH
|
155
263
|
|
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
|
264
|
+
# Process init command and exit
|
265
|
+
if opts.subcommand == :init!
|
266
|
+
dir, name = Prick::SubCommand.init(project_file, args.expect(0..1), cmd.name, cmd.title)
|
267
|
+
Prick.mesg "Initialized Prick project '#{name}' in #{File.absolute_path(dir)}/"
|
164
268
|
exit
|
165
269
|
end
|
166
270
|
|
167
|
-
# Check
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
271
|
+
# Check for prick project
|
272
|
+
if ![:teardown!, :clean!].include?(opts.subcommand) || args.size == 0
|
273
|
+
# We test for the presense of the schema directory to verify we're in a
|
274
|
+
# prick directory. Checking for a configuration file doesn't work because
|
275
|
+
# they can be placed elsewhere. TODO: This require us to check for project file manually
|
276
|
+
# File.directory? "schema" or Prick.error "Not in a prick project directory"
|
277
|
+
File.directory?(SCHEMA_DIR) or Prick.error "Not in a prick project directory"
|
278
|
+
File.exist?(project_file) or Prick.error "Can't find project file '#{project_file}'"
|
279
|
+
end
|
173
280
|
|
174
281
|
# 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
|
282
|
+
state = Prick.state = State.new(project_file, environment_file, state_file)
|
181
283
|
|
182
|
-
#
|
183
|
-
|
284
|
+
# Lazyness
|
285
|
+
database = state.database
|
286
|
+
username = state.username
|
287
|
+
environment = state.environment
|
184
288
|
|
185
289
|
# Process subcommands
|
186
290
|
case opts.subcommand
|
187
291
|
when :version!
|
188
292
|
puts "#{Prick.state.name}-#{Prick.state.version}"
|
189
293
|
|
190
|
-
when :env!
|
191
|
-
env = args.expect(1)
|
192
|
-
Prick.state.environment = env
|
193
|
-
Prick.state.save
|
194
|
-
|
195
294
|
when :setup!
|
196
|
-
Prick
|
295
|
+
state.project_loaded? or Prick.error "No #{project_file} found"
|
296
|
+
username, database, environment = parse_database_args(state, args)
|
297
|
+
require_db(database, exist: false)
|
298
|
+
Prick::SubCommand.setup(database, username, environment)
|
197
299
|
|
300
|
+
# FIXME Ensure that we never drop the current user
|
198
301
|
when :teardown!
|
199
|
-
|
302
|
+
if args.empty?
|
303
|
+
Prick::SubCommand.teardown(database, remove_state_file: true)
|
304
|
+
else
|
305
|
+
Prick::SubCommand.teardown(args)
|
306
|
+
end
|
307
|
+
|
308
|
+
when :get!
|
309
|
+
case cmd.subcommand
|
310
|
+
when :database!; puts database
|
311
|
+
when :username!; puts username
|
312
|
+
when :environment!; puts environment
|
313
|
+
else
|
314
|
+
raise ArgumentError
|
315
|
+
end
|
316
|
+
|
317
|
+
when :set!
|
318
|
+
variable, *args = args.expect(1..3)
|
319
|
+
require_db(database) if variable == "duration"
|
320
|
+
Prick::SubCommand.set(variable, *args) or error "Illegal variable name '#{variable}'"
|
200
321
|
|
201
322
|
when :clean!
|
323
|
+
database = args.expect(0..1) || database
|
324
|
+
require_db(database)
|
202
325
|
Prick::SubCommand.clean(database)
|
203
326
|
|
204
327
|
when :create!
|
205
|
-
create_command = opts.create!
|
328
|
+
create_command = opts.create! # Because we need easy access to subcommand options
|
206
329
|
case create_command.subcommand
|
207
|
-
when :
|
330
|
+
when :database!
|
331
|
+
database, username, environment = parse_database_args(state, args)
|
332
|
+
require_db(database, exist: false)
|
333
|
+
Prick::SubCommand.create_database(database, username, environment)
|
334
|
+
when :migration!
|
335
|
+
require_db
|
208
336
|
arg = args.expect(1)
|
209
|
-
version = PrickVersion.try(arg) or
|
337
|
+
version = PrickVersion.try(arg) or Prick.error "Illegal version: #{arg}"
|
210
338
|
Prick::SubCommand.create_migration(
|
211
339
|
username, version,
|
212
340
|
force: create_command.subcommand!.force?,
|
213
341
|
file: create_command.subcommand!.file)
|
342
|
+
when :users, :schema, :data, :all
|
343
|
+
raise NotImplementedError
|
214
344
|
else
|
215
|
-
raise
|
345
|
+
raise ArgumentError
|
216
346
|
end
|
217
347
|
|
218
348
|
when :build!
|
349
|
+
require_db
|
219
350
|
dump = cmd.dump? ? cmd.dump("batches")&.to_sym || :batches : nil
|
220
351
|
# exclude = cmd.exclude? ? cmd.exclude.split(",") : []
|
221
352
|
Prick::SubCommand.build(
|
222
353
|
database, username, args.expect(0..1), force: cmd.force?, timer: cmd.time?, dump: dump)
|
223
354
|
|
224
355
|
when :make!
|
356
|
+
require_db
|
225
357
|
dump = cmd.dump? ? cmd.dump("batches")&.to_sym || :batches : nil
|
226
358
|
Prick::SubCommand.make(database, username, args.expect(0..1), timer: cmd.time?, dump: dump)
|
227
359
|
|
228
360
|
when :fox!
|
361
|
+
require_db
|
229
362
|
Prick::SubCommand.fox(database, username, args)
|
230
363
|
|
231
364
|
when :drop!
|
232
|
-
case
|
233
|
-
when :
|
234
|
-
|
235
|
-
|
365
|
+
case cmd.subcommand
|
366
|
+
when :users!
|
367
|
+
# Should set state.username to owner of database
|
368
|
+
database = state.database = args.expect(0..1) || database
|
369
|
+
username = state.username = State.connection.rdbms.owner(database)
|
370
|
+
require_db(database)
|
236
371
|
Prick::SubCommand.drop_users(database)
|
237
|
-
when :
|
238
|
-
|
239
|
-
|
372
|
+
when :owner!
|
373
|
+
owner = args.expect(0..1) || username
|
374
|
+
Prick::SubCommand.drop_owner(owner)
|
375
|
+
when :database!
|
376
|
+
database = args.expect(0..1) || database
|
240
377
|
Prick::SubCommand.drop_database(database)
|
241
|
-
when :data
|
378
|
+
when :data!
|
242
379
|
raise NotImplementedError
|
380
|
+
when :schema!
|
381
|
+
require_db
|
382
|
+
schemas = args.to_a
|
383
|
+
Prick::SubCommand.drop_schema(database, schemas)
|
243
384
|
else
|
244
|
-
|
385
|
+
Prick.error "Unknown subject: #{subject}"
|
245
386
|
end
|
246
387
|
|
247
388
|
when :release!
|
248
389
|
kind = args.expect(1).to_sym
|
249
390
|
constrain? kind, :major, :minor, :patch or
|
250
|
-
|
391
|
+
Prick.failure "Expected 'major', 'minor', or 'patch' argument, got '#{kind}'"
|
251
392
|
Prick::SubCommand.release(kind)
|
252
393
|
|
253
394
|
when :migrate!
|
395
|
+
require_db
|
254
396
|
args.expect(0)
|
255
397
|
Prick::SubCommand.migrate(database, username, file: cmd.file)
|
256
398
|
|
399
|
+
when :list!
|
400
|
+
format = (cmd.subcommand!.long? ? :long : :short) if cmd.subcommand && cmd.subcommand != :users!
|
401
|
+
case cmd.subcommand
|
402
|
+
when :environments!; Prick::SubCommand.list_environments(format: format)
|
403
|
+
when :databases!; Prick::SubCommand.list_databases(format: format)
|
404
|
+
when :variables!;
|
405
|
+
all = cmd.subcommand!.all?
|
406
|
+
Prick::SubCommand.list_variables(format: format, all: all)
|
407
|
+
when :users!; Prick::SubCommand.list_users
|
408
|
+
when :owners!; Prick::SubCommand.list_owners(format: format)
|
409
|
+
else
|
410
|
+
Prick.error "Unknown subcommand '#{cmd.subcommand || args.first }'"
|
411
|
+
end
|
412
|
+
|
257
413
|
when :dump!
|
258
414
|
subject = cmd.subcommand!
|
259
415
|
case cmd.subcommand
|
416
|
+
when :node!
|
417
|
+
conn = PgConn.new(database, username)
|
418
|
+
builder = Prick::Build::Builder.new(conn, Prick::SCHEMA_DIR)
|
419
|
+
builder.root.dump
|
420
|
+
when :build!
|
421
|
+
conn = PgConn.new(database, username)
|
422
|
+
builder = Prick::Build::Builder.new(conn, Prick::SCHEMA_DIR)
|
423
|
+
# FIXME Nothing happens here
|
260
424
|
when :migration!
|
261
425
|
arg = args.expect(1)
|
262
|
-
version = PrickVersion.try(arg) or
|
426
|
+
version = PrickVersion.try(arg) or Prick.error "Illegal version number: #{arg}"
|
263
427
|
Prick::SubCommand.create_migration(username, version, force: subject.force?, file: "/dev/stdout")
|
264
428
|
when :type!
|
265
429
|
conn = PgConn.new(database, username)
|
@@ -269,15 +433,24 @@ begin
|
|
269
433
|
graph.dump
|
270
434
|
when :data!, :schema!, :database!
|
271
435
|
raise NotImplementedError
|
272
|
-
when :
|
273
|
-
|
436
|
+
when :variable!
|
437
|
+
scope =
|
438
|
+
case [subject.export?, subject.local?]
|
439
|
+
in [true, false]; :global
|
440
|
+
in [false, true]; :local
|
441
|
+
in [false, false]; nil
|
442
|
+
else
|
443
|
+
Prick.error "Conflicting options - --export and --local"
|
444
|
+
end
|
445
|
+
puts state.bash_source(args.first ? args : nil, scope: scope)
|
446
|
+
when :value!
|
447
|
+
puts args.expect(1..).map { |var| Array(state.bash_environment[var]).join(' ') }
|
274
448
|
else
|
275
|
-
|
449
|
+
object = args.extract(1) # Fails if object is absent
|
450
|
+
Prick.error "Unknown dump object: #{object}"
|
276
451
|
end
|
277
|
-
|
278
|
-
|
279
|
-
else
|
280
|
-
raise Prick::Fail, "Internal error: Unhandled command - #{opts.subcommand.inspect}"
|
452
|
+
else
|
453
|
+
Prick.failure "Internal error: Unhandled command - #{opts.subcommand.inspect}"
|
281
454
|
end
|
282
455
|
|
283
456
|
rescue Prick::Build::PostgresError => ex
|
@@ -295,409 +468,11 @@ rescue Prick::Build::PostgresError => ex
|
|
295
468
|
end
|
296
469
|
exit 1
|
297
470
|
|
298
|
-
rescue RuntimeError, IOError, ShellOpts::Failure, Prick::Fail, Prick::Build::PostgresError => ex
|
299
|
-
ShellOpts.failure(ex.message)
|
300
|
-
|
301
471
|
rescue ShellOpts::Error, Prick::Error => ex
|
472
|
+
raise
|
302
473
|
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
474
|
|
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)
|
475
|
+
rescue RuntimeError, IOError, ShellOpts::Failure, Prick::Failure, Prick::Build::PostgresError => ex
|
476
|
+
ShellOpts.failure(ex.message)
|
649
477
|
end
|
650
478
|
|
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
|
-
)
|