prick 0.3.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/TODO +7 -0
  4. data/exe/prick +235 -163
  5. data/lib/ext/fileutils.rb +7 -0
  6. data/lib/prick.rb +7 -5
  7. data/lib/prick/builder.rb +31 -8
  8. data/lib/prick/cache.rb +34 -0
  9. data/lib/prick/constants.rb +106 -54
  10. data/lib/prick/database.rb +26 -20
  11. data/lib/prick/diff.rb +103 -25
  12. data/lib/prick/git.rb +31 -9
  13. data/lib/prick/head.rb +183 -0
  14. data/lib/prick/migration.rb +41 -181
  15. data/lib/prick/program.rb +255 -0
  16. data/lib/prick/project.rb +264 -0
  17. data/lib/prick/rdbms.rb +3 -12
  18. data/lib/prick/schema.rb +6 -11
  19. data/lib/prick/state.rb +129 -74
  20. data/lib/prick/version.rb +41 -28
  21. data/prick.gemspec +3 -1
  22. data/share/diff/diff.after-tables.sql +4 -0
  23. data/share/diff/diff.before-tables.sql +4 -0
  24. data/share/diff/diff.tables.sql +8 -0
  25. data/share/migration/diff.tables.sql +8 -0
  26. data/share/{release_migration → migration}/features.yml +0 -0
  27. data/share/migration/migrate.sql +3 -0
  28. data/share/{release_migration → migration}/migrate.yml +3 -0
  29. data/share/migration/tables.sql +3 -0
  30. data/share/{schemas → schema/schema}/build.yml +0 -0
  31. data/share/{schemas → schema/schema}/prick/build.yml +0 -0
  32. data/share/schema/schema/prick/data.sql +7 -0
  33. data/share/{schemas → schema/schema}/prick/schema.sql +0 -0
  34. data/share/{schemas → schema/schema}/prick/tables.sql +2 -2
  35. data/share/{schemas → schema/schema}/public/.keep +0 -0
  36. data/share/{schemas → schema/schema}/public/build.yml +0 -0
  37. data/share/{schemas → schema/schema}/public/schema.sql +0 -0
  38. data/test_refactor +34 -0
  39. metadata +23 -21
  40. data/file +0 -0
  41. data/lib/prick/build.rb +0 -376
  42. data/lib/prick/migra.rb +0 -22
  43. data/share/feature_migration/diff.sql +0 -2
  44. data/share/feature_migration/migrate.sql +0 -2
  45. data/share/release_migration/diff.sql +0 -3
  46. data/share/release_migration/migrate.sql +0 -5
  47. data/share/schemas/prick/data.sql +0 -7
data/prick.gemspec CHANGED
@@ -1,4 +1,6 @@
1
1
 
2
+ #$LOAD_PATH.unshift("/home/clr/prj/shellopts/lib")
3
+
2
4
  #lib = File.expand_path("../lib", __FILE__)
3
5
  #$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
6
  #require "prick/version"
@@ -29,7 +31,7 @@ Gem::Specification.new do |spec|
29
31
  spec.require_paths = ["lib"]
30
32
 
31
33
  # spec.add_dependency "pg"
32
- spec.add_dependency "shellopts", "2.0.0.pre.11"
34
+ spec.add_dependency "shellopts", "2.0.0.pre.14"
33
35
  spec.add_dependency "semantic"
34
36
  spec.add_dependency "indented_io"
35
37
  end
@@ -0,0 +1,4 @@
1
+ -- Generated by prick(1) via migra(1). Please don't touch.
2
+ --
3
+ -- It should not be necessary to change this file as it doesn't contain data changes
4
+ --
@@ -0,0 +1,4 @@
1
+ -- Generated by prick(1) via migra(1). Please don't touch.
2
+ --
3
+ -- It should not be necessary to change this file as it doesn't contain data changes
4
+ --
@@ -0,0 +1,8 @@
1
+ -- Generated by prick(1) via migra(1). Please don't touch.
2
+ --
3
+ -- This file contains changes that can touch existing data in the database that
4
+ -- needs speciel treatment in the migrate.sql
5
+ --
6
+ -- Note that this file is not executed by prick by default and that it is not
7
+ -- added to the Git repo when it changes. You have to do that manually
8
+ --
@@ -0,0 +1,8 @@
1
+ -- Generated by prick(1) via migra(1). Please don't touch.
2
+ --
3
+ -- This file contains changes that can touch existing data in the database that
4
+ -- needs speciel treatment in the migrate.sql
5
+ --
6
+ -- Note that this file is not executed by prick by default and that it is not
7
+ -- added to the Git repo when it changes. You have to do that manually
8
+ --
File without changes
@@ -0,0 +1,3 @@
1
+ -- Customize your migrations here but
2
+ --
3
+
@@ -2,4 +2,7 @@
2
2
  #
3
3
  ---
4
4
  - features
5
+ - diff.before-tables.sql
6
+ - tables
5
7
  - migrate.sql
8
+ - diff.after-tables.sql
@@ -0,0 +1,3 @@
1
+ -- Placeholder for table changes. After you prepared a diff, you should inspect
2
+ -- diff.table.sql and incorporate the changes here
3
+ --
File without changes
File without changes
@@ -0,0 +1,7 @@
1
+ -- Auto-generated file. Don't touch
2
+ --
3
+
4
+ COPY prick.versions (id, fork, major, minor, patch, pre, feature, version) FROM stdin;
5
+ 1 \N 0 0 0 \N \N 0.0.0
6
+ \.
7
+
File without changes
@@ -6,11 +6,11 @@ set search_path to prick;
6
6
 
7
7
  create table versions (
8
8
  id integer generated by default as identity primary key,
9
- custom varchar,
9
+ fork varchar,
10
10
  major integer not null,
11
11
  minor integer not null,
12
12
  patch integer not null,
13
- pre varchar,
13
+ pre integer,
14
14
  feature varchar,
15
15
  version varchar not null
16
16
  );
File without changes
File without changes
File without changes
data/test_refactor ADDED
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/bash
2
+
3
+ function add_table() {
4
+ local name=$1
5
+ echo "Creating table $name"
6
+ echo "create table $name (id integer);" >>schema/public/tables.sql
7
+ git add schema/public/tables.sql
8
+ git commit -m "Added table $name" >/dev/null
9
+ }
10
+
11
+ function add_migration() {
12
+ echo "Creating migration"
13
+ cp schema/public/tables.sql migration/diff.sql
14
+ echo '\i diff.sql' >migration/migrate.sql
15
+ git commit -am "Added migration"
16
+ }
17
+
18
+ set -e
19
+ clear
20
+
21
+ if [ -d dir ]; then
22
+ find dir -type f -delete
23
+ else
24
+ mkdir dir
25
+ fi
26
+
27
+ cd dir
28
+ prick --name prj init "."
29
+
30
+ prick prepare release
31
+ add_table a
32
+ add_migration
33
+ prick create release 0.1.0
34
+
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.3.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Claus Rasmussen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-01-05 00:00:00.000000000 Z
11
+ date: 2021-02-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: shellopts
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 2.0.0.pre.11
19
+ version: 2.0.0.pre.14
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 2.0.0.pre.11
26
+ version: 2.0.0.pre.14
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: semantic
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -78,7 +78,6 @@ files:
78
78
  - doc/prick.txt
79
79
  - doc/sh.prick
80
80
  - exe/prick
81
- - file
82
81
  - lib/ext/algorithm.rb
83
82
  - lib/ext/fileutils.rb
84
83
  - lib/ext/forward_method.rb
@@ -87,8 +86,8 @@ files:
87
86
  - lib/prick.rb
88
87
  - lib/prick/archive.rb
89
88
  - lib/prick/branch.rb
90
- - lib/prick/build.rb
91
89
  - lib/prick/builder.rb
90
+ - lib/prick/cache.rb
92
91
  - lib/prick/command.rb
93
92
  - lib/prick/constants.rb
94
93
  - lib/prick/database.rb
@@ -97,7 +96,7 @@ files:
97
96
  - lib/prick/ensure.rb
98
97
  - lib/prick/exceptions.rb
99
98
  - lib/prick/git.rb
100
- - lib/prick/migra.rb
99
+ - lib/prick/head.rb
101
100
  - lib/prick/migration.rb
102
101
  - lib/prick/program.rb
103
102
  - lib/prick/project.rb
@@ -110,8 +109,9 @@ files:
110
109
  - make_releases
111
110
  - make_schema
112
111
  - prick.gemspec
113
- - share/feature_migration/diff.sql
114
- - share/feature_migration/migrate.sql
112
+ - share/diff/diff.after-tables.sql
113
+ - share/diff/diff.before-tables.sql
114
+ - share/diff/diff.tables.sql
115
115
  - share/features/diff.sql
116
116
  - share/features/feature/diff.sql
117
117
  - share/features/feature/migrate.sql
@@ -119,22 +119,24 @@ files:
119
119
  - share/features/features.yml
120
120
  - share/features/migrations.sql
121
121
  - share/gitignore
122
- - share/release_migration/diff.sql
123
- - share/release_migration/features.yml
124
- - share/release_migration/migrate.sql
125
- - share/release_migration/migrate.yml
122
+ - share/migration/diff.tables.sql
123
+ - share/migration/features.yml
124
+ - share/migration/migrate.sql
125
+ - share/migration/migrate.yml
126
+ - share/migration/tables.sql
126
127
  - share/schema/build.yml
127
128
  - share/schema/schema.sql
128
- - share/schemas/build.yml
129
- - share/schemas/prick/build.yml
130
- - share/schemas/prick/data.sql
131
- - share/schemas/prick/schema.sql
132
- - share/schemas/prick/tables.sql
133
- - share/schemas/public/.keep
134
- - share/schemas/public/build.yml
135
- - share/schemas/public/schema.sql
129
+ - share/schema/schema/build.yml
130
+ - share/schema/schema/prick/build.yml
131
+ - share/schema/schema/prick/data.sql
132
+ - share/schema/schema/prick/schema.sql
133
+ - share/schema/schema/prick/tables.sql
134
+ - share/schema/schema/public/.keep
135
+ - share/schema/schema/public/build.yml
136
+ - share/schema/schema/public/schema.sql
136
137
  - test_assorted
137
138
  - test_feature
139
+ - test_refactor
138
140
  - test_single_dev
139
141
  homepage: http://www.nowhere.com/
140
142
  licenses: []
