prick 0.28.1 → 0.29.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/exe/prick +69 -17
  3. data/lib/{builder → prick/builder}/batch.rb +34 -25
  4. data/lib/{builder → prick/builder}/builder.rb +12 -1
  5. data/lib/{builder → prick/builder}/parser.rb +25 -66
  6. data/lib/prick/constants.rb +4 -0
  7. data/lib/prick/environment.rb +134 -0
  8. data/lib/{ext → prick/ext}/expand_variables.rb +16 -3
  9. data/lib/prick/local/ansi.rb +6 -0
  10. data/lib/prick/state.rb +86 -44
  11. data/lib/{subcommand → prick/subcommand}/prick-build.rb +9 -8
  12. data/lib/prick/subcommand/prick-clean.rb +17 -0
  13. data/lib/{subcommand → prick/subcommand}/prick-drop.rb +11 -6
  14. data/lib/prick/version.rb +1 -1
  15. data/lib/prick.rb +22 -19
  16. data/prick.environments.yml +14 -0
  17. data/prick.gemspec +1 -0
  18. metadata +57 -40
  19. data/lib/share/init/.prick-context +0 -2
  20. /data/lib/{builder → prick/builder}/node.rb +0 -0
  21. /data/lib/{builder → prick/builder}/node_pool.rb +0 -0
  22. /data/lib/{local → prick/local}/command.rb +0 -0
  23. /data/lib/{local → prick/local}/git.rb +0 -0
  24. /data/lib/{local → prick/local}/timer.rb +0 -0
  25. /data/lib/{share → prick/share}/init/.gitignore +0 -0
  26. /data/lib/{share → prick/share}/init/.rspec +0 -0
  27. /data/lib/{share → prick/share}/init/migration/.keep +0 -0
  28. /data/lib/{share → prick/share}/init/prick.yml +0 -0
  29. /data/lib/{share → prick/share}/init/schema/.keep +0 -0
  30. /data/lib/{share → prick/share}/init/schema/build.yml +0 -0
  31. /data/lib/{share → prick/share}/init/schema/prick/.keep +0 -0
  32. /data/lib/{share → prick/share}/init/schema/prick/build.yml +0 -0
  33. /data/lib/{share → prick/share}/init/schema/prick/data.sql +0 -0
  34. /data/lib/{share → prick/share}/init/schema/prick/tables.sql +0 -0
  35. /data/lib/{share → prick/share}/init/schema/public/.keep +0 -0
  36. /data/lib/{share → prick/share}/init/spec/prick_helper.rb +0 -0
  37. /data/lib/{share → prick/share}/init/spec/prick_spec.rb +0 -0
  38. /data/lib/{share → prick/share}/init/spec/spec_helper.rb +0 -0
  39. /data/lib/{share → prick/share}/migrate/migration/build.yml +0 -0
  40. /data/lib/{share → prick/share}/migrate/migration/diff.after-tables.sql +0 -0
  41. /data/lib/{share → prick/share}/migrate/migration/diff.before-tables.sql +0 -0
  42. /data/lib/{share → prick/share}/migrate/migration/diff.tables.sql +0 -0
  43. /data/lib/{subcommand → prick/subcommand}/prick-create.rb +0 -0
  44. /data/lib/{subcommand → prick/subcommand}/prick-fox.rb +0 -0
  45. /data/lib/{subcommand → prick/subcommand}/prick-init.rb +0 -0
  46. /data/lib/{subcommand → prick/subcommand}/prick-make.rb +0 -0
  47. /data/lib/{subcommand → prick/subcommand}/prick-migrate.rb +0 -0
  48. /data/lib/{subcommand → prick/subcommand}/prick-release.rb +0 -0
  49. /data/lib/{subcommand → prick/subcommand}/prick-setup.rb +0 -0
  50. /data/lib/{subcommand → prick/subcommand}/prick-teardown.rb +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 10bf0db9a65cd8441d8f17ea9ad055f177d49508f2445ee733722fcc0fb5c6dc
4
- data.tar.gz: 693a602c5f57b6bdd97cdefa00c69a0c517cd54e4b32e2d10657fa1c8cfb8949
3
+ metadata.gz: 21dec70a7d5860aa9e3731a5213559bf1eef4b94de999d180de823e7d66ac615
4
+ data.tar.gz: 2ab02d0286f9881568b1170cd63311150260f7cd990e4c32d43c42bfa2f072dc
5
5
  SHA512:
6
- metadata.gz: 1ec3e792b312d572d9eb65feb3c595d94ec944b9854f12c9f16a805dfce24a45d0be6fe923c02fc1bf57c9a3ce0d6b221c28eaeaea5a1ab1a0f044e228a07b5e
7
- data.tar.gz: a0cc6eb39133fbfc7eef170a173378bd685a3f43315ac633748dc1fafa02589dae100d1fe8f30ab4687a175e3d8a13d0fca793245fbb10fb2297fed5d8e4c659
6
+ metadata.gz: 102695943884b0aa0e91830f5cc4059e80d57f1a7f23d39fa332097b39ca0e0116b11367f6db679df7d128efe4612290d6c47fc67bf7be207e1f0e645e0365e7
7
+ data.tar.gz: 77daad11d1dd47dba7f63d0a897b3d229be04063698880eba6294ebb2ebd112ce0f21e7d7c480aa1b5ac7992469283da54f1281cfa77b4b48d1594158ff2643a
data/exe/prick CHANGED
@@ -13,8 +13,8 @@ begin
13
13
  # Bootsnap.instrumentation = ->(event, path) { puts "#{event} #{path}" }
14
14
  end
15
15
 
16
- require 'prick.rb'
17
16
  require 'shellopts'
17
+ require_relative '../lib/prick.rb'
18
18
 
19
19
  include ShellOpts
20
20
  include Prick
