prick 0.19.0 → 0.20.1
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/Gemfile +10 -4
- data/README.md +7 -7
- data/Rakefile +3 -1
- data/TODO +13 -11
- data/bin/console +2 -1
- data/doc/build-yml.txt +14 -0
- data/exe/prick +237 -19
- data/lib/builder/batch.rb +147 -0
- data/lib/builder/builder.rb +122 -0
- data/lib/builder/node.rb +189 -0
- data/lib/builder/node_pool.rb +105 -0
- data/lib/builder/parser.rb +120 -0
- data/lib/local/command.rb +193 -0
- data/lib/{prick → local}/git.rb +148 -22
- data/lib/local/timer.rb +98 -0
- data/lib/prick/constants.rb +54 -66
- data/lib/prick/diff.rb +28 -18
- data/lib/prick/prick_version.rb +161 -0
- data/lib/prick/state.rb +80 -165
- data/lib/prick/version.rb +2 -163
- data/lib/prick.rb +38 -24
- data/lib/share/init/.gitignore +10 -0
- data/lib/share/init/.prick-context +2 -0
- data/lib/share/init/.rspec +3 -0
- data/{share/schema/schema/public → lib/share/init/migration}/.keep +0 -0
- data/lib/share/init/prick.yml +6 -0
- data/lib/share/init/schema/.keep +0 -0
- data/lib/share/init/schema/build.yml +2 -0
- data/lib/share/init/schema/prick/.keep +0 -0
- data/lib/share/init/schema/prick/build.yml +5 -0
- data/lib/share/init/schema/prick/data.sql +6 -0
- data/{share/schema → lib/share/init}/schema/prick/tables.sql +2 -3
- data/lib/share/init/schema/public/.keep +0 -0
- data/lib/share/init/spec/prick_helper.rb +1 -0
- data/lib/share/init/spec/prick_spec.rb +6 -0
- data/lib/share/init/spec/spec_helper.rb +50 -0
- data/lib/share/migrate/migration/build.yml +4 -0
- data/lib/share/migrate/migration/diff.after-tables.sql +0 -0
- data/lib/share/migrate/migration/diff.before-tables.sql +0 -0
- data/lib/share/migrate/migration/diff.tables.sql +0 -0
- data/lib/subcommand/prick-build.rb +55 -0
- data/lib/subcommand/prick-create.rb +78 -0
- data/lib/subcommand/prick-drop.rb +25 -0
- data/lib/subcommand/prick-fox.rb +62 -0
- data/lib/subcommand/prick-init.rb +46 -0
- data/lib/subcommand/prick-make.rb +202 -0
- data/lib/subcommand/prick-migrate.rb +37 -0
- data/lib/subcommand/prick-release.rb +23 -0
- data/lib/subcommand/prick-setup.rb +20 -0
- data/lib/subcommand/prick-teardown.rb +18 -0
- data/prick.gemspec +32 -21
- metadata +95 -76
- data/.gitignore +0 -29
- data/.travis.yml +0 -7
- data/doc/create_release.txt +0 -17
- data/doc/flow.txt +0 -98
- data/doc/migra +0 -1
- data/doc/migrations.txt +0 -172
- data/doc/notes.txt +0 -116
- data/doc/prick.txt +0 -114
- data/doc/sh.prick +0 -316
- data/lib/ext/algorithm.rb +0 -14
- data/lib/ext/fileutils.rb +0 -26
- data/lib/ext/forward_method.rb +0 -18
- data/lib/ext/pg.rb +0 -18
- data/lib/ext/shortest_path.rb +0 -44
- data/lib/prick/archive.rb +0 -124
- data/lib/prick/branch.rb +0 -265
- data/lib/prick/builder.rb +0 -246
- data/lib/prick/cache.rb +0 -34
- data/lib/prick/command.rb +0 -104
- data/lib/prick/database.rb +0 -82
- data/lib/prick/dsort.rb +0 -151
- data/lib/prick/ensure.rb +0 -119
- data/lib/prick/exceptions.rb +0 -25
- data/lib/prick/head.rb +0 -189
- data/lib/prick/migration.rb +0 -70
- data/lib/prick/program.rb +0 -287
- data/lib/prick/project.rb +0 -626
- data/lib/prick/rdbms.rb +0 -137
- data/lib/prick/schema.rb +0 -27
- data/lib/prick/share.rb +0 -64
- data/libexec/strip-comments +0 -33
- data/make_releases +0 -72
- data/make_schema +0 -10
- data/share/diff/diff.after-tables.sql +0 -4
- data/share/diff/diff.before-tables.sql +0 -4
- data/share/diff/diff.tables.sql +0 -8
- data/share/features/diff.sql +0 -2
- data/share/features/feature/diff.sql +0 -2
- data/share/features/feature/migrate.sql +0 -2
- data/share/features/features.sql +0 -2
- data/share/features/features.yml +0 -2
- data/share/features/migrations.sql +0 -4
- data/share/gitignore +0 -2
- data/share/migration/diff.tables.sql +0 -8
- data/share/migration/features.yml +0 -6
- data/share/migration/migrate.sql +0 -3
- data/share/migration/migrate.yml +0 -8
- data/share/migration/tables.sql +0 -3
- data/share/schema/build.yml +0 -14
- data/share/schema/schema/build.yml +0 -3
- data/share/schema/schema/prick/build.yml +0 -14
- data/share/schema/schema/prick/data.sql +0 -7
- data/share/schema/schema/prick/schema.sql +0 -3
- data/share/schema/schema/public/build.yml +0 -13
- data/share/schema/schema.sql +0 -3
- data/test_assorted +0 -192
- data/test_feature +0 -112
- data/test_refactor +0 -34
- data/test_single_dev +0 -83
data/lib/prick/branch.rb
DELETED
|
@@ -1,265 +0,0 @@
|
|
|
1
|
-
require "prick/state.rb"
|
|
2
|
-
|
|
3
|
-
# FIXME FIXME FIXME Not used!
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
module Prick
|
|
7
|
-
class Branch
|
|
8
|
-
# Branch name. It is usually equal to the version but migrations use a
|
|
9
|
-
# <base_version>_<version> format instead
|
|
10
|
-
attr_reader :name
|
|
11
|
-
|
|
12
|
-
# Version of this branch. Note that version and base_version are the same
|
|
13
|
-
# for feature branches
|
|
14
|
-
attr_reader :version
|
|
15
|
-
|
|
16
|
-
# Base version
|
|
17
|
-
attr_reader :base_version
|
|
18
|
-
|
|
19
|
-
# The release directory. It contains the release's .prick-migration file
|
|
20
|
-
attr_reader :directory
|
|
21
|
-
|
|
22
|
-
# The Schema object. This is shared by many all branches
|
|
23
|
-
attr_reader :schema
|
|
24
|
-
|
|
25
|
-
# Migration object. Running the migration object on the base release will
|
|
26
|
-
# migrate it to this release
|
|
27
|
-
attr_reader :migration
|
|
28
|
-
|
|
29
|
-
# Database name
|
|
30
|
-
def database() name end
|
|
31
|
-
|
|
32
|
-
# Classifiers
|
|
33
|
-
def release?() self.is_a?(Release) && !prerelease? end
|
|
34
|
-
def prerelease?() self.is_a?(PreRelease) end
|
|
35
|
-
def feature?() self.is_a?(Feature) end
|
|
36
|
-
def migration?() self.is_a?(MigrationRelease) end
|
|
37
|
-
|
|
38
|
-
# Note that `name` can be nil. It defaults to `version.to_s`
|
|
39
|
-
def initialize(name, version, base_version, directory, migration)
|
|
40
|
-
@name = name || migration.version.to_s
|
|
41
|
-
@version = version
|
|
42
|
-
@base_version = base_version
|
|
43
|
-
@directory = directory
|
|
44
|
-
@schema = Schema.new
|
|
45
|
-
@migration = migration
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
def dump
|
|
49
|
-
puts "#{self.class}"
|
|
50
|
-
indent {
|
|
51
|
-
puts "name: #{name}"
|
|
52
|
-
puts "version: #{version}"
|
|
53
|
-
puts "base_version: #{base_version}"
|
|
54
|
-
puts "directory: #{directory}"
|
|
55
|
-
print "migration: "
|
|
56
|
-
migration.dump
|
|
57
|
-
puts "database: #{database}"
|
|
58
|
-
}
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
def self.load(name) raise NotThis end
|
|
62
|
-
|
|
63
|
-
# True if the branch exists in git
|
|
64
|
-
def exist?() self.class.exist?(name) end
|
|
65
|
-
|
|
66
|
-
def create()
|
|
67
|
-
!exist? or raise Error, "Can't create branch #{name}, exists already"
|
|
68
|
-
Git.create_branch(name)
|
|
69
|
-
Git.checkout_branch(name)
|
|
70
|
-
prepare if !prepared?
|
|
71
|
-
self
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
# True if the branch exists on disk
|
|
75
|
-
def present?() self.class.present?(name) end
|
|
76
|
-
|
|
77
|
-
def prepared?() @migration.exist? end
|
|
78
|
-
def prepare() @migration.create end
|
|
79
|
-
|
|
80
|
-
def include(feature_version) @migration.append_feature(feature_version) end
|
|
81
|
-
|
|
82
|
-
def build(database) schema.build(database) end
|
|
83
|
-
|
|
84
|
-
# Used to checkout migrations. MigrationReleases checks out the
|
|
85
|
-
# corresponding branch while Release and PreRelease checks out a tag
|
|
86
|
-
def checkout_release() Git.checkout_branch(version) end
|
|
87
|
-
|
|
88
|
-
def migrate(database)
|
|
89
|
-
@migration.migrate(database)
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
def migrate_features(database)
|
|
93
|
-
@migration.migrate_features(database)
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
def self.directory(name) raise NotThis end
|
|
97
|
-
def self.exist?(name) Git.branch?(name) || Git.tag?(name) end
|
|
98
|
-
def self.present?(name) File.exist?(directory(name)) end
|
|
99
|
-
|
|
100
|
-
def <=>(other)
|
|
101
|
-
if !self.is_a?(MigrationRelease) && other.is_a?(MigrationRelease)
|
|
102
|
-
compare(other.base_version, other.version)
|
|
103
|
-
else
|
|
104
|
-
compare(other.version, other.base_version)
|
|
105
|
-
end
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
private
|
|
109
|
-
def compare(other_version, other_base_version)
|
|
110
|
-
r = version <=> other_version
|
|
111
|
-
return r if r != 0
|
|
112
|
-
if base_version.nil?
|
|
113
|
-
other_base_version.nil? ? 0 : -1
|
|
114
|
-
elsif other_base_version.nil?
|
|
115
|
-
1
|
|
116
|
-
else
|
|
117
|
-
base_version <=> other_base_version
|
|
118
|
-
end
|
|
119
|
-
end
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
# A user defined branch. User defined branches have no version and only the
|
|
123
|
-
# #build method is defined TODO: Make all methods but #build private
|
|
124
|
-
class UserBranch < Branch
|
|
125
|
-
def initialize(name)
|
|
126
|
-
super(name, nil, nil, nil, nil)
|
|
127
|
-
end
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
class AbstractRelease < Branch
|
|
131
|
-
def create(schema_version = self.version)
|
|
132
|
-
super()
|
|
133
|
-
schema.version = schema_version
|
|
134
|
-
Git.add schema.version_file
|
|
135
|
-
self
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
def checkout_release() Git.checkout_tag(version) end
|
|
139
|
-
|
|
140
|
-
def tag!() Git.create_tag(version) end
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
class Release < AbstractRelease
|
|
144
|
-
def initialize(version, base_version)
|
|
145
|
-
!version.zero? || base_version.nil? or raise Internal, "Version 0.0.0 has no base release"
|
|
146
|
-
directory = self.class.directory(version.to_s)
|
|
147
|
-
migration = ReleaseMigration.new(version, base_version)
|
|
148
|
-
super(nil, version, base_version, directory, migration)
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
def self.load(name)
|
|
152
|
-
migration = ReleaseMigration.load(directory(name))
|
|
153
|
-
self.new(migration.version, migration.base_version)
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
def self.directory(name)
|
|
157
|
-
File.join(RELEASES_DIR, name)
|
|
158
|
-
end
|
|
159
|
-
end
|
|
160
|
-
|
|
161
|
-
class PreRelease < AbstractRelease
|
|
162
|
-
attr_reader :prerelease_version
|
|
163
|
-
|
|
164
|
-
def database() version.to_s end
|
|
165
|
-
|
|
166
|
-
def initialize(prerelease_version, base_version)
|
|
167
|
-
@prerelease_version = prerelease_version
|
|
168
|
-
version = prerelease_version.truncate(:pre)
|
|
169
|
-
directory = Release.directory(version.to_s)
|
|
170
|
-
migration = ReleaseMigration.new(version, base_version)
|
|
171
|
-
super(prerelease_version.to_s, version, base_version, directory, migration)
|
|
172
|
-
end
|
|
173
|
-
|
|
174
|
-
def self.load(name, prerelease_version)
|
|
175
|
-
migration = ReleaseMigration.load(directory(name))
|
|
176
|
-
self.new(prerelease_version, migration.base_version)
|
|
177
|
-
end
|
|
178
|
-
|
|
179
|
-
def create()
|
|
180
|
-
super(prerelease_version)
|
|
181
|
-
end
|
|
182
|
-
|
|
183
|
-
def increment
|
|
184
|
-
PreRelease.new(prerelease_version.increment(:pre), base_version)
|
|
185
|
-
end
|
|
186
|
-
|
|
187
|
-
def self.directory(name)
|
|
188
|
-
version = Version.new(name)
|
|
189
|
-
Release.directory(version.truncate(:pre).to_s)
|
|
190
|
-
end
|
|
191
|
-
end
|
|
192
|
-
|
|
193
|
-
class MigrationRelease < Branch
|
|
194
|
-
def database() version.to_s end
|
|
195
|
-
|
|
196
|
-
def initialize(version, base_version)
|
|
197
|
-
migration = MigrationMigration.new(version, base_version)
|
|
198
|
-
super(migration.name, version, base_version, migration.dir, migration)
|
|
199
|
-
end
|
|
200
|
-
|
|
201
|
-
def self.load(name)
|
|
202
|
-
directory = self.directory(name)
|
|
203
|
-
migration_state = MigrationState.new(directory).read
|
|
204
|
-
self.new(migration_state.version, migration_state.base_version)
|
|
205
|
-
end
|
|
206
|
-
|
|
207
|
-
def self.directory(name)
|
|
208
|
-
File.join(MIGRATIONS_DIR, name)
|
|
209
|
-
end
|
|
210
|
-
end
|
|
211
|
-
|
|
212
|
-
# Feature maintains a migration in the parent release but it is ignored when
|
|
213
|
-
# including the feature
|
|
214
|
-
class Feature < Branch
|
|
215
|
-
attr_reader :feature_name
|
|
216
|
-
|
|
217
|
-
def database() base_version.to_s end
|
|
218
|
-
|
|
219
|
-
def initialize(feature_name, base_version)
|
|
220
|
-
version = Version.new(base_version, feature: feature_name)
|
|
221
|
-
migration = FeatureMigration.new(feature_name, base_version)
|
|
222
|
-
super(version.to_s, version, base_version, migration.features_dir, migration)
|
|
223
|
-
@feature_name = feature_name
|
|
224
|
-
end
|
|
225
|
-
|
|
226
|
-
def create
|
|
227
|
-
super()
|
|
228
|
-
schema.version = version
|
|
229
|
-
Git.add schema.version_file
|
|
230
|
-
self
|
|
231
|
-
end
|
|
232
|
-
|
|
233
|
-
def include(feature_version) @migration.insert_feature(feature_version) end
|
|
234
|
-
|
|
235
|
-
def rebase(base_version)
|
|
236
|
-
new_version = Version.new(new_base_version, feature: feature_name)
|
|
237
|
-
name = new_version.to_s
|
|
238
|
-
|
|
239
|
-
Git.create_branch(name)
|
|
240
|
-
Git.checkout_branch(name)
|
|
241
|
-
|
|
242
|
-
symlink = self.directory(name)
|
|
243
|
-
FileUtils.ln_sr(directory, symlink, force: true)
|
|
244
|
-
Git.add(symlink)
|
|
245
|
-
|
|
246
|
-
migration.base_version = new_base_version
|
|
247
|
-
migration.save
|
|
248
|
-
|
|
249
|
-
schema.version = new_version
|
|
250
|
-
Git.add ect.schema.version_file
|
|
251
|
-
end
|
|
252
|
-
|
|
253
|
-
def self.load(name)
|
|
254
|
-
directory = self.directory(name)
|
|
255
|
-
migration_state = MigrationState.new(directory).read
|
|
256
|
-
self.new(migration_state.version.feature, migration_state.base_version)
|
|
257
|
-
end
|
|
258
|
-
|
|
259
|
-
def self.directory(name)
|
|
260
|
-
version = Version.new(name)
|
|
261
|
-
File.join(Release.directory(version.truncate(:feature).to_s), version.feature.to_s)
|
|
262
|
-
end
|
|
263
|
-
end
|
|
264
|
-
end
|
|
265
|
-
|
data/lib/prick/builder.rb
DELETED
|
@@ -1,246 +0,0 @@
|
|
|
1
|
-
require "prick/state.rb"
|
|
2
|
-
|
|
3
|
-
require 'indented_io'
|
|
4
|
-
|
|
5
|
-
module Prick
|
|
6
|
-
# Builder is a procedural object for building schemas and executing
|
|
7
|
-
# migrations. Builder use resources that can be executables, SQL files, YAML
|
|
8
|
-
# files, FOX files, or directories. A resource is identified by a name (eg.
|
|
9
|
-
# 'my-tables') and is used to match a build file. Build files are looked up
|
|
10
|
-
# in the following order:
|
|
11
|
-
#
|
|
12
|
-
# #{name} executable
|
|
13
|
-
# #{name}.* executable
|
|
14
|
-
# #{name}.yml
|
|
15
|
-
# #{name}.sql
|
|
16
|
-
# #{name}.fox
|
|
17
|
-
# #{name}/
|
|
18
|
-
#
|
|
19
|
-
# The output from executable objects is expected to be SQL statements that
|
|
20
|
-
# are then fed into postgres
|
|
21
|
-
#
|
|
22
|
-
# When a resource match a directory, the directory can contain a special
|
|
23
|
-
# default resource ('build' or 'migrate') that takes over the rest of the
|
|
24
|
-
# build process for that directory. Typically, you'll use the 'build.yml' or
|
|
25
|
-
# 'migrate.yml' to control the build order of the other resources. If a
|
|
26
|
-
# directory doesn't contain a build resource, the resources in the directory
|
|
27
|
-
# are built in alphabetic order
|
|
28
|
-
#
|
|
29
|
-
# Build SQL scripts and executables are executed with search path set to
|
|
30
|
-
# containing schema. This doesn't include migration script or executable
|
|
31
|
-
#
|
|
32
|
-
class Builder
|
|
33
|
-
attr_reader :database
|
|
34
|
-
attr_reader :directory
|
|
35
|
-
attr_reader :default # either "build" or "migrate"
|
|
36
|
-
attr_reader :lines
|
|
37
|
-
|
|
38
|
-
def state_file() self.class.state_file end
|
|
39
|
-
def state_file=(file) self.class.state_file = file end
|
|
40
|
-
def self.state_file() @@state_file end
|
|
41
|
-
def self.state_file=(file) @@state_file = file end
|
|
42
|
-
|
|
43
|
-
def initialize(database, directory, default)
|
|
44
|
-
@database = database
|
|
45
|
-
@directory = directory
|
|
46
|
-
@default = default
|
|
47
|
-
@execute = true
|
|
48
|
-
@lines = []
|
|
49
|
-
@cwd = Dir.getwd # used in error messages
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def build(subject = default, execute: true)
|
|
53
|
-
puts "build(#{subject.inspect}, execute: #{execute.inspect})" if $verbose > 0
|
|
54
|
-
@execute = execute
|
|
55
|
-
@lines = []
|
|
56
|
-
Dir.chdir(directory) {
|
|
57
|
-
if subject
|
|
58
|
-
build_subject(subject)
|
|
59
|
-
else
|
|
60
|
-
build_directory(".")
|
|
61
|
-
end
|
|
62
|
-
}
|
|
63
|
-
@lines.reject! { |l| l =~ /^\s*--/ || l =~ /^\s*$/ }
|
|
64
|
-
self
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
def self.yml_file(directory) raise NotThis end
|
|
68
|
-
|
|
69
|
-
protected
|
|
70
|
-
def do_path(path, &block)
|
|
71
|
-
puts "do_path(#{path.inspect})" if $verbose >= 3
|
|
72
|
-
if File.directory?(path)
|
|
73
|
-
dir, file = path, nil
|
|
74
|
-
else
|
|
75
|
-
dir, file = File.split(path)
|
|
76
|
-
end
|
|
77
|
-
if $verbose >= 2
|
|
78
|
-
indent { Dir.chdir(dir) { yield(file) } }
|
|
79
|
-
else
|
|
80
|
-
Dir.chdir(dir) { yield(file) }
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
def do_sql(path, schema: nil)
|
|
85
|
-
puts "do_sql(#{path})" if $verbose >= 2
|
|
86
|
-
do_path(path) { |file|
|
|
87
|
-
if @execute
|
|
88
|
-
begin
|
|
89
|
-
Rdbms.exec_file(database.name, file, user: database.user, schema: schema)
|
|
90
|
-
rescue Command::Error => ex
|
|
91
|
-
$stderr.puts ex.stderr
|
|
92
|
-
$stderr.puts "in #{reldir}/#{file}"
|
|
93
|
-
exit 1
|
|
94
|
-
end
|
|
95
|
-
else
|
|
96
|
-
@lines += IO.readlines(file).map(&:chomp)
|
|
97
|
-
end
|
|
98
|
-
}
|
|
99
|
-
true
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
def do_fox(path, schema: nil)
|
|
103
|
-
puts "do_fox(#{path.inspect}, #{schema.inspect})" if $verbose >= 2
|
|
104
|
-
do_path(path) { |file|
|
|
105
|
-
lines = Command.command "fox --state=#{state_file} --write --delete=none #{database.name} #{file}"
|
|
106
|
-
if @execute
|
|
107
|
-
begin
|
|
108
|
-
Rdbms.exec_sql(database.name, lines.join("\n"), user: database.user, schema: schema)
|
|
109
|
-
rescue Command::Error => ex
|
|
110
|
-
$stderr.puts ex.stderr
|
|
111
|
-
$stderr.puts "from #{reldir}/#{file}"
|
|
112
|
-
exit 1
|
|
113
|
-
end
|
|
114
|
-
else
|
|
115
|
-
@lines += lines
|
|
116
|
-
end
|
|
117
|
-
}
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
def do_exe(path, args = [], schema: nil)
|
|
121
|
-
puts "do_exe(#{path.inspect}, #{args.inspect})" if $verbose >= 2
|
|
122
|
-
do_path(path) { |file|
|
|
123
|
-
cmd = (["./#{file}"] + args).join(" ")
|
|
124
|
-
lines = Command.command cmd, stdin: [database.name, database.user], stderr: nil
|
|
125
|
-
if @execute
|
|
126
|
-
begin
|
|
127
|
-
Rdbms.exec_sql(database.name, lines.join("\n"), user: database.user, schema: schema)
|
|
128
|
-
rescue Command::Error => ex
|
|
129
|
-
$stderr.puts ex.stderr
|
|
130
|
-
$stderr.puts "from #{reldir}/#{file}"
|
|
131
|
-
exit 1
|
|
132
|
-
end
|
|
133
|
-
else
|
|
134
|
-
@lines += lines
|
|
135
|
-
end
|
|
136
|
-
}
|
|
137
|
-
true
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
def do_yml(path)
|
|
141
|
-
puts "do_yml(#{path})" if $verbose >= 2
|
|
142
|
-
do_path(path) { |file|
|
|
143
|
-
YAML.load(File.read(file))&.each { |subject| build_subject(subject) }
|
|
144
|
-
}
|
|
145
|
-
true
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
# A subject can be both an abstract subject or a concrete file (*.yml, *.sql, or *.fox)
|
|
149
|
-
def build_subject(subject)
|
|
150
|
-
puts "build_subject(#{subject.inspect}) in #{Dir.getwd}" if $verbose > 0
|
|
151
|
-
cmd, *args = subject.split(/\s+/)
|
|
152
|
-
if File.file?(cmd) && File.executable?(cmd)
|
|
153
|
-
do_exe(cmd, args)
|
|
154
|
-
elsif File.file?(subject) && subject.end_with?(".yml")
|
|
155
|
-
do_yml(subject)
|
|
156
|
-
elsif File.file?(subject) && subject.end_with?(".sql")
|
|
157
|
-
do_sql(subject)
|
|
158
|
-
elsif File.file?(subject) && subject.end_with?(".fox")
|
|
159
|
-
do_fox(subject)
|
|
160
|
-
elsif File.exist?(yml_file = "#{subject}.yml")
|
|
161
|
-
do_yml(yml_file)
|
|
162
|
-
elsif File.exist?(sql_file = "#{subject}.sql")
|
|
163
|
-
do_sql(sql_file)
|
|
164
|
-
elsif File.directory?(subject)
|
|
165
|
-
build_directory(subject)
|
|
166
|
-
else
|
|
167
|
-
false
|
|
168
|
-
end
|
|
169
|
-
end
|
|
170
|
-
|
|
171
|
-
def build_directory(path)
|
|
172
|
-
puts "build_directory(#{path.inspect}) in #{Dir.getwd}" if $verbose >= 2
|
|
173
|
-
do_path(path) { |_|
|
|
174
|
-
build_subject(@default) || begin
|
|
175
|
-
if !Dir["#{default}", "#{default}.yml", "#{default}.sql"].empty?
|
|
176
|
-
subjects = [default]
|
|
177
|
-
else
|
|
178
|
-
candidates = Dir["*"]
|
|
179
|
-
exes = candidates.select { |file| File.file?(file) && File.executable?(file) }
|
|
180
|
-
ymls = candidates.select { |file| file.end_with?(".yml") }.map { |f| f.sub(/\.yml$/, "") }
|
|
181
|
-
sqls = candidates.select { |file| file.end_with?(".sql") }.map { |f| f.sub(/\.sql$/, "") }
|
|
182
|
-
foxs = candidates.select { |file| file.end_with?(".fox") }.map { |f| f.sub(/\.fox$/, "") }
|
|
183
|
-
dirs = candidates.select { |file| File.directory?(file) }
|
|
184
|
-
subjects = (exes + ymls + sqls + foxs + dirs).uniq.sort #.reject { |f| f != "diff" } FIXME ??
|
|
185
|
-
end
|
|
186
|
-
subjects.inject(false) { |a, s| build_subject(s) || a }
|
|
187
|
-
end
|
|
188
|
-
}
|
|
189
|
-
end
|
|
190
|
-
|
|
191
|
-
private
|
|
192
|
-
# Return the relative path to the current directory from the directory of
|
|
193
|
-
# the time of the instantiation of the Builder object. Used in error
|
|
194
|
-
# messages
|
|
195
|
-
def reldir
|
|
196
|
-
Dir.getwd.sub(/^#{@cwd}\//, "")
|
|
197
|
-
end
|
|
198
|
-
end
|
|
199
|
-
|
|
200
|
-
class MigrationBuilder < Builder
|
|
201
|
-
def initialize(database, directory)
|
|
202
|
-
super(database, directory, "migrate")
|
|
203
|
-
end
|
|
204
|
-
|
|
205
|
-
def self.yml_file(directory) File.join(directory, "migrate") + ".yml" end
|
|
206
|
-
end
|
|
207
|
-
|
|
208
|
-
class SchemaBuilder < Builder
|
|
209
|
-
def initialize(database, directory)
|
|
210
|
-
super(database, directory, "build")
|
|
211
|
-
end
|
|
212
|
-
|
|
213
|
-
def build(subject = nil, execute: true)
|
|
214
|
-
if subject
|
|
215
|
-
@execute = execute
|
|
216
|
-
@lines = []
|
|
217
|
-
Dir.chdir(directory) {
|
|
218
|
-
if File.executable?(subject)
|
|
219
|
-
do_exe(subject)
|
|
220
|
-
elsif subject.end_with?(".sql")
|
|
221
|
-
do_sql(subject)
|
|
222
|
-
else
|
|
223
|
-
build_subject(subject)
|
|
224
|
-
end
|
|
225
|
-
}
|
|
226
|
-
else
|
|
227
|
-
super(execute: execute)
|
|
228
|
-
end
|
|
229
|
-
self
|
|
230
|
-
end
|
|
231
|
-
|
|
232
|
-
def self.yml_file(directory) File.join(directory, "build") + ".yml" end
|
|
233
|
-
|
|
234
|
-
protected
|
|
235
|
-
def do_sql(path)
|
|
236
|
-
schema = Dir.getwd =~ /^.*schema\/([^\/]+)(?:\/.*)?$/ ? $1 : "public"
|
|
237
|
-
super(path, schema: schema)
|
|
238
|
-
end
|
|
239
|
-
|
|
240
|
-
def do_exe(path, args = [])
|
|
241
|
-
schema = Dir.getwd =~ /^.*schema\/([^\/]+)(?:\/.*)?$/ ? $1 : "public"
|
|
242
|
-
super(path, args, schema: schema)
|
|
243
|
-
end
|
|
244
|
-
end
|
|
245
|
-
end
|
|
246
|
-
|
data/lib/prick/cache.rb
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
module Prick
|
|
3
|
-
class Cache
|
|
4
|
-
def initialize
|
|
5
|
-
end
|
|
6
|
-
|
|
7
|
-
def exist?(version)
|
|
8
|
-
File.exist?(file(version))
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def list
|
|
12
|
-
Dir.glob(File.join(CACHE_DIR, "*.sql.gz"))
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def load(database, version)
|
|
16
|
-
Rdbms.load(database, file(version))
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def save(database, version = database.version)
|
|
20
|
-
Rdbms.save(database, file(version))
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
# Returns list of removed files
|
|
24
|
-
def clean
|
|
25
|
-
l = list
|
|
26
|
-
FileUtils.rm(l)
|
|
27
|
-
l
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def file(version)
|
|
31
|
-
File.join(CACHE_DIR, "#{version}.sql.gz")
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
end
|
data/lib/prick/command.rb
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
require 'fcntl'
|
|
2
|
-
|
|
3
|
-
module Command
|
|
4
|
-
class Error < RuntimeError
|
|
5
|
-
attr_reader :status
|
|
6
|
-
attr_reader :stdout
|
|
7
|
-
attr_reader :stderr
|
|
8
|
-
|
|
9
|
-
def initialize(message, status, stdout, stderr)
|
|
10
|
-
super(message)
|
|
11
|
-
@status = status
|
|
12
|
-
@stdout = stdout
|
|
13
|
-
@stderr = stderr
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
# Execute the shell command 'cmd' and return standard output as an array of
|
|
18
|
-
# strings. while stderr is passed through unless stderr: is false. If stderr:
|
|
19
|
-
# is true, it returns a tuple of [stdout, stderr] instead. The shell command
|
|
20
|
-
# is executed with the `errexit` and `pipefail` bash options
|
|
21
|
-
#
|
|
22
|
-
# The :stdin option is a line or an array of lines that'll be fed to the
|
|
23
|
-
# standard input of the command. Default is nil
|
|
24
|
-
#
|
|
25
|
-
# It raises a Command::Error exception if the command fails unless :fail is
|
|
26
|
-
# true. The exit status of the last command is stored in ::status
|
|
27
|
-
#
|
|
28
|
-
def command(cmd, stdin: nil, stderr: false, fail: true)
|
|
29
|
-
cmd = "set -o errexit\nset -o pipefail\n#{cmd}"
|
|
30
|
-
|
|
31
|
-
pw = IO::pipe # pipe[0] for read, pipe[1] for write
|
|
32
|
-
pr = IO::pipe
|
|
33
|
-
pe = IO::pipe
|
|
34
|
-
|
|
35
|
-
STDOUT.flush
|
|
36
|
-
|
|
37
|
-
pid = fork {
|
|
38
|
-
pw[1].close
|
|
39
|
-
pr[0].close
|
|
40
|
-
pe[0].close
|
|
41
|
-
|
|
42
|
-
STDIN.reopen(pw[0])
|
|
43
|
-
pw[0].close
|
|
44
|
-
|
|
45
|
-
STDOUT.reopen(pr[1])
|
|
46
|
-
pr[1].close
|
|
47
|
-
|
|
48
|
-
STDERR.reopen(pe[1])
|
|
49
|
-
pe[1].close
|
|
50
|
-
|
|
51
|
-
exec(cmd)
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
pw[0].close
|
|
55
|
-
pr[1].close
|
|
56
|
-
pe[1].close
|
|
57
|
-
|
|
58
|
-
if stdin
|
|
59
|
-
pw[1].puts(stdin)
|
|
60
|
-
pw[1].flush
|
|
61
|
-
pw[1].close
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
@status = Process.waitpid2(pid)[1].exitstatus
|
|
65
|
-
|
|
66
|
-
out = pr[0].readlines.collect { |line| line.chop }
|
|
67
|
-
err = pe[0].readlines.collect { |line| line.chop }.grep_v(/^NOTICE:/)
|
|
68
|
-
|
|
69
|
-
pw[1].close if !stdin
|
|
70
|
-
pr[0].close
|
|
71
|
-
pe[0].close
|
|
72
|
-
|
|
73
|
-
result =
|
|
74
|
-
case stderr
|
|
75
|
-
when true; [out, err]
|
|
76
|
-
when false; out
|
|
77
|
-
when NilClass;
|
|
78
|
-
$stderr.puts err
|
|
79
|
-
out
|
|
80
|
-
else
|
|
81
|
-
raise Internal, "Unexpected value for :stderr - #{stderr.inspect}"
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
if @status == 0 || fail == false
|
|
85
|
-
result
|
|
86
|
-
elsif fail
|
|
87
|
-
raise Command::Error.new("\n" + cmd + "\n" + (out + err).join("\n") + "\n", status, out, err)
|
|
88
|
-
end
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
# Exit status of the last command
|
|
92
|
-
def status() @status end
|
|
93
|
-
|
|
94
|
-
# Like command but returns true if the command exited with the expected status
|
|
95
|
-
def command?(cmd, expect: 0)
|
|
96
|
-
command(cmd, fail: false)
|
|
97
|
-
@status == expect
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
module_function :command
|
|
101
|
-
module_function :status
|
|
102
|
-
module_function :command?
|
|
103
|
-
end
|
|
104
|
-
|