prick 0.18.0 → 0.20.2

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.
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
data/lib/prick/project.rb DELETED
@@ -1,626 +0,0 @@
1
- require "prick/state.rb"
2
-
3
- require "tmpdir"
4
-
5
- module Prick
6
- class Project
7
- attr_reader :name
8
- attr_reader :user # Database user
9
- attr_reader :head # Current branch/tag
10
- attr_reader :schema
11
-
12
- # Return the versioned database or the project database if `version` is nil
13
- def database(version = nil)
14
- version ? Database.new("#{name}-#{version}", user) : @database
15
- end
16
-
17
- attr_reader :cache
18
-
19
- def initialize(name, user, head)
20
- @name = name
21
- @user = user || ENV['USER']
22
- @head = head
23
- @schema = Schema.new
24
- @database = Database.new(name, user)
25
- @cache = Cache.new
26
- end
27
-
28
- forward_methods :version, :base_version, :@head
29
- forward_methods :clean?, :@head
30
- forward_methods :tag?, :release_tag?, :migration_tag?, :@head
31
- forward_methods :branch?, :release_branch?, :prerelease_branch?, :feature_branch?, :migration_branch?, :@head
32
-
33
- def self.exist?(directory)
34
- File.directory?(directory) && Dir.chdir(directory) { ProjectState.new.exist? }
35
- end
36
-
37
- def self.create(name, user, directory)
38
- user ||= ENV['USER']
39
-
40
- FileUtils.mkdir(directory) if directory != "."
41
-
42
- Dir.chdir(directory) {
43
- # Initialize git instance
44
- Git.init
45
-
46
- # Create prick version file
47
- PrickVersion.new.write(VERSION)
48
-
49
- # Create project state file
50
- ProjectState.new(name: name, user: user).write
51
-
52
- # Directories
53
- FileUtils.mkdir_p(DIRS)
54
- DIRS.each { |dir| FileUtils.touch("#{dir}/.keep") }
55
-
56
- # Copy default gitignore and schema files
57
- Share.cp("gitignore", ".gitignore")
58
- Share.cp("schema/schema", ".")
59
-
60
- # Add .prick-migration file
61
- MigrationState.new(version: Version.zero).create
62
-
63
- # Add everything so far
64
- Git.add(".")
65
- Git.commit("Initial import")
66
-
67
- # Rename branch "master"/"main" to "0.0.0_initial"
68
- from_branch = Git.branch?("master") ? "master" : "main"
69
- Git.rename_branch(from_branch, "0.0.0_initial")
70
-
71
- # Create schema
72
- schema = Schema.new
73
- schema.version = Version.zero
74
- Git.add schema.version_file
75
-
76
- # Create release
77
- Git.commit "Created release v0.0.0"
78
- Git.create_tag(Version.zero)
79
- Git.checkout_tag(Version.zero)
80
- }
81
- end
82
-
83
- # Initialize from disk
84
- #
85
- # TODO Handle migrations
86
- def self.load
87
- if Git.detached?
88
- name = "v#{Git.current_tag}"
89
- else
90
- name = Git.current_branch
91
- end
92
- begin
93
- branch = Head.load(name)
94
- rescue Version::FormatError
95
- raise Fail, "Illegal branch name: #{name}"
96
- end
97
- state = ProjectState.new.read
98
- Project.new(state.name, state.user, branch)
99
- end
100
-
101
- def build(database = self.database, version: nil)
102
- database.clean
103
- if version
104
- FileUtils.mkdir_p(TMP_DIR)
105
- Dir.mktmpdir("clone-", TMP_DIR) { |dir|
106
- Command.command "git clone . #{dir}"
107
- Dir.chdir(dir) {
108
- Git.checkout_tag(version)
109
- project = Project.load
110
- project.head.build(database)
111
- }
112
- }
113
- else
114
- head.build(database)
115
- end
116
- self
117
- end
118
-
119
- def load(database = self.database, version: nil, file: nil)
120
- version.nil? ^ file.nil? or raise Internal, "Need exactly one of :file and :version to be defined"
121
- database.clean
122
- if version
123
- cache.exist?(version) or raise Internal, "Can't find cache file for database #{database}"
124
- cache.load(database, version)
125
- else
126
- database.load(file)
127
- end
128
- self
129
- end
130
-
131
- def save(database = nil, file: nil)
132
- !database.nil? || file or raise Internal, "Need a database when saving to file"
133
- database ||= self.database
134
- if file
135
- database.save(file)
136
- else
137
- cache.save(database)
138
- end
139
- self
140
- end
141
-
142
- # Create a schema diff between two database versions. to_version defaults to the
143
- # current version. Returns the Diff object
144
- def diff(from_version, to_version)
145
- begin
146
- from_db = Database.new("#{name}-base", user)
147
- to_db = Database.new("#{name}-next", user)
148
- from_version ||= version
149
- build(from_db, version: from_version)
150
- build(to_db, version: to_version)
151
- Diff.new(from_db, to_db)
152
- ensure
153
- from_db&.drop
154
- to_db&.drop
155
- end
156
- end
157
-
158
- def prepare_release(fork = nil)
159
- check_clean(:release_tag)
160
- @head = ReleaseBranch.new(fork, version).create
161
- submit "Prepared new release based on v#{version}", true
162
- self
163
- end
164
-
165
- def prepare_schema(name, commit: true)
166
- path = File.join(SCHEMA_DIR, name)
167
- FileUtils.mkdir_p(path)
168
- Git.add Share.cp("schema/schema.sql", path, clobber: false, templates: { 'SCHEMA' => name })
169
- Git.add Share.cp("schema/build.yml", path, clobber: false)
170
- File.open(Schema.yml_file, "a") { |f| f.write("- #{name}\n") }
171
- Git.add(Schema.yml_file)
172
- submit "Added schema #{name}", commit
173
- end
174
-
175
- def prepare_diff(from_version = version)
176
- begin
177
- from_name = "#{name}-base"
178
- from_db = Database.new(from_name, user)
179
- build(from_db, version: from_version)
180
-
181
- to_name = "#{name}-next"
182
- to_db = Database.new(to_name, user)
183
- build(to_db)
184
-
185
- if prerelease_branch?
186
- head.migrate_features(from_db)
187
- end
188
-
189
- diff = Diff.new(from_db, to_db)
190
- for path, lines, tables in [
191
- [BEFORE_TABLES_DIFF_PATH, diff.before_table_changes, false],
192
- [TABLES_DIFF_PATH, diff.table_changes, true],
193
- [AFTER_TABLES_DIFF_PATH, diff.after_table_changes, false]]
194
- if lines.empty?
195
- if File.exist?(path)
196
- if tables
197
- Share.cp(File.join("diff", File.basename(path)), path)
198
- Git.add(path)
199
- else
200
- Git.rm(path)
201
- end
202
- end
203
- else
204
- Share.cp(File.join("diff", File.basename(path)), path)
205
- File.open(path, "a") { |f| f.puts lines }
206
- Git.add(path) if !tables
207
- end
208
- end
209
- self
210
- ensure
211
- from_db&.drop
212
- to_db&.drop
213
- end
214
- end
215
-
216
- def create_release(new_version)
217
- check_clean(:release_branch)
218
- head = ReleaseTag.new(new_version, version)
219
- check_migration(head.migration)
220
- (@head = head).create
221
- self
222
- end
223
-
224
- def generate_schema
225
- build = SchemaBuilder.new(database, SCHEMA_DIR).build(execute: false)
226
- puts build.lines
227
- end
228
-
229
- def generate_migration
230
- build = MigrationBuilder.new(database, MIGRATION_DIR).build(execute: false)
231
- puts build.lines
232
- end
233
-
234
- private
235
- def check(kind) self.send(:"#{kind}?") end
236
- def check_clean(kind = nil)
237
- clean? or raise Internal, "Dirty repository"
238
- kind.nil? || check(kind) or raise Internal, "Not on a #{kind} tag/branh"
239
- end
240
-
241
- def check_branch() branch? or raise Internal, "Not on a branch" end
242
- def check_tag() tag? or raise Internal, "Not on a tag" end
243
-
244
- # FIXME: Use Cache::file
245
- def cache_file(version) File.join(CACHE_DIR, "#{database(version)}.sql.gz") end
246
-
247
- def submit(msg, commit = true)
248
- Git.commit msg if commit
249
- @message = msg
250
- end
251
-
252
- def clean(database) # FIXME: Use Database#clean
253
- if database.exist?
254
- database.recreate if database.loaded?
255
- else
256
- database.create
257
- end
258
- end
259
-
260
- def check_migration(migration)
261
- begin
262
- from_version = migration.base_version
263
- from_db = Database.new("#{name}-base", user)
264
- to_db = Database.new("#{name}-next", user)
265
- build(from_db, version: from_version)
266
- build(to_db)
267
- migration.migrate(from_db)
268
- Diff.new(from_db, to_db).same? or raise Error, "Schema/migration mismatch"
269
- ensure
270
- from_db&.drop
271
- to_db&.drop
272
- end
273
- end
274
- end
275
- end
276
-
277
- __END__
278
-
279
- module Prick
280
- class Project
281
- # Name of project. Persisted in the project state file
282
- attr_reader :name
283
-
284
- # Name of Postgresql user that owns the databases. Defaults to #name.
285
- # Persisted in the project state file. TODO: Make writable
286
- attr_reader :user
287
-
288
- # Current branch
289
- attr :branch
290
-
291
- # Version of the current branch. If is defined as #branch.version
292
- def version() branch.version end
293
-
294
- # Project (default) database
295
- def database(version = nil)
296
- version ? Database.new("#{name}-#{version.truncate(:pre)}", user) : @database
297
- end
298
-
299
- # Last commit message. TODO: Move to git.rb
300
- attr_reader :message
301
-
302
- # True if we're on a tag
303
- def tag?() Git.detached? end
304
- def self.tag?() Git.detached? end
305
-
306
- # Classifiers
307
- forward_methods :release?, :prerelease?, :feature?, :migration?, :@branch
308
-
309
- def initialize(name, user, branch)
310
- @name = name
311
- @user = user
312
- @branch = branch
313
- @database = Database.new(name, user)
314
- end
315
-
316
- def self.load
317
- name = Git.current_branch || Git.current_tag
318
- if name =~ MIGRATION_RE
319
- branch = MigrationRelease.load(name)
320
- else
321
- begin
322
- version = Version.new(name)
323
- rescue Version::FormatError
324
- raise Fail, "Illegal branch name: #{name}"
325
- end
326
- if version.release?
327
- branch = Release.load(name)
328
- elsif version.pre?
329
- branch = PreRelease.load(name, version)
330
- elsif version.feature?
331
- branch = Feature.load(name)
332
- else
333
- raise Oops
334
- end
335
- end
336
- state = ProjectState.new.read
337
- Project.new(state.name, state.user, branch)
338
- end
339
-
340
- def self.initialized?(directory)
341
- File.directory?(directory) && Dir.chdir(directory) { ProjectState.new.exist? }
342
- end
343
-
344
- def self.initialize_directory(name, user, directory)
345
- FileUtils.mkdir_p(directory)
346
- Dir.chdir(directory) {
347
- # Initialize git instance
348
- Git.init
349
-
350
- # Create prick version file
351
- PrickVersion.new.write(VERSION)
352
-
353
- # Create project state file
354
- ProjectState.new(name: name, user: user).write
355
-
356
- # Directories
357
- DIRS.each { |dir|
358
- !File.exist?(dir) or raise Fail, "Already initialized: Directory '#{dir}' exists"
359
- }
360
- FileUtils.mkdir_p(DIRS)
361
- DIRS.each { |dir| FileUtils.touch("#{dir}/.keep") }
362
-
363
- # Copy default gitignore and schema files
364
- Share.cp("gitignore", ".gitignore")
365
- Share.cp("schemas", ".")
366
-
367
- # Add everything so far
368
- Git.add(".")
369
- Git.commit("Initial import")
370
-
371
- # Create initial release
372
- release = Release.new(Version.zero, nil)
373
- release.create
374
-
375
- schema = Schema.new(SCHEMAS_DIR)
376
- schema.version = release.version
377
- Git.add schema.version_file
378
-
379
- Git.commit "Release 0.0.0"
380
- release.tag!
381
-
382
- # Kill master branch
383
- Git.delete_branch("master")
384
- }
385
- end
386
-
387
- def build(database: self.database, version: nil)
388
- clean(database)
389
- if version
390
- FileUtils.mkdir_p(TMP_DIR)
391
- Dir.mktmpdir("clone-", TMP_DIR) { |dir|
392
- Command.command "git clone . #{dir}"
393
- Dir.chdir(dir) {
394
- Git.checkout_tag(version)
395
- project = Project.load
396
- project.branch.build(database)
397
- }
398
- }
399
- else
400
- branch.build(database)
401
- end
402
- self
403
- end
404
-
405
- def load(file, database: self.database)
406
- clean(database)
407
- database.load(file)
408
- self
409
- end
410
-
411
- def save(file, database: self.database)
412
- database.save(file)
413
- self
414
- end
415
-
416
- def cache_file(version) File.join(CACHE_DIR, "#{database(version)}.sql.gz") end
417
-
418
- def make(database, subject)
419
- Schema.built? or raise Error, "Schema is not built into project database"
420
- Schema.make(database, subject)
421
- end
422
-
423
- def backup(path = nil)
424
- save path || File.join(SPOOL_DIR, "#{name}-#{Time.now.utc.strftime("%Y%m%d-%H%M%S")}.sql.gz")
425
- end
426
-
427
- def restore(path = nil)
428
- load path || Dir.glob(File.join(SPOOL_DIR, "#{name}-*.sql.gz")).sort.last
429
- end
430
-
431
- def prepare_release(commit: true)
432
- release = ReleaseMigration.new(nil, branch.version).create
433
- submit "Prepared new release based on #{version}", commit
434
- release
435
- end
436
-
437
- def prepare_schema(name, commit: true)
438
- path = File.join(SCHEMAS_DIR, name)
439
- FileUtils.mkdir_p(path)
440
- Git.add Share.cp("schema/*", path, clobber: false, templates: { 'SCHEMA' => name })
441
- File.open(branch.schema.yml_file, "a") { |f| f.write("- #{name}\n") }
442
- Git.add(branch.schema.yml_file)
443
- submit "Added schema #{name}", commit
444
- end
445
-
446
- def prepare_diff(from_version)
447
- to_database = nil
448
- begin
449
- from_name = "#{name}-base"
450
- from_database = Database.new(from_name, user)
451
- build(database: from_database, version: from_version)
452
-
453
- to_name = "#{name}-next"
454
- to_database = Database.new(to_name, user)
455
- build(database: to_database)
456
-
457
- # Helpful double-check
458
- Diff.same?(to_database.name, database.name) or
459
- raise Error, "Schema and project database are not synchronized"
460
-
461
- if release?
462
- dir = branch.migration.migration_dir
463
- else
464
- dir = branch.migration.features_dir
465
- end
466
-
467
- # dir = branch.migration.features_dir || branch.migration.migration_dir
468
- to_file = File.join(dir, DIFF_FILE)
469
-
470
- if prerelease?
471
- branch.migrate_features(from_database)
472
- end
473
-
474
- Diff.new(from_name, to_name).write(to_file)
475
- ensure
476
- from_database&.drop
477
- to_database&.drop
478
- end
479
- end
480
-
481
- def prepare_migration(from, commit: true)
482
- to = branch.version
483
- migration_release = MigrationRelease.new(to, from)
484
- migration_release.create
485
- submit "Prepared migration from #{from} to #{to}", commit
486
- migration_release
487
- end
488
-
489
- def create_release(version, commit: true)
490
- check_migration(branch.version) or raise Error, "Schema/migration mismatch"
491
- release = Release.new(version, branch.version)
492
- release.create
493
- submit "Created release #{version}", commit
494
- release.tag!
495
- build
496
- release
497
- end
498
-
499
- def cancel_release(version, commit: true)
500
- Git.cancel_tag(version)
501
- end
502
-
503
- def create_release_from_prerelease(commit: true)
504
- check_migration(branch.base_version) or raise Error, "Schema/migration mismatch"
505
- release = Release.new(branch.version.truncate(:pre), branch.base_version)
506
- release.create
507
- submit "Released #{release.version}", commit
508
- release.tag!
509
- build
510
- release
511
- end
512
-
513
- def create_prerelease(version, commit: true)
514
- prerelease = PreRelease.new(version.increment(:pre), branch.version)
515
- prerelease.create
516
- submit "Created pre-release #{prerelease.version}", commit
517
- build
518
- prerelease
519
- end
520
-
521
- def increment_prerelease(commit: true)
522
- prerelease = branch.increment
523
- prerelease.create
524
- submit "Created pre-release #{prerelease.version}", commit
525
- build
526
- prerelease
527
- end
528
-
529
- # # Turned out to be a bad idea
530
- # def retarget_migration(version, commit: true)
531
- # branch.retarget(version)
532
- # commit "Retargeted to #{version}" if commit
533
- # branch
534
- # end
535
-
536
- def create_feature(name, commit: true)
537
- feature = Feature.new(name, version)
538
- feature.create
539
- submit "Created feature #{name}", commit
540
- end
541
-
542
- def include_feature(feature_version, commit: false)
543
- Git.merge_branch(feature_version, exclude_files: [branch.schema.version_file], fail: true)
544
- branch.include(feature_version)
545
- end
546
-
547
- # Checks that the migration of the current branch takes the database from
548
- # the base version to the content of the schema
549
- def check_migration(from_version)
550
- begin
551
- from_db = Database.new("#{name}-base", user)
552
- to_db = Database.new("#{name}-next", user)
553
- build(database: from_db, version: from_version)
554
- build(database: to_db)
555
- migration = # FIXME: This may be a repeated pattern
556
- if migration?
557
- branch.migration
558
- elsif prerelease?
559
- branch.migration
560
- else
561
- Migration.new(nil, branch.directory)
562
- end
563
- migration.migrate(from_db)
564
- Diff.new(from_db, to_db).same?
565
- ensure
566
- from_db&.drop
567
- to_db&.drop
568
- end
569
- end
570
-
571
- # TODO: Make production-only and add a to-argument
572
- def upgrade
573
- branches = list_upgrades(database.version, branch.version)
574
- FileUtils.mkdir_p(TMP_DIR)
575
- Dir.mktmpdir("clone-", TMP_DIR) { |dir|
576
- Command.command "git clone . #{dir}"
577
- Dir.chdir(dir) {
578
- branches.each { |branch|
579
- branch.checkout_release
580
- project = Project.load
581
- project.branch.migrate(project.database)
582
- }
583
- }
584
- }
585
- end
586
-
587
- def list_releases(all: false)
588
- Git.list_tags(include_cancelled: all).grep(RELEASE_RE) { |tag|
589
- version = $2
590
- dir = File.join(RELEASES_DIR, version)
591
- migration_state = MigrationState.new(dir).read(tag: tag)
592
- Release.new(migration_state.version, migration_state.base_version)
593
- }
594
- end
595
-
596
- # TODO
597
- # list_migrations(all: false)
598
- def list_migrations
599
- Git.list_branches.grep(MIGRATION_RE) { |branch|
600
- from_version = Version.new($1)
601
- to_version = Version.new($4)
602
- MigrationRelease.new(to_version, from_version)
603
- }
604
- end
605
-
606
- def list_upgrades(from, to)
607
- edges = (list_releases + list_migrations).map { |branch| [branch.base_version, branch.version, branch] }
608
- (Algorithm.shortest_path(edges, from, to) || []).map(&:last)
609
- end
610
-
611
- private
612
- def submit(msg, commit = true)
613
- Git.commit msg if commit
614
- @message = msg
615
- end
616
-
617
- def clean(database)
618
- if database.exist?
619
- database.recreate if database.loaded?
620
- else
621
- database.create
622
- end
623
- end
624
- end
625
- end
626
-