prick 0.18.0 → 0.20.2

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