@@ -34,10 +34,19 @@ SPEC = %(
34
34
  Change to directory DIR before doing anything else
35
35
 
36
36
  -d,database=DATABASE
37
- Override database name from prick.yml
37
+ Override database name. Default is read from .prick.context
38
38
 
39
39
  -U,username=USERNAME
40
- Override username from from prick.yml
40
+ Override username. Default is read from .prick.context
41
+
42
+ -e,environment=ENVIRONMENT
43
+ Override environment. Default is read from from .prick.context
44
+
45
+ -p,project=PRICK-FILE
46
+ Override default environment file ('prick.yml')
47
+
48
+ -c,context=CONTEXT-FILE
49
+ Override default context file ('.prick.context')
41
50
 
42
51
  version!
43
52
  Print project version
@@ -58,6 +67,9 @@ SPEC = %(
58
67
  teardown!
59
68
  Drop the database and the database user. TODO: Also run teardown scripts
60
69
 
70
+ clean!
71
+ Empties the database and drops related users except the database user
72
+
61
73
  create.data!
62
74
  create.schema!
63
75
  create.database!
@@ -75,8 +87,9 @@ SPEC = %(
75
87
  drop! -- [KIND]
76
88
  @ Drop objects
77
89
 
78
- Kind can be 'users', 'data', 'schema', 'database' (the default), or 'all'. It is
79
- not an error if the object doesn't exist. TODO Only 'users' is currently defined
90
+ Kind can be 'users', 'data', 'schema', 'user', 'database' (the default),
91
+ or 'all'. It is not an error if the object doesn't exist. TODO 'data' and
92
+ 'schema' is not implemented
80
93
 
81
94
  build! -f,force -t,time --dump=KIND? -- [SCHEMA]
82
95
  Build the project. If SCHEMA is defined, later schemas are excluded.
@@ -94,7 +107,10 @@ SPEC = %(
94
107
 
95
108
  fox! -- FILE...
96
109
  Load fox file data. Data are reset to their initial state after build
97
- before the fox data are loaded
110
+ before the fox data are loaded. This makes it possible to experiment with
111
+ different data sets
112
+
113
+ # TODO: A --clean option that resets data
98
114
 
99
115
  release! -- KIND
100
116
  Create a release of the given kind. KIND can be 'major', 'minor', or
@@ -108,6 +124,7 @@ SPEC = %(
108
124
  dump.data!
109
125
  dump.schema!
110
126
  dump.database!
127
+ dump.environment!
111
128
  TODO
112
129
 
113
130
  dump.migration! --force -- VERSION
@@ -150,13 +167,18 @@ begin
150
167
  # Check state
151
168
  File.exist?(PRICK_PROJECT_FILE) or raise Prick::Error, "Not in a prick project directory"
152
169
 
170
+ # Handle -p and -c
171
+ project_file = opts.project || PRICK_PROJECT_PATH
172
+ context_file = opts.context || PRICK_CONTEXT_PATH
173
+
153
174
  # Load state
154
- Prick.state = State.load
175
+ state = Prick.state = State.load(project_file, context_file)
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
155
181
 
156
- # Handle -d and -U options
157
- database = opts.database || Prick.state.database
158
- username = opts.username || Prick.state.username
159
-
160
182
  # Expect a sub-command
161
183
  cmd = opts.subcommand! or raise Prick::Error, "Subcomand expected"
162
184
 
@@ -176,6 +198,9 @@ begin
176
198
  when :teardown!
177
199
  Prick::SubCommand.teardown(database, username)
178
200
 
201
+ when :clean!
202
+ Prick::SubCommand.clean(database)
203
+
179
204
  when :create!
180
205
  create_command = opts.create!
181
206
  case create_command.subcommand
@@ -186,14 +211,15 @@ begin
186
211
  username, version,
187
212
  force: create_command.subcommand!.force?,
188
213
  file: create_command.subcommand!.file)
189
- else
190
- raise NotImplementedError
214
+ else
215
+ raise NotImplementedError
191
216
  end
192
217
 
193
218
  when :build!
194
219
  dump = cmd.dump? ? cmd.dump("batches")&.to_sym || :batches : nil
220
+ # exclude = cmd.exclude? ? cmd.exclude.split(",") : []
195
221
  Prick::SubCommand.build(
196
- database, username, args.expect(0..1), force: cmd.force?, timer: cmd.time?, dump: dump)
222
+ database, username, args.expect(0..1), force: cmd.force?, timer: cmd.time?, dump: dump)
197
223
 
198
224
  when :make!
199
225
  dump = cmd.dump? ? cmd.dump("batches")&.to_sym || :batches : nil
@@ -208,6 +234,8 @@ begin
208
234
  Prick::SubCommand.drop_all(database)
209
235
  when :users
210
236
  Prick::SubCommand.drop_users(database)
237
+ when :user
238
+ Prick::SubCommand.drop_user(username)
211
239
  when :database
212
240
  Prick::SubCommand.drop_database(database)
213
241
  when :data, :schema
@@ -229,20 +257,44 @@ begin
229
257
  when :dump!
230
258
  subject = cmd.subcommand!
231
259
  case cmd.subcommand
232
- when :migration
260
+ when :migration!
233
261
  arg = args.expect(1)
234
262
  version = PrickVersion.try(arg) or raise "Illegal version number: #{arg}"
235
263
  Prick::SubCommand.create_migration(username, version, force: subject.force?, file: "/dev/stdout")
236
- when :data, :schema, :database
264
+ when :type!
265
+ conn = PgConn.new(database, username)
266
+ builder = Prick::Build::Builder.new(conn, Prick::SCHEMA_DIR)
267
+ meta = PgMeta.new(conn, exclude_schemas: builder.pg_graph_ignore_schemas)
268
+ graph = PgGraph::Type.new(meta, builder.reflections_file)
269
+ graph.dump
270
+ when :data!, :schema!, :database!
237
271
  raise NotImplementedError
272
+ when :environment!
273
+ puts state.bash_source
238
274
  else
239
- raise Prick::Error, "Unknown subject: #{subject.inspect}"
275
+ raise Prick::Error, "Unknown dump object: #{cmd.subcommand!.__name__}"
240
276
  end
241
277
 
278
+
242
279
  else
243
280
  raise Prick::Fail, "Internal error: Unhandled command - #{opts.subcommand.inspect}"
244
281
  end
245
282
 
283
+ rescue Prick::Build::PostgresError => ex
284
+ $stderr.puts "Error: #{ex.message}"
285
+ if STDERR.tty?
286
+ file, lineno, charno = ex.err
287
+ if file && lineno
288
+ lines = IO.readlines(file).map(&:chomp)
289
+ i = lineno - 1
290
+ from = [i - 10, 0].max
291
+ to = [i + 10, lines.size].min
292
+ $stderr.puts
293
+ $stderr.puts lines[from...i], lines[i].bold, lines[i+1...to]
294
+ end
295
+ end
296
+ exit 1
297
+
246
298
  rescue RuntimeError, IOError, ShellOpts::Failure, Prick::Fail, Prick::Build::PostgresError => ex
247
299
  ShellOpts.failure(ex.message)
248
300
 
@@ -14,10 +14,10 @@ module Prick
14
14
  @nodes = []
15
15
  end
16
16
 
17
- def execute(&block)
17
+ def execute(**opts, &block)
18
18
  name = self.class.to_s.sub(/.*::/, "").split(/(?=[A-Z])/).map(&:downcase).join(" ")
19
19
  time "Execute #{name} (nodes: #{nodes.size})" do
20
- yield
20
+ yield(**opts)
21
21
  end
22
22
  end
23
23
 
@@ -28,23 +28,38 @@ module Prick
28
28
  end
29
29
 
30
30
  class SqlBatch < BuildBatch
31
- def execute
31
+ def execute(step: true) # This is marginally faster!
32
32
  super {
33
33
  begin
34
34
  sql = []
35
+ file = nil
36
+ node = nil
37
+
35
38
  # A SQL batch allows the first node to be an evaluated or executed node
36
39
  if nodes.first.is_a?(CommandNode)
37
- time "Execute script" do
38
- sql = [nodes.first.source]
40
+ node = nodes.shift
41
+ sql = [node.source]
42
+ end
43
+
44
+ if step
45
+ conn.execute sql, silent: true if !sql.empty?
46
+ for node in nodes
47
+ conn.execute node.source, silent: true
39
48
  end
49
+ else
50
+ node = nil
51
+ conn.execute sql + nodes[sql.size..-1].map(&:source), silent: true
40
52
  end
41
- conn.execute sql + nodes[sql.size..-1].map(&:source)
42
53
 
43
- rescue PG::SyntaxError, PG::Error => ex
44
- error, line, pos = parse_pg_message(ex.message)
45
- if line
54
+ rescue PG::Error => ex
55
+ error, line, char = conn.err
56
+ file = nil
57
+ if step
58
+ ;
59
+ elsif line
60
+ # Locate error node and make line number relative
46
61
  if line < nodes.first.lines
47
- node = nodes.first;
62
+ node = nodes.first
48
63
  else
49
64
  line -= nodes.first.lines
50
65
  node = nodes[1..-1].find { |node|
@@ -58,26 +73,20 @@ module Prick
58
73
  end
59
74
  }
60
75
  end
76
+ # file = node.path
77
+ end
61
78
 
62
- if node.is_a?(SqlNode)
63
- message = ["prick: #{error} in #{node.path}", line, pos].compact.join(":")
64
- else
65
- message = "prick: #{error} from #{node.path}"
66
- end
79
+ if node.is_a?(SqlNode)
80
+ message = ["#{error} in #{node.path}", line, char].compact.join(":")
81
+ elsif node
82
+ message = "#{error} from #{node.path}"
67
83
  else
68
- raise
84
+ message = conn.errmsg + " in SQL batch"
69
85
  end
70
- raise PostgresError.new(message)
86
+ raise PostgresError.new(message, file, line, char)
71
87
  end
72
88
  }
73
89
  end
74
-
75
- private
76
- # Returns [error, line, pos] tuple
77
- def parse_pg_message(message)
78
- message =~ /ERROR:\s*(.*?)\n(LINE (\d+): ).*?\n(\s*\^)/m or return nil
79
- [$1, $3.to_i, $4.size - $2.size]
80
- end
81
90
  end
82
91
 
83
92
  class ModuleBatch < BuildBatch
@@ -139,7 +148,7 @@ module Prick
139
148
  # FIXME: Why only in FoxBatch - should be set higher up in the system
140
149
  conn.execute "update prick.versions set built_at = now() at time zone 'UTC'"
141
150
  rescue PG::SyntaxError, PG::Error => ex
142
- raise PostgresError, "prick: #{ex.message}"
151
+ raise PostgresError.new(ex.message)
143
152
  end
144
153
  }
145
154
  t_type.emit
@@ -10,7 +10,18 @@ include Constrain
10
10
  module Prick
11
11
  module Build
12
12
  class Error < StandardError; end
13
- class PostgresError < Error; end
13
+ class PostgresError < Error
14
+ attr_reader :file
15
+ attr_reader :lineno
16
+ attr_reader :charno
17
+
18
+ def initialize(message, file = nil, lineno = nil, charno = nil)
19
+ super(message)
20
+ @file, @lineno, @charno = file, lineno, charno
21
+ end
22
+
23
+ def err = [@file, @lineno, @charno]
24
+ end
14
25
 
15
26
  class Builder
16
27
  # PgConn object
@@ -34,7 +34,7 @@ module Prick
34
34
  end
35
35
  end
36
36
 
37
- # Search for an executable in path
37
+ # Search for an executable in path. Return nil if not found
38
38
  def find_executable(filename) # ChatGPT
39
39
  Prick.state.executable_search_path.split(File::PATH_SEPARATOR).each do |directory|
40
40
  path = File.join(directory, filename)
@@ -43,80 +43,37 @@ module Prick
43
43
  nil
44
44
  end
45
45
 
46
- # Expand $ENVIRONMENT variable in file names. The function implements a
47
- # hierarchy of environments:
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
48
49
  #
49
- # production
50
- # (online)
51
- # development
52
- # online
53
- # offline
54
- # backend
55
- # frontend
56
- # test
57
- #
58
- # If an environment doesn't exist in #dir, then the higher level
59
- # environments are tried in turn. Eg. if the current environment is
60
- # 'test', the algorithm expands '$ENVIRONMENT' to 'test', 'offline', and
61
- # 'development' until an existing file is found. If no file is found the
62
- # the unexpanded value is returned
63
- #
64
- # The production environment acts as a online environment but not a
65
- # development environment. This means it will first search for
66
- # 'production', then 'online', and then stop without searching for
67
- # 'development'
68
- #
69
- # NOTE: This is a hardcoded feature for an internal project. It is
70
- # configurable in the next major version
71
- #
72
- # TODO: Refactor: dir is not handled well when the filename includes a
73
- # $PWD variblea
50
+ # The hierarchy of environments is defined in the PRICK_ENVIRONMENT_FILE
74
51
  #
75
52
  def expand_filename(dir, filename)
76
- # Expand variables
77
- path = expand_variables(filename, Prick.state.bash_environment)
53
+ environment = Prick.state.environment
54
+ bash_vars = Prick.state.bash_environment
78
55
 
79
- # Use only filename as template if expansion is an absolute path
80
- if path.start_with? "/"
81
- template = filename
82
- else
83
- template = "#{dir}/#{filename}"
84
- path = "#{dir}/#{path}"
85
- end
86
- return path if File.exist?(path)
56
+ last = nil
57
+ for env in [environment] + Environment[environment].ancestors.reverse
58
+ bash_vars["ENVIRONMENT"] = env
59
+ file = expand_variables(filename, bash_vars)
60
+ last ||= (file != last and file) or return nil # return if no ENVIRONMENT substitution
61
+ path = (file.start_with?("/") ? file : File.join(dir, file))
87
62
 
88
- # Iterate through environments
89
- env = Prick.state.environment.to_s
90
- while true
63
+ # Check for file (may be executable)
91
64
  return path if File.exist?(path)
92
- case env
93
- when "production"
94
- file = expand_variables(path, ENVIRONMENT: "online") or return nil
95
- return file if File.exist? file
96
- break
97
- when "development"; break
98
- when "online"; env = "development"
99
- when "offline"; env = "development"
100
- when "backend"; env = "offline"
101
- when "frontend"; env = "offline"
102
- when "test"; env = "offline"
103
- else
104
- raise Error, "Illegal env: '#{env}'"
105
- end
106
- path = expand_variables(template, Prick.state.bash_environment.merge(ENVIRONMENT: env))
107
- end
108
65
 
109
- # Look for executable in PATH
110
- if filename !~ /\// && (path = find_executable(filename))
111
- return path
112
- else
113
- return nil
66
+ # Check for executable in search path
67
+ path = find_executable(file) and return path if file !~ /\//
114
68
  end
69
+
70
+ # Return nil if not found
71
+ return nil
115
72
  end
116
73
 
117
74
  # Expand $ENVIRONMENT variable
118
75
  def expand_string(string)
119
- expand_variables(string, ENVIRONMENT: Prick.state.environment.to_s, PWD: Dir.getwd)
76
+ expand_variables(string, Prick.state.bash_environment)
120
77
  end
121
78
 
122
79
  def parse_directory(parent, dir)
@@ -170,8 +127,9 @@ module Prick
170
127
  if entry =~ /^(\S+?)(\?)?(?:\s+(.+))?\s*$/
171
128
  command = $1
172
129
  optional = !$2.nil?
173
- args = expand_string($3 || '').split
174
- path = expand_filename(dir, command)
130
+ rest = $3
131
+ args = expand_string(rest || '').split
132
+ path = expand_filename(dir, command)
175
133
  path || optional or raise Error, "Can't find '#{entry}' in #{dir}/ from #{unit}"
176
134
  !path.nil? or return nil
177
135
  else
@@ -215,11 +173,12 @@ module Prick
215
173
  SqlNode.new(unit, phase, path)
216
174
  when /\.fox$/
217
175
  FoxNode.new(unit, :seed, path)
176
+ when /build-.*\.yml$/
177
+ parse_build_file(unit, dir, path)
218
178
  else
219
179
  raise Error, "Expected executable, fox, or sql file: #{File.basename(path)} in #{dir}"
220
180
  end
221
181
  else
222
- path =
223
182
  raise Error, "Can't find '#{entry}' in #{dir}/ from #{unit}"
224
183
  end
225
184
  end
@@ -36,6 +36,10 @@ module Prick
36
36
  PRICK_PROJECT_FILE = "prick.yml"
37
37
  PRICK_PROJECT_PATH = PRICK_PROJECT_FILE
38
38
 
39
+ # # Environment specification file
40
+ # PRICK_ENVIRONMENT_FILE = "prick.environment.yml"
41
+ # PRICK_ENVIRONMENTS_PATH = PRICK_ENVIRONMENT_FILE
42
+
39
43
  # Context file
40
44
  PRICK_CONTEXT_FILE = ".prick-context"
41
45
  PRICK_CONTEXT_PATH = PRICK_CONTEXT_FILE
@@ -0,0 +1,134 @@
1
+ require 'yaml'
2
+ require 'dsort'
3
+
4
+ module Prick
5
+ class Environment
6
+ # Environments name
7
+ attr_reader :name
8
+
9
+ # Names of parent environments
10
+ def parents = @values[:parents]
11
+
12
+ # Ancestors sorted in dependency order
13
+ def ancestors
14
+ @ancestors ||= effective_values[:parents].sort_by { |name| @@SORTED_INDEXES[name] }
15
+ end
16
+
17
+ # List of variables including :parents
18
+ def variables = @@VARIABLES
19
+
20
+ # List of user defined variables
21
+ def user_variables = @@VARIABLES - [:parent]
22
+
23
+ # Hash from variable to value
24
+ attr_accessor :values
25
+
26
+ # Hash from variable name to effective value. The effective value is the
27
+ # sum of this environment's value and its parents' values
28
+ attr_accessor :effective_values
29
+
30
+ def self.[](name) @@ENVIRONMENTS[name] end
31
+ def self.environment?(name) @@ENVIRONMENTS.key?(name) end
32
+ def self.environments() @@SORTED_ENVIRONMENTS.map { |key| @@ENVIRONMENTS[key] } end
33
+ def self.variables() @@VARIABLES end
34
+
35
+ def initialize(name)
36
+ @name = name
37
+ @values = variables.map { |key| [key, []] }.to_h
38
+ @effective_values = variables.map { |key| [key, []] }.to_h
39
+ @@ENVIRONMENTS[name] = self
40
+ end
41
+
42
+ def self.load_environments(hash) # hash can be nil
43
+ if hash
44
+ parse(hash)
45
+ analyze
46
+ end
47
+ end
48
+
49
+ # does not include the name of the environment
50
+ def bash_env
51
+ user_variables.map { |variable|
52
+ ["PRICK_ENVIRONMENT_#{variable.upcase}", effective_values[variable]]
53
+ }.to_h
54
+ end
55
+
56
+ def dump
57
+ puts name
58
+ indent {
59
+ values.each { |var, val|
60
+ next if val.empty?
61
+ puts "#{var}:"
62
+ indent { puts val }
63
+ }
64
+ effective_values.each { |var, val|
65
+ next if val.empty?
66
+ puts "effective_#{var}:"
67
+ indent { puts val }
68
+ }
69
+ }
70
+ end
71
+
72
+ def self.dump
73
+ environments.each(&:dump)
74
+ end
75
+
76
+ private
77
+ @@VARIABLES = []
78
+ @@ENVIRONMENTS = {}
79
+ @@SORTED_ENVIRONMENTS = []
80
+
81
+ def self.yaml_to_array(value)
82
+ !value.nil? && Array(value).flatten.compact.map(&:to_s).map(&:split).flatten
83
+ end
84
+
85
+ def self.parse(hash)
86
+ hash = hash.dup
87
+ @@VARIABLES = [:parents] + (yaml_to_array(hash.delete("variables")).map(&:to_sym) || [])
88
+
89
+ for environment, settings in hash
90
+ env = Environment.new(environment)
91
+ if settings.is_a? Hash
92
+ for variable, value in settings
93
+ variable = (variable == "inherit" ? :parents : variable.to_sym)
94
+ value = yaml_to_array(value)
95
+ if variables.include?(variable)
96
+ env.values[variable] = value
97
+ else
98
+ raise ArgumentError, "Illegal variable: '#{variable}'"
99
+ end
100
+ end
101
+ else
102
+ raise ArgumentError, "Illegal value for '#{environment}': #{settings.inspect}"
103
+ end
104
+ end
105
+ end
106
+
107
+ def self.analyze
108
+ # Sort environments in dependency order
109
+ deps = @@ENVIRONMENTS.map { |name, env| [name, env.parents] }
110
+ @@SORTED_ENVIRONMENTS = DSort.dsort(deps)
111
+ @@SORTED_INDEXES = @@SORTED_ENVIRONMENTS.map.with_index { |env, idx| [env, idx] }.to_h
112
+
113
+ # Check for undeclared inherited environments
114
+ @@SORTED_ENVIRONMENTS.each { |environment|
115
+ @@ENVIRONMENTS.key?(environment) or raise ArgumentError, "Can't find '#{inherited}' environment"
116
+ }
117
+
118
+ # Compute effective attribute values by processing environments in
119
+ # dependency order so that all parents' environments are computed before
120
+ # the current environment
121
+ for name in @@SORTED_ENVIRONMENTS
122
+ env = Environment[name]
123
+ env.effective_values = env.values.transform_values { |v| v.dup } # Deep-dup
124
+ for parent in env.parents.dup
125
+ for var in variables
126
+ env.effective_values[var].unshift *Environment[parent].effective_values[var]
127
+ end
128
+ end
129
+ env.effective_values.transform_values! { |v| v.uniq }
130
+ end
131
+ end
132
+ end
133
+ end
134
+
@@ -6,7 +6,7 @@
6
6
  # backslash. All occurrences of a variable in the string are replaced
7
7
  #
8
8
  # The str argument is the template string and the variables argument is a hash
9
- # from variable name (Symbol) to variable value
9
+ # from variable name (String) to variable value
10
10
  #
11
11
  # Note that the characters '\x00' and '\x01' are used internally and may not be
12
12
  # present in the template string
@@ -17,11 +17,24 @@ def expand_variables(str, variables) # ChatGPT
17
17
 
18
18
  # Expand variables
19
19
  str.gsub!(/\$(\w+)\b|\$\{(\w+)\}/) do |match| # Strange that '\b' is necessary
20
- key = ($1 || $2).to_sym
21
- variables[key] || match
20
+ key = $1 || $2
21
+ # variables[key] || match
22
+ variables[key] || ""
22
23
  end
23
24
 
24
25
  # Restore escaped characters
25
26
  str.gsub("\x00", '\\').gsub("\x01", '$')
26
27
  end
27
28
 
29
+ # Return true if any of the variables will be expanded
30
+ def expand_variables?(str, variables)
31
+ # Replace escaped bashslashes and dollar signs
32
+ str = str.gsub('\\\\', "\x00").gsub('\\$', "\x01")
33
+
34
+ # Look for expansion
35
+ str.gsub!(/\$(\w+)\b|\$\{(\w+)\}/) do |match| # Strange that '\b' is necessary
36
+ return true if variables.include?($1 || $2)
37
+ end
38
+
39
+ return false
40
+ end
@@ -0,0 +1,6 @@
1
+
2
+ class String
3
+ ANSI_BOLD_START = "\e[1m"
4
+ ANSI_BOLD_STOP = "\e[22m"
5
+ def bold = "#{ANSI_BOLD_START}#{self.to_s}#{ANSI_BOLD_STOP}"
6
+ end
data/lib/prick/state.rb CHANGED
@@ -27,16 +27,22 @@ module Prick
27
27
  # Version of prick(1)
28
28
  attr_accessor :prick_version
29
29
 
30
- # Run-time environment. Can be :production, :development, or :test
31
- attr_accessor :environment
32
-
33
30
  # Name of database
34
31
  attr_accessor :database
35
32
 
36
33
  # Name of database user
37
34
  attr_accessor :username
38
35
 
39
- # Prick project dir. This is not a constant because exe/prick can change directory
36
+ # Run-time environment name
37
+ def environment() @environment end
38
+ def environment=(env)
39
+ constrain env, String
40
+ Environment.environment?(env) or raise "Illegal environment: '#{env}'"
41
+ @environment = env
42
+ end
43
+
44
+ # Prick project dir. This is not a constant because exe/prick can change
45
+ # directory (FIXME it can?)
40
46
  def prick_dir
41
47
  @prick_dir ||= Dir.getwd
42
48
  end
@@ -46,52 +52,54 @@ module Prick
46
52
  @executable_search_path ||= "#{ENV['PATH']}:#{prick_dir}/#{BIN_DIR}:#{prick_dir}/#{LIBEXEC_DIR}"
47
53
  end
48
54
 
49
- def bash_environment
50
- ENV.to_h.merge({
51
- DATABASE: Prick.state.database,
52
- USERNAME: Prick.state.username,
53
- ENVIRONMENT: Prick.state.environment.to_s,
54
- PRICK_DIR: Prick.state.prick_dir,
55
- PRICK_SCHEMADIR: File.join(Prick.state.prick_dir, SCHEMA_DIR),
56
- PRICK_BINDIR: File.join(Prick.state.prick_dir, BIN_DIR),
57
- PRICK_LIBEXECDIR: File.join(Prick.state.prick_dir, LIBEXEC_DIR),
58
- PRICK_VARDIR: File.join(Prick.state.prick_dir, VAR_DIR),
59
- PRICK_CACHEDIR: File.join(Prick.state.prick_dir, CACHE_DIR),
60
- PRICK_SPOOLDIR: File.join(Prick.state.prick_dir, SPOOL_DIR),
61
- PRICK_TMPDIR: File.join(Prick.state.prick_dir, TMP_DIR),
62
- PRICK_CLONEDIR: File.join(Prick.state.prick_dir, CLONE_DIR),
63
- PRICK_SPECDIR: File.join(Prick.state.prick_dir, BIN_DIR),
64
- PATH: Prick.state.executable_search_path
65
- })
66
- end
67
-
68
- def self.load
69
- begin
70
- h = YAML.load(File.read PRICK_PROJECT_PATH)
71
- rescue Errno::ENOENT
72
- raise Prick::Error, "Can't open project file: #{PRICK_PROJECT_PATH}"
73
- end
74
- state = State.new
75
- state.name = h["name"]
76
- state.title = h["title"]
77
- state.version = h["version"] && PrickVersion.new(h["version"])
78
- state.prick_version = h["prick"] && PrickVersion.new(h["prick"])
79
-
80
- begin
81
- h = YAML.load(File.read PRICK_CONTEXT_PATH)
82
- rescue Errno::ENOENT
83
- raise Prick::Error, "Can't open environment file: #{PRICK_CONTEXT_PATH}"
55
+ # Create a bash(1) environment (Hash). It is used for in-prick expansion of
56
+ # variables and also injected into the enviroment of subprocesses
57
+ def bash_environment(scope = :global)
58
+ hash = {
59
+ "DATABASE" => Prick.state.database, # FIXME: Yt
60
+ "USERNAME" => Prick.state.username, # FIXME: Yt
61
+ "ENVIRONMENT" => Prick.state.environment.to_s, # FIXME: Yt
62
+ "PRICK_NAME" => Prick.state.name,
63
+ "PRICK_TITLE" => Prick.state.title,
64
+ "PRICK_VERSION" => Prick.state.version,
65
+ "PRICK_DATABASE" => Prick.state.database,
66
+ "PRICK_USERNAME" => Prick.state.username,
67
+ "PRICK_ENVIRONMENT" => Prick.state.environment.to_s,
68
+ }
69
+ case scope
70
+ when :local; # nop
71
+ hash.merge Environment[Prick.state.environment].bash_env
72
+ when :global;
73
+ ENV.to_h.merge(hash).merge({
74
+ "PATH" => Prick.state.executable_search_path,
75
+ "PRICK_SCHEMADIR" => File.join(Prick.state.prick_dir, SCHEMA_DIR),
76
+ "PRICK_BINDIR" => File.join(Prick.state.prick_dir, BIN_DIR),
77
+ "PRICK_LIBEXECDIR" => File.join(Prick.state.prick_dir, LIBEXEC_DIR),
78
+ "PRICK_VARDIR" => File.join(Prick.state.prick_dir, VAR_DIR),
79
+ "PRICK_CACHEDIR" => File.join(Prick.state.prick_dir, CACHE_DIR),
80
+ "PRICK_SPOOLDIR" => File.join(Prick.state.prick_dir, SPOOL_DIR),
81
+ "PRICK_TMPDIR" => File.join(Prick.state.prick_dir, TMP_DIR),
82
+ "PRICK_CLONEDIR" => File.join(Prick.state.prick_dir, CLONE_DIR),
83
+ "PRICK_SPECDIR" => File.join(Prick.state.prick_dir, BIN_DIR)
84
+ }).merge(Environment[Prick.state.environment].bash_env)
85
+ else
86
+ raise ArgumentError
84
87
  end
85
- state.environment = h["environment"]&.to_sym
86
- state.database = h["database"]
87
- state.username = h["username"]
88
+ end
88
89
 
89
- # TODO Load schema version
90
+ def bash_source
91
+ bash_environment(:local).map { |var,val| "export #{var}=\"#{Array(val).join(' ')}\"\n" }.join
92
+ end
90
93
 
94
+ def self.load(project_file, context_file)
95
+ state = State.new
96
+ state.send(:parse_project_file, project_file || PRICK_PROJECT_PATH)
97
+ state.send(:parse_context_file, context_file || PRICK_CONTEXT_PATH)
91
98
  state
92
99
  end
93
100
 
94
101
  def save
102
+ raise NotImplementedError
95
103
  h = {
96
104
  "name" => name,
97
105
  "title" => title,
@@ -126,11 +134,45 @@ module Prick
126
134
  indent {
127
135
  for method in [
128
136
  :name, :title, :prick_version, :project_version, :schema_version,
129
- :database_version, :environment, :database, :username]
137
+ :database_version, :database, :username]
130
138
  puts "#{method}: #{self.send method}"
131
139
  end
140
+ puts "environments:"
141
+ indent { Environment.dump }
132
142
  }
133
143
  end
144
+
145
+ private
146
+ def load_yaml(file, expected_keys, optional_keys)
147
+ begin
148
+ hash = YAML.load(File.read file)
149
+ rescue Errno::ENOENT
150
+ raise Prick::Error, "Can't read #{file}"
151
+ end
152
+ for key in expected_keys
153
+ !hash[key].to_s.empty? or raise Prick::Error, "Can't find '#{key}' in #{file}"
154
+ end
155
+ (unknown = (hash.keys - expected_keys - optional_keys).first) and
156
+ Prick::Error "Illegal key '#{unknown}' in #{file}"
157
+ hash
158
+ end
159
+
160
+ def parse_context_file(context_file)
161
+ hash = load_yaml(context_file, %w(environment database username), [])
162
+ @database = hash["database"]
163
+ @username = hash["username"]
164
+ @environment = hash["environment"]
165
+ end
166
+
167
+ def parse_project_file(prick_file)
168
+ hash = load_yaml(prick_file, %w(name title), %w(version prick environments))
169
+ @name = hash["name"]
170
+ @title = hash["title"]
171
+ @version = hash["version"] && PrickVersion.new(hash["version"])
172
+ @prick_version = hash["prick"] && PrickVersion.new(hash["prick"])
173
+ Environment.load_environments(hash["environments"] || {})
174
+ end
134
175
  end
135
176
  end
136
177
 
178
+
@@ -3,7 +3,10 @@
3
3
  require 'builder/builder.rb'
4
4
 
5
5
  module Prick::SubCommand
6
- def self.build(database, username, schema, builddir: "schema", force: false, timer: nil, dump: nil)
6
+ def self.build(
7
+ database, username, schema,
8
+ builddir: "schema", force: false, timer: nil, dump: nil)
9
+
7
10
  Timer.on! if timer
8
11
  time "Prick::Command#build" do
9
12
  begin
@@ -15,21 +18,19 @@ module Prick::SubCommand
15
18
  builder = nil
16
19
  time "Load build object" do
17
20
  if super_conn.rdbms.exist? database
18
- conn = PgConn.new(database, username)
19
21
  exist = true
20
22
  else
21
23
  super_conn.rdbms.create database, owner: username
22
- conn = PgConn.new(database, username)
23
24
  exist = false
24
25
  end
26
+ conn = PgConn.new(database, username)
25
27
 
26
28
  builder = Prick::Build::Builder.new(conn, builddir)
27
29
 
28
30
  if exist
29
31
  if force
30
32
  # Drop all schemas but re-creates the public schema
31
- super_conn.rdbms.empty!(database)
32
- conn.schema.drop("public") # drop it again FIXME
33
+ super_conn.rdbms.empty!(database, public: false)
33
34
 
34
35
  else
35
36
  # Find schemas to refresh. This includes all schemas in the
@@ -69,9 +70,9 @@ module Prick::SubCommand
69
70
  builder.execute conn
70
71
  end
71
72
 
72
- rescue Prick::Error => ex
73
- $stderr.puts ex.message
74
- exit 1
73
+ # rescue Prick::Error => ex
74
+ # $stderr.puts ex.message
75
+ # exit 1
75
76
 
76
77
  rescue ::Command::Error => ex
77
78
  $stderr.puts ex.message
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'builder/builder.rb'
4
+
5
+ module Prick::SubCommand
6
+ # Drop users and empty database. This has the same as effect as
7
+ # teardown+setup but without recreating the user and the database that
8
+ # annoyingly terminates all user sessions
9
+ def self.clean(database)
10
+ drop_users(database)
11
+ PgConn.new("postgres") { |conn|
12
+ conn.rdbms.empty!(database) if conn.rdbms.exist?(database)
13
+ }
14
+ end
15
+ end
16
+
17
+
@@ -3,8 +3,15 @@
3
3
  require 'builder/builder.rb'
4
4
 
5
5
  module Prick::SubCommand
6
- def self.drop_users(database)
6
+ def self.drop_user(username) # No database so does not cascade
7
7
  PgConn.new("postgres") { |conn|
8
+ conn.role.drop([username])
9
+ }
10
+ end
11
+
12
+ # Drop all users associated with the given database except the owner
13
+ def self.drop_users(database)
14
+ PgConn.new(database) { |conn|
8
15
  users = conn.role.list(database: database)
9
16
  conn.role.drop(users, cascade: true)
10
17
  }
@@ -15,11 +22,9 @@ module Prick::SubCommand
15
22
  end
16
23
 
17
24
  def self.drop_all(database)
18
- PgConn.new("postgres") { |conn|
19
- users = conn.role.list(database: database)
20
- PgConn.new(database) { |db| db.role.drop(users, cascade: true) }
21
- conn.rdbms.drop database
22
- }
25
+ drop_users(database)
26
+ drop_database(database)
27
+ drop_user(username)
23
28
  end
24
29
  end
25
30
 
data/lib/prick/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Prick
4
- VERSION = "0.28.1"
4
+ VERSION = "0.29.1"
5
5
  end
data/lib/prick.rb CHANGED
@@ -1,4 +1,4 @@
1
- require 'prick/version.rb'
1
+ require_relative 'prick/version.rb'
2
2
 
3
3
  require 'pg_conn'
4
4
 
@@ -11,16 +11,18 @@ module Prick
11
11
  class Fail < RuntimeError; end
12
12
  end
13
13
 
14
- require 'prick/constants.rb'
15
- require 'ext/expand_variables.rb'
14
+ require_relative 'prick/constants.rb'
15
+ require_relative 'prick/ext/expand_variables.rb'
16
16
 
17
- require 'local/command.rb'
18
- require 'local/git.rb'
19
- require 'local/timer.rb'
17
+ require_relative 'prick/local/command.rb'
18
+ require_relative 'prick/local/git.rb'
19
+ require_relative 'prick/local/timer.rb'
20
+ require_relative 'prick/local/ansi.rb'
20
21
 
21
- require 'prick/state.rb'
22
- require 'prick/prick_version.rb'
23
- require 'prick/diff.rb'
22
+ require_relative 'prick/environment.rb'
23
+ require_relative 'prick/state.rb'
24
+ require_relative 'prick/prick_version.rb'
25
+ require_relative 'prick/diff.rb'
24
26
 
25
27
  module Prick
26
28
  module SubCommand
@@ -30,16 +32,17 @@ module Prick
30
32
  end
31
33
  end
32
34
 
33
- require 'subcommand/prick-init.rb'
34
- require 'subcommand/prick-setup.rb'
35
- require 'subcommand/prick-teardown.rb'
36
- require 'subcommand/prick-create.rb'
37
- require 'subcommand/prick-build.rb'
38
- require 'subcommand/prick-make.rb'
39
- require 'subcommand/prick-fox.rb'
40
- require 'subcommand/prick-drop.rb'
41
- require 'subcommand/prick-release.rb'
42
- require 'subcommand/prick-migrate.rb'
35
+ require_relative 'prick/subcommand/prick-init.rb'
36
+ require_relative 'prick/subcommand/prick-setup.rb'
37
+ require_relative 'prick/subcommand/prick-teardown.rb'
38
+ require_relative 'prick/subcommand/prick-clean.rb'
39
+ require_relative 'prick/subcommand/prick-create.rb'
40
+ require_relative 'prick/subcommand/prick-build.rb'
41
+ require_relative 'prick/subcommand/prick-make.rb'
42
+ require_relative 'prick/subcommand/prick-fox.rb'
43
+ require_relative 'prick/subcommand/prick-drop.rb'
44
+ require_relative 'prick/subcommand/prick-release.rb'
45
+ require_relative 'prick/subcommand/prick-migrate.rb'
43
46
 
44
47
  module Prick
45
48
  @state = nil
@@ -0,0 +1,14 @@
1
+ online:
2
+ offline:
3
+ production: online
4
+ development: offline
5
+ frontend: development
6
+ app_registry_frontend: frontend
7
+ app_portal_frontend: frontend
8
+ backend: development
9
+ app_registry_backend: backend
10
+ app_portal_backend: backend
11
+ fdw_import: online
12
+ sagsys_import: offline
13
+ app_portal_import: offline
14
+ test: offline
data/prick.gemspec CHANGED
@@ -38,6 +38,7 @@ Gem::Specification.new do |spec|
38
38
  spec.add_dependency "postspec"
39
39
  spec.add_dependency "pg_graph"
40
40
  spec.add_dependency "shellopts"
41
+ spec.add_dependency "dsort"
41
42
 
42
43
  spec.add_development_dependency "ruby-prof"
43
44
 
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.28.1
4
+ version: 0.29.1
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-01-11 00:00:00.000000000 Z
11
+ date: 2024-01-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: semantic
@@ -136,6 +136,20 @@ dependencies:
136
136
  - - ">="
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: dsort
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :runtime
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
139
153
  - !ruby/object:Gem::Dependency
140
154
  name: ruby-prof
141
155
  requirement: !ruby/object:Gem::Requirement
@@ -168,50 +182,53 @@ files:
168
182
  - bin/setup
169
183
  - doc/build-yml.txt
170
184
  - exe/prick
171
- - lib/builder/batch.rb
172
- - lib/builder/builder.rb
173
- - lib/builder/node.rb
174
- - lib/builder/node_pool.rb
175
- - lib/builder/parser.rb
176
- - lib/ext/expand_variables.rb
177
- - lib/local/command.rb
178
- - lib/local/git.rb
179
- - lib/local/timer.rb
180
185
  - lib/prick.rb
186
+ - lib/prick/builder/batch.rb
187
+ - lib/prick/builder/builder.rb
188
+ - lib/prick/builder/node.rb
189
+ - lib/prick/builder/node_pool.rb
190
+ - lib/prick/builder/parser.rb
181
191
  - lib/prick/constants.rb
182
192
  - lib/prick/diff.rb
193
+ - lib/prick/environment.rb
194
+ - lib/prick/ext/expand_variables.rb
195
+ - lib/prick/local/ansi.rb
196
+ - lib/prick/local/command.rb
197
+ - lib/prick/local/git.rb
198
+ - lib/prick/local/timer.rb
183
199
  - lib/prick/prick_version.rb
200
+ - lib/prick/share/init/.gitignore
201
+ - lib/prick/share/init/.rspec
202
+ - lib/prick/share/init/migration/.keep
203
+ - lib/prick/share/init/prick.yml
204
+ - lib/prick/share/init/schema/.keep
205
+ - lib/prick/share/init/schema/build.yml
206
+ - lib/prick/share/init/schema/prick/.keep
207
+ - lib/prick/share/init/schema/prick/build.yml
208
+ - lib/prick/share/init/schema/prick/data.sql
209
+ - lib/prick/share/init/schema/prick/tables.sql
210
+ - lib/prick/share/init/schema/public/.keep
211
+ - lib/prick/share/init/spec/prick_helper.rb
212
+ - lib/prick/share/init/spec/prick_spec.rb
213
+ - lib/prick/share/init/spec/spec_helper.rb
214
+ - lib/prick/share/migrate/migration/build.yml
215
+ - lib/prick/share/migrate/migration/diff.after-tables.sql
216
+ - lib/prick/share/migrate/migration/diff.before-tables.sql
217
+ - lib/prick/share/migrate/migration/diff.tables.sql
184
218
  - lib/prick/state.rb
219
+ - lib/prick/subcommand/prick-build.rb
220
+ - lib/prick/subcommand/prick-clean.rb
221
+ - lib/prick/subcommand/prick-create.rb
222
+ - lib/prick/subcommand/prick-drop.rb
223
+ - lib/prick/subcommand/prick-fox.rb
224
+ - lib/prick/subcommand/prick-init.rb
225
+ - lib/prick/subcommand/prick-make.rb
226
+ - lib/prick/subcommand/prick-migrate.rb
227
+ - lib/prick/subcommand/prick-release.rb
228
+ - lib/prick/subcommand/prick-setup.rb
229
+ - lib/prick/subcommand/prick-teardown.rb
185
230
  - lib/prick/version.rb
186
- - lib/share/init/.gitignore
187
- - lib/share/init/.prick-context
188
- - lib/share/init/.rspec
189
- - lib/share/init/migration/.keep
190
- - lib/share/init/prick.yml
191
- - lib/share/init/schema/.keep
192
- - lib/share/init/schema/build.yml
193
- - lib/share/init/schema/prick/.keep
194
- - lib/share/init/schema/prick/build.yml
195
- - lib/share/init/schema/prick/data.sql
196
- - lib/share/init/schema/prick/tables.sql
197
- - lib/share/init/schema/public/.keep
198
- - lib/share/init/spec/prick_helper.rb
199
- - lib/share/init/spec/prick_spec.rb
200
- - lib/share/init/spec/spec_helper.rb
201
- - lib/share/migrate/migration/build.yml
202
- - lib/share/migrate/migration/diff.after-tables.sql
203
- - lib/share/migrate/migration/diff.before-tables.sql
204
- - lib/share/migrate/migration/diff.tables.sql
205
- - lib/subcommand/prick-build.rb
206
- - lib/subcommand/prick-create.rb
207
- - lib/subcommand/prick-drop.rb
208
- - lib/subcommand/prick-fox.rb
209
- - lib/subcommand/prick-init.rb
210
- - lib/subcommand/prick-make.rb
211
- - lib/subcommand/prick-migrate.rb
212
- - lib/subcommand/prick-release.rb
213
- - lib/subcommand/prick-setup.rb
214
- - lib/subcommand/prick-teardown.rb
231
+ - prick.environments.yml
215
232
  - prick.gemspec
216
233
  homepage: http://www.nowhere.com/
217
234
  licenses: []
@@ -1,2 +0,0 @@
1
- database:
2
- username:
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes