prick 0.2.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.
@@ -0,0 +1,100 @@
1
+ require "prick/constants.rb"
2
+ require "prick/exceptions.rb"
3
+
4
+ module Prick
5
+ # TODO: Resolve dependencies by extracting \i includes and then execute them
6
+ # in topological order. This means the must be no 'if' constructs in the
7
+ # files because otherwise dependencies are not static. The rule is that if a
8
+ # file \i includes another file, then the included file can always be execute
9
+ # before the current file
10
+ #
11
+ # Alternatively add some special tags:
12
+ #
13
+ # -- require prick (meaning include the prick schema)
14
+ # -- require public/user-schema (include this file)
15
+ #
16
+ class Schema
17
+ # Enclosing project
18
+ attr_reader :project
19
+
20
+ # Path to data file
21
+ def Schema.data_file() DATA_SQL_PATH end
22
+ def data_file() Schema.data_file end
23
+
24
+ # Version read from schemas/prick/data.sql
25
+ def version()
26
+ @version ||= begin
27
+ File.open(data_file, "r") { |file|
28
+ while !file.eof? && file.gets.chomp != COPY_STMT
29
+ ;
30
+ end
31
+ !file.eof? or raise Fail, "No COPY statement in #{data_file}"
32
+ l = file.gets.chomp
33
+ a = l.split("\t")[1..].map { |val| val == '\N' ? nil : val }
34
+ a.size == FIELDS.size or raise Fail, "Illegal data format in #{data_file}"
35
+ custom, major, minor, patch, pre = a[0], *a[1..-2].map { |val| val && val.to_i }
36
+ v = Version.new("0.0.0", custom: (custom == '\N' ? nil : custom))
37
+ v.major = major
38
+ v.minor = minor
39
+ v.patch = patch
40
+ v.pre = (pre == "null" ? nil : pre)
41
+ v
42
+ }
43
+ end
44
+ end
45
+
46
+ # Write version number into schemas/prick/data.sql
47
+ def version=(version)
48
+ @version = Version.new(version)
49
+ File.open(data_file, "w") { |f|
50
+ f.puts "--"
51
+ f.puts "-- This file is auto-generated by prick(1). Please don't touch"
52
+ f.puts COPY_STMT
53
+ f.print \
54
+ "1\t",
55
+ FIELDS[..-2].map { |f| @version.send(f.to_sym) || '\N' }.join("\t"),
56
+ "\t#{@version}\n"
57
+ f.puts "\\."
58
+ }
59
+ Git.add(data_file)
60
+ @version
61
+ end
62
+
63
+ def initialize(project)
64
+ @project = project
65
+ end
66
+
67
+ # Path to the schemas directory
68
+ def path() "#{project.path}/#{SCHEMA_DIR}" end
69
+
70
+ def built?(database = project.database)
71
+ database.exist? && database.version == version
72
+ end
73
+
74
+ # Build a release from the files in schemas/
75
+ def build(database = project.database)
76
+ files = collect("schema.sql") + collect("data.sql")
77
+ Dir.chdir(path) {
78
+ files.each { |file| Rdbms.exec_file(database.name, file, user: project.user) }
79
+ }
80
+ end
81
+
82
+ # Collects instances of `filename` in sub-directories of schemas/
83
+ def collect(filename)
84
+ Dir.chdir(path) {
85
+ if File.exist?(filename)
86
+ [filename]
87
+ else
88
+ Dir["*/#{filename}"]
89
+ end
90
+ }
91
+ end
92
+
93
+ private
94
+ FIELDS = %w(custom major minor patch pre feature version)
95
+ COPY_STMT = "COPY prick.versions (id, #{FIELDS.join(', ')}) FROM stdin;"
96
+
97
+ DATA_SQL_PATH = "#{Prick::PRICK_DIR}/data.sql"
98
+ end
99
+ end
100
+
@@ -0,0 +1,133 @@
1
+
2
+ # Moved to lib/prick.rb to avoid having Gem depend on it
3
+ # require 'semantic' # https://github.com/jlindsey/semantic
4
+
5
+ # Required by gem
6
+ module Prick
7
+ VERSION = "0.2.0"
8
+ end
9
+
10
+ # Project related code starts here
11
+ module Prick
12
+ class Version
13
+ include Comparable
14
+
15
+ PRE_LABEL = "pre"
16
+ PRE_RE = /^#{PRE_LABEL}\.(\d+)$/
17
+
18
+ def self.zero() Version.new("0.0.0") end
19
+ def zero?() self == Version.zero end
20
+
21
+ # Return true if `string` is a version. If true, it sets the Regex capture
22
+ # groups 1-3. See also Constants::VERSION_RE
23
+ def self.version?(string) (string =~ VERSION_RE).nil? ? false : true end
24
+
25
+ attr_accessor :custom
26
+ attr_accessor :semver
27
+ attr_accessor :feature
28
+
29
+ def major() @semver.major end
30
+ def major=(major) @semver.major = major end
31
+
32
+ def minor() @semver.minor end
33
+ def minor=(minor) @semver.minor = minor end
34
+
35
+ def patch() @semver.patch end
36
+ def patch=(patch) @semver.patch = patch end
37
+
38
+ # Return true if this is a custom release
39
+ def custom?() !@custom.nil? end
40
+
41
+ # Return true if this is a feature release
42
+ def feature?() !@feature.nil? end
43
+
44
+ # Return true if this is a release branch
45
+ def release?() !feature? end
46
+
47
+ # Return true if this is a pre-release
48
+ def pre?() !@semver.pre.nil? end
49
+
50
+ # The releases is stored as a String (eg. 'pre.1') in the semantic version
51
+ # but #pre returns only the Integer number
52
+ def pre() @semver.pre =~ PRE_RE ? $1.to_i : nil end
53
+
54
+ # #pre= expects an integer or nil argument
55
+ def pre=(pre) @semver.pre = (pre ? "#{PRE_LABEL}.#{pre}" : nil) end
56
+
57
+ def dup() Version.new(self) end
58
+ def clone() Version.new(self) end
59
+
60
+ def eql?(other) self == other end
61
+ def hash() @semver.hash end
62
+
63
+ def initialize(version, custom: nil, feature: nil)
64
+ case version
65
+ when String
66
+ version =~ VERSION_RE
67
+ self.class.version?(version) or raise "Expected a version, got #{version.inspect}"
68
+ @custom = custom || $1
69
+ @semver = Semantic::Version.new($2)
70
+ @feature = feature || $3
71
+ when Semantic::Version
72
+ @custom = custom
73
+ @semver = version.dup
74
+ @feature = feature
75
+ when Version
76
+ @custom = custom || version.custom
77
+ @semver = version.semver.dup
78
+ @feature = feature || version.feature
79
+ else
80
+ raise "Expected a String, Version, or Semantic::Version, got #{version.class}"
81
+ end
82
+ end
83
+
84
+ # `part` can be one of :major, :minor, :patch, or :pre. If pre is undefined, it
85
+ # is set to `pre_initial_value`
86
+ def increment(part, pre_initial_value = 1)
87
+ if part == :pre
88
+ v = self.dup
89
+ v.pre = (v.pre ? v.pre+1 : pre_initial_value)
90
+ v
91
+ else
92
+ Version.new(semver.increment!(part), custom: custom, feature: feature)
93
+ end
94
+ end
95
+
96
+ def truncate(part)
97
+ case part
98
+ when :pre
99
+ v = self.dup
100
+ v.feature = nil
101
+ v.pre = nil
102
+ v
103
+ when :feature
104
+ v = self.dup
105
+ v.feature = nil
106
+ v
107
+ else
108
+ raise NotYet
109
+ end
110
+ end
111
+
112
+ def <=>(other)
113
+ r = (custom || "") <=> (other.custom || "")
114
+ return r if r != 0
115
+ r = semver <=> other.semver
116
+ return r if r != 0
117
+ r = (feature || "") <=> (other.feature || "")
118
+ return r
119
+ end
120
+
121
+ # Render as String
122
+ def to_s
123
+ (custom ? "#{custom}-" : "") + semver.to_s + (feature ? "_#{feature}" : "")
124
+ end
125
+
126
+ # Render as string
127
+ def inspect() to_s end
128
+ end
129
+
130
+ # ZERO = Version.new("0.0.0")
131
+ end
132
+
133
+
@@ -0,0 +1,369 @@
1
+ #!/usr/bin/bash
2
+
3
+ set -e
4
+ set -u
5
+ set -o pipefail
6
+
7
+ use_cache=false
8
+ create_cache=true
9
+
10
+
11
+
12
+ clear
13
+
14
+ ORG=$PWD
15
+ DIR=prj
16
+ PROJECT=prj
17
+ BASE=$PWD/$DIR
18
+
19
+ PUBLIC=schemas/public/schema.sql
20
+
21
+ alias prick='\prick -n $PROJECT'
22
+
23
+ rm -rf $DIR
24
+
25
+ echo "*** Initializing project"
26
+ prick -n $PROJECT init $DIR
27
+ cd $DIR
28
+ prick status
29
+ echo
30
+
31
+ echo "*** Create feature_a"
32
+ prick checkout 0.0.0
33
+ prick create feature feature_a
34
+ echo
35
+
36
+ echo "*** Add table public.a"
37
+ echo "create table a (id integer);" >>$PUBLIC
38
+ git add $PUBLIC
39
+ git commit -m "Added public.a (feature_a)"
40
+ echo
41
+
42
+ echo "*** Create migration"
43
+ prick prepare migration
44
+ echo "\\i diff.sql" >>features/0.0.0/feature_a/migrate.sql
45
+ git commit -am "Prepared migration"
46
+ echo
47
+
48
+ echo "*** Create feature_b"
49
+ prick checkout 0.0.0
50
+ prick create feature feature_b
51
+ echo "create table b (id integer);" >>$PUBLIC
52
+ git add $PUBLIC
53
+ git commit -m "Added public.b (feature_b)"
54
+ echo
55
+
56
+ echo "*** Create migration"
57
+ prick prepare migration
58
+ echo "\\i diff.sql" >>features/0.0.0/feature_b/migrate.sql
59
+ git commit -am "Prepared migration"
60
+ echo
61
+
62
+ echo "*** Create 0.1.0-pre.0"
63
+ prick checkout 0.0.0
64
+ prick create prerelease minor
65
+ prick status
66
+ echo
67
+
68
+ echo "*** Include feature_a"
69
+ prick include 0.0.0_feature_a
70
+ prick commit
71
+ echo
72
+
73
+ echo "*** Create release 0.1.0"
74
+ prick release
75
+ prick status
76
+ echo
77
+
78
+ echo "*** Create 0.1.1-pre.0"
79
+ prick checkout 0.1.0
80
+ prick create prerelease patch
81
+ echo
82
+
83
+ echo "*** Include feature_b"
84
+ prick include 0.0.0_feature_b
85
+ sed -i -e '/<<<</d' -e '/====/d' -e '/>>>>/d' $PUBLIC
86
+ git add $PUBLIC
87
+ prick commit
88
+ echo
89
+
90
+ echo "*** Release 0.2.0"
91
+ prick release
92
+ prick status
93
+ echo
94
+
95
+
96
+
97
+
98
+
99
+ #echo "*** Prepare migration"
100
+ #prick prepare migration
101
+ #echo
102
+
103
+
104
+
105
+
106
+
107
+
108
+
109
+
110
+
111
+ exit
112
+
113
+ ###################################
114
+
115
+ echo "*** Initializing project"
116
+ prick -n $PROJECT init $DIR
117
+ cd $DIR
118
+ prick status
119
+ echo
120
+
121
+ echo "*** Create feature_a"
122
+ prick checkout 0.0.0
123
+ prick create feature feature_a
124
+ echo
125
+
126
+ echo "*** Create feature_b"
127
+ prick checkout 0.0.0
128
+ prick create feature feature_b
129
+ echo
130
+
131
+ echo "*** Create feature_c"
132
+ prick checkout 0.0.0
133
+ prick create feature feature_c
134
+ echo
135
+
136
+ echo "*** Create feature_d"
137
+ prick checkout 0.0.0
138
+ prick create feature feature_d
139
+ echo
140
+
141
+ echo "*** Checkout 0.0.0"
142
+ prick checkout 0.0.0
143
+ prick status
144
+ echo
145
+
146
+ echo "*** Create 0.1.0-pre.0"
147
+ prick checkout 0.0.0
148
+ prick create prerelease minor
149
+ prick status
150
+ echo
151
+
152
+ echo "*** Include feature_a"
153
+ prick include "0.0.0_feature_a"
154
+ prick commit
155
+ echo
156
+
157
+ echo "*** Release 0.1.0"
158
+ prick release
159
+ prick status
160
+ echo
161
+
162
+ echo "*** Checkout 0.0.0_feature_c"
163
+ prick checkout 0.0.0_feature_c
164
+ prick status
165
+ echo
166
+
167
+ echo "*** Include feature_b in feature_c"
168
+ prick include 0.0.0_feature_b
169
+ prick commit
170
+ echo
171
+
172
+ echo "*** Create 0.2.0-pre.0"
173
+ prick checkout 0.1.0
174
+ prick create prerelease minor
175
+ prick status
176
+
177
+ echo "*** Include feature_c"
178
+ prick include 0.0.0_feature_c
179
+ prick commit
180
+ echo
181
+
182
+ echo "*** Release 0.2.0"
183
+ prick release
184
+ prick status
185
+ echo
186
+
187
+ echo "*** Create 1.0.0-pre.0"
188
+ prick checkout 0.2.0
189
+ prick create prerelease major
190
+ prick status
191
+
192
+ echo "create table tt (id integer)" >schemas/public/schema.sql
193
+ git add schemas/public/schema.sql
194
+ git commit -m "Added table public.tt"
195
+
196
+ prick prepare migration
197
+
198
+
199
+ #echo "*** Checkout 0.0.0_feature_d"
200
+ #prick checkout 0.0.0_feature_d
201
+ #prick status
202
+ #echo
203
+ #
204
+ #echo "*** Rebase to 0.2.0"
205
+ #prick rebase 0.2.0
206
+
207
+
208
+ exit
209
+
210
+
211
+
212
+
213
+
214
+
215
+
216
+
217
+
218
+
219
+
220
+
221
+
222
+
223
+
224
+
225
+
226
+
227
+
228
+ if ! $use_cache; then
229
+ prick -n $PROJECT init $DIR
230
+ cd $DIR
231
+
232
+ prick create feature feature_a
233
+ echo "create table feature_a_table (id integer);" >schemas/public/schema.sql
234
+ git add schemas/public/schema.sql
235
+ git commit -m "Added public.feature_a_table"
236
+ prick checkout 0.0.0
237
+ prick create prerelease minor
238
+ prick include 0.0.0_feature_a
239
+ prick commit
240
+ prick create release
241
+
242
+ prick create feature feature_b
243
+ echo "create table feature_b_table (id integer);" >>schemas/public/schema.sql
244
+ git add schemas/public/schema.sql
245
+ git commit -m "Added public.feature_b_table"
246
+ prick checkout 0.1.0
247
+ prick create feature feature_b2
248
+ prick include 0.1.0_feature_b
249
+ prick commit
250
+ prick checkout 0.1.0
251
+ prick create prerelease minor
252
+ # prick include 0.1.0_feature_b
253
+ # prick commit
254
+ prick create release
255
+
256
+ if $create_cache; then
257
+ cd $ORG
258
+ tar -zcf $DIR.tar.gz $DIR
259
+ cd $DIR
260
+ fi
261
+ else
262
+ tar -zxf $DIR.tar.gz $DIR
263
+ cd $DIR
264
+ fi
265
+
266
+ prick checkout 0.2.0
267
+ git status
268
+ prick create feature feature_c
269
+ git status
270
+
271
+ prick checkout 0.2.0
272
+ prick create feature feature_d
273
+ prick checkout 0.2.0_feature_d
274
+ prick include 0.2.0_feature_c
275
+ prick commit
276
+
277
+ prick checkout 0.2.0
278
+ prick create prerelease minor
279
+ prick include 0.2.0_feature_c
280
+ prick commit
281
+ prick include 0.2.0_feature_d
282
+ prick commit
283
+ prick include 0.1.0_feature_b2
284
+ prick commit
285
+
286
+ prick create release
287
+
288
+ # TODO features of older releases symlinks
289
+
290
+
291
+ mkdir migrations/0.0.0_0.2.0
292
+ cd migrations/0.0.0_0.2.0
293
+ touch migrations.sql
294
+ touch features.sql
295
+ touch diff.sql
296
+ ln -s ../../features/0.1.0/feature_b .
297
+ cd -
298
+
299
+ #mkdir features/0.3.0
300
+
301
+
302
+
303
+ exit
304
+
305
+
306
+ {
307
+ dropdb prick-0.1.0 || true
308
+ dropdb prick-0.2.0 || true
309
+ } &>/dev/null
310
+
311
+ prick -n $PROJECT build 0.1.0
312
+ prick -n $PROJECT build 0.2.0
313
+
314
+
315
+ exit
316
+
317
+ if ! $use_cache; then
318
+ prick -n $PROJECT init $DIR
319
+ cd $DIR
320
+
321
+ prick create prerelease minor
322
+ prick create release # 0.1.0
323
+ prick create feature my_feature # 0.1.0_my_feature
324
+ prick checkout 0.1.0
325
+ prick create feature another_feature
326
+ prick checkout 0.1.0
327
+ prick create prerelease minor
328
+
329
+ if $create_cache; then
330
+ cd $ORG
331
+ tar -zcf $DIR.tar.gz $DIR
332
+ cd $DIR
333
+ fi
334
+ else
335
+ tar -zxf $DIR.tar.gz $DIR
336
+ cd $DIR
337
+ fi
338
+
339
+ prick include 0.1.0_my_feature
340
+ prick commit
341
+
342
+
343
+ exit
344
+
345
+ if ! $use_cache; then
346
+ prick -n $PROJECT init $DIR
347
+ cd $DIR
348
+
349
+ prick create prerelease minor
350
+ prick increment prerelease
351
+ prick create release
352
+
353
+ prick prerelease minor
354
+ prick release
355
+
356
+ if $create_cache; then
357
+ cd $ORG
358
+ tar -zcf $DIR.tar.gz $DIR
359
+ cd $DIR
360
+ fi
361
+ else
362
+ tar -zxf $DIR.tar.gz $DIR
363
+ cd $DIR
364
+ fi
365
+
366
+ prick prepare
367
+ prick release 0.2.1
368
+
369
+ #clear; rm -rf ex; prick -n prick init ex && tree ex && (cd ex; git log; git status); prick -C ex -n prick prepare minor; prick -C ex -n prick prerelease