prick 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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