data/file DELETED
File without changes
data/lib/prick/build.rb DELETED
@@ -1,376 +0,0 @@
1
-
2
- require "prick/ensure.rb"
3
- require "prick/dsort.rb"
4
- require "ext/fileutils.rb" # for ::touch_p
5
-
6
- module Prick
7
- class Build
8
- include Ensure
9
-
10
- # The associated project object
11
- attr_reader :project
12
-
13
- # Version
14
- attr_reader :version
15
-
16
- # Build name. Same as `version.to_s`
17
- def name() version.to_s end
18
-
19
- # Associated database object
20
- attr_reader :database
21
-
22
- # Schema object. Only defined when the build has been checked out
23
- attr_reader :schema
24
-
25
- # Migration object. Running the migration on a base release database will
26
- # mutate it into the current release
27
- attr_reader :migration
28
-
29
- # Path to a filesystem node that represents the build on disk. Used to
30
- # detect if a build is present in the current release's tree. It is
31
- # possible to infer the base release from the node - either by a naming
32
- # convention or by reading the file. Build::deref_node_file does that
33
- def node() raise AbstractMethod end
34
-
35
- # Base release. Returns nil if version is 0.0.0. Raises an exception if
36
- # branch is not represented on disk and it can't be inferred from the
37
- # version (only features)
38
- def base_release()
39
- return nil if version.zero?
40
- @base_release.present? or raise Internal, "Release #{name} is not present"
41
- @base_release
42
- end
43
-
44
- # List of features in this build. This requires the build to be present on disk
45
- def features()
46
- present? or raise "Build #{name} is not present"
47
- version.zero? ? [] : migration.feature_versions.map { |version| project[version] }
48
- end
49
-
50
- # Return the build's history as a hash from release to list of features
51
- def history()
52
- h = {}
53
- Algorithm.follow(self, :base_release).each { |release|
54
- h[release] = []
55
- indent {
56
- release.features.each { |feature| h[release] << feature }
57
- }
58
- }
59
- h
60
- end
61
-
62
- def initialize(project, base_release, version, migration, database: nil, schema: nil)
63
- base_release.nil? || base_release.is_a?(Release) or
64
- raise Internal, "Expected a Release object, got #{base_release.class}"
65
- version.is_a?(Version) or raise Internal, "Expected a Version object, got #{version.class}"
66
- @project = project
67
- @base_release = base_release
68
- @version = version
69
- @migration = migration
70
- @schema = Schema.new(project)
71
- @database = database || Database.new("#{project.name}-#{name}", project.user)
72
- project[name] = self
73
- end
74
-
75
- # Return true if the build exists as a branch in git
76
- def exist?() Git.branch?(name) end
77
-
78
- # Create and checkout the branch
79
- def create()
80
- !present? or raise Fail, "Build #{name} is already present on disk"
81
- !exist? or raise Fail, "Build #{name} is already present in git"
82
- Git.create_branch(name)
83
- Git.checkout_branch(name)
84
- end
85
-
86
- # FIXME: Kills the current branch under the feets of the application. Also doesn't update
87
- # internal structures in Project
88
- def destroy()
89
- project.release != self or raise Error, "Can't destroy current branch - #{self.version}"
90
- Git.delete_branch(name)
91
- end
92
-
93
- # True if the release is present in this git branch
94
- def present?() File.exist?(node) end
95
-
96
- # True if the release is the active branch
97
- def active?() Git.current_branch == name end
98
-
99
- def checkout()
100
- Git.checkout(name)
101
- end
102
-
103
- def checkback() # Doubtfull - creates strange results on Release and Prerelease branches
104
- base_release.checkout
105
- end
106
-
107
- def built?()
108
- active? && @schema.built?(@database)
109
- end
110
-
111
- def build()
112
- active? or raise Error, "Can't build: Not active"
113
- @schema.build(@database)
114
- end
115
-
116
- def rebuild()
117
- active? or raise Error, "Can't rebuild: Not active"
118
- @database.recreate
119
- build
120
- end
121
-
122
- def include_feature(feature)
123
- migration.include_feature(feature.migration)
124
- end
125
-
126
- def remove_feature(feature)
127
- raise NotYet
128
- end
129
-
130
- # Create a copy of the project in tmp/ and checkout the branch. Used to build
131
- # releases. Returns the path to the copy
132
- def snapshot() end
133
-
134
- # Sorting
135
- def <=>(other) version <=> other.version end
136
-
137
- # Use #name for String conversion
138
- def to_s() name end
139
-
140
- # Reads the name of the base release from a node (see Build#node)
141
- def self.deref_node_file(node)
142
- if File.basename(node) == "0.0.0"
143
- nil
144
- elsif File.symlink?(node) # Releases and prereleases
145
- symlink = Command.command("readlink -v #{node}").first
146
- value = File.basename(symlink.sub(/\/$/, ""))
147
- value == "/dev/null" ? nil : value
148
- elsif File.directory?(node) # Migrations
149
- name = File.basename(node)
150
- name =~ MIGRATION_RE or raise "Illegal migration name: #{name}"
151
- $1
152
- end
153
- end
154
-
155
- private
156
- @states = {
157
- exist: [:create, :destroy],
158
- initialized: [:exist, :initialize, false], # ???
159
- active: [:exist, :checkout, :checkback],
160
- # built: [:active, :build, lambda { |this| this.database.recreate } ],
161
- }
162
- end
163
-
164
- class AbstractRelease < Build
165
- # Tag
166
- def tag() [version.custom, "v#{version.semver}"].compact.join("-") end
167
-
168
- # Cache object
169
- attr_reader :archive
170
-
171
- # Redefine Build#node
172
- attr_reader :node
173
-
174
- # The directory representing this release. It is initially empty. It is the
175
- # same as the next release's migration directory and contains features that
176
- # require this release
177
- def release_dir() raise AbstractMethod end
178
-
179
- def initialize(project, base_release, version, migration, **opts)
180
- super
181
- @node = File.join(RELEASE_DIR, name)
182
- @archive = DumpFile.new(project, version.to_s)
183
- end
184
-
185
- def cached?() archive.exist? end
186
- def cache() database.save(archive.path) end
187
- def uncache() FileUtils.rm_f(archive.path) end
188
-
189
- def loaded?() schema.loaded?(database) end
190
- def load() database.ensure(:loaded, archive.file) end
191
- def unload() database.ensure(:loaded, expect: false) end
192
-
193
- def prepare(commit: true)
194
- migration.prepare
195
- Git.commit("Prepared next release") if commit
196
- end
197
-
198
- def <=>(other) version <=> other.version end
199
-
200
- # Create the release in Git and on the disk
201
- def create(create_release_link_file: true)
202
- super()
203
-
204
- # Create release link file (eg. releases/0.1.0)
205
- if create_release_link_file
206
- base_release_dir = (version.zero? ? "/dev/null" : "../#{migration.path}")
207
- Dir.chdir(RELEASE_DIR) {
208
- FileUtils.ln_s(base_release_dir, File.basename(node))
209
- }
210
- Git.add(node)
211
- end
212
-
213
- # Set schema version
214
- project.schema.version = version
215
- Git.add(project.schema.path)
216
- end
217
-
218
- def dump
219
- return self
220
- $stderr.puts "#{self.class} #{version}"
221
- $stderr.indent { |f|
222
- f.puts "node : #{node.inspect}"
223
- f.puts "base_release: #{base_release&.version.inspect}"
224
- f.puts "migration : #{migration&.path.inspect}"
225
- f.puts "release_dir : #{release_dir.inspect}"
226
- }
227
- self
228
- end
229
-
230
- private
231
- @ensure_states = {
232
- # cached: [:built, :cache, :uncache],
233
- loaded: [:cached, :load, :unload]
234
- }
235
- end
236
-
237
- class Release < AbstractRelease
238
- def release_dir() File.join(FEATURE_DIR, name) end
239
-
240
- def initialize(project, base_release, version)
241
- migration = base_release && ReleaseMigration.new(base_release.release_dir)
242
- super(project, base_release, version, migration)
243
- end
244
-
245
- # Create the release in Git and on the disk. We assume that the migration exists
246
- def create
247
- super
248
-
249
- # Create migration link file
250
- if !version.zero?
251
- migration_version = "#{base_release.version}_#{version}"
252
- features = "../#{migration.path}"
253
- Dir.chdir(MIGRATION_DIR) {
254
- FileUtils.ln_s(features, migration_version)
255
- Git.add(migration_version)
256
- }
257
- end
258
-
259
- # Create new empty feature directory
260
- ReleaseMigration.new(release_dir).create
261
-
262
- Git.commit("Release #{version}")
263
- Git.create_tag(version)
264
- dump
265
- migration.dump if migration
266
- self
267
- end
268
- end
269
-
270
- # TODO: Rename to PreRelease
271
- class Prerelease < AbstractRelease
272
- attr_reader :target_release
273
-
274
- def release_dir() base_release.release_dir end
275
-
276
- def initialize(project, base_release, version, target_version = version.truncate(:pre))
277
- @target_release = Release.new(project, base_release, target_version)
278
- migration = ReleaseMigration.new(target_release.migration.path)
279
- super(project, base_release, version, migration)
280
- end
281
-
282
- # Create the pre-release in Git and on disk
283
- def create
284
- super
285
- migration.prepare
286
- Git.commit("Pre-release #{version}")
287
- dump
288
- self
289
- end
290
-
291
- # Create a migration for this release
292
- def prepare_migration
293
- base_release.built? or raise "Base release #{base_release} is not built"
294
- puts "Prerelease#generate_migration"
295
- end
296
- end
297
-
298
- class MigrationPrerelease < Prerelease
299
- def initialize(project, base_release, version, target_version = version.truncate(:pre))
300
- release_dir = "/migrations/..."
301
- end
302
- end
303
-
304
- class MigrationRelease < AbstractRelease
305
- def create
306
- # does not call super because migrations belong to the release they migrate to
307
- #
308
- # code, code, code
309
- end
310
-
311
- def include_feature
312
- raise NotYet
313
- end
314
- end
315
-
316
- class Feature < Build
317
- # Name of feature
318
- def feature() version.feature end
319
-
320
- # A feature's node is the feature directory
321
- def node() release_dir end
322
-
323
- def release_dir() migration.path end
324
-
325
- def initialize(project, base_release, name)
326
- base_release.is_a?(Release) || base_release.is_a?(Prerelease) or
327
- raise Internal, "Expected a Release object, got #{base_release.class}"
328
- version = Version.new(base_release.version, feature: name)
329
- migration = FeatureMigration.new(Migration.path(version))
330
- super(project, base_release, version, migration)
331
- end
332
-
333
- def checkout()
334
- super
335
- # FileUtils.ln_sf(feature, "feature")
336
- end
337
-
338
- def create
339
- super
340
- migration.create
341
- migration.prepare
342
- Git.commit("Created feature #{feature}")
343
- migration.dump
344
- self
345
- end
346
-
347
- # features/
348
- # 0.0.0/
349
- # feature_a
350
- # feature_b/
351
- # base_release.prick
352
- # name.yml <- 0.2.0/feature_b
353
- # rebased.yml <- reads base_release here
354
- #
355
- # 0.2.0/
356
- # feature_a -> 0.0.0/feature_a <- not rebased
357
- # feature_b -> 0.0.0/feature_b <- rebased
358
-
359
-
360
- def rebase(new_base_release)
361
- # Checkout new_base_release
362
- # Merge feature
363
- # Establish symlinks
364
- # Create as branch
365
-
366
- # new_base > base_release or
367
- # raise Error, "Can't rebase from #{base_release.version} to #{new_base.version}"
368
- # new_feature = Feature.new(project, base_release, base.version, base: base)
369
- # new_feature.ensure(:active)
370
- # schema.version = version
371
- # FileUtils.ln_sf("../#{feature.release_dir}", new_feature.release_dir)
372
- # Git.add(new_feature.release_dir)
373
- # new_feature
374
- end
375
- end
376
- end