prick 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/TODO +7 -0
  4. data/exe/prick +95 -33
  5. data/lib/ext/fileutils.rb +7 -0
  6. data/lib/prick.rb +5 -3
  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 -18
  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 +199 -0
  16. data/lib/prick/project.rb +277 -0
  17. data/lib/prick/rdbms.rb +2 -1
  18. data/lib/prick/schema.rb +5 -10
  19. data/lib/prick/state.rb +129 -74
  20. data/lib/prick/version.rb +41 -28
  21. data/share/diff/diff.after-tables.sql +4 -0
  22. data/share/diff/diff.before-tables.sql +4 -0
  23. data/share/diff/diff.tables.sql +8 -0
  24. data/share/migration/diff.tables.sql +8 -0
  25. data/share/{release_migration → migration}/features.yml +0 -0
  26. data/share/migration/migrate.sql +3 -0
  27. data/share/{release_migration → migration}/migrate.yml +3 -0
  28. data/share/migration/tables.sql +3 -0
  29. data/share/{schemas → schema/schema}/build.yml +0 -0
  30. data/share/{schemas → schema/schema}/prick/build.yml +0 -0
  31. data/share/schema/schema/prick/data.sql +7 -0
  32. data/share/{schemas → schema/schema}/prick/schema.sql +0 -0
  33. data/share/{schemas → schema/schema}/prick/tables.sql +2 -2
  34. data/share/{schemas → schema/schema}/public/.keep +0 -0
  35. data/share/{schemas → schema/schema}/public/build.yml +0 -0
  36. data/share/{schemas → schema/schema}/public/schema.sql +0 -0
  37. data/test_refactor +34 -0
  38. metadata +22 -20
  39. data/file +0 -0
  40. data/lib/prick/build.rb +0 -376
  41. data/lib/prick/migra.rb +0 -22
  42. data/share/feature_migration/diff.sql +0 -2
  43. data/share/feature_migration/migrate.sql +0 -2
  44. data/share/release_migration/diff.sql +0 -3
  45. data/share/release_migration/migrate.sql +0 -5
  46. data/share/schemas/prick/data.sql +0 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 56c37c6657b0b17d1e166a17f0a832c2529a90459e620c68b2f078e22fa03185
4
- data.tar.gz: d9dc9dc4434248db40e8aa47b9cbc011ff4b11d39ea3796e8c3003aa536bee96
3
+ metadata.gz: 67c64dcd2eb2d716544b81a7b17f15c8b42af6b863821f411596fac4b6868edd
4
+ data.tar.gz: 178c2bd8cd8617fb4a10d6e1f76f15a601bb1341a2c64456a5c83ecc9eeff629
5
5
  SHA512:
6
- metadata.gz: b386cad69ddc0d893445b16209dc32ce20d63fc9d99d35cdfd7a34f5de6594401257e40bceb974287845c582f941523dc2ea959a92d48e9a2b8fa432f020904d
7
- data.tar.gz: c188655cd7538def6579d742b42b6ed38338e7908a451839fc76fcd9c945481b565022f191a67a9b1257d47abbc7bf1303593aee00cc77af474c3204e481cd3a
6
+ metadata.gz: 31fd38814ff54a3b535cabe371f1578abfcd025e749e9a9b1d18cdd454f7c74e5797b9166c4429f1bbda5ece50432bc0ace27d07a97e25591d1bae9648bb4b63
7
+ data.tar.gz: 8c9bf98db283cb79a11edd4016339c74c84fc02517b9872b476e776ecf21e91ecde490e87689a8ae1a041ecd25836f92d5d145ac6e2452824480a8a9db5c65c5
data/.gitignore CHANGED
@@ -24,3 +24,6 @@
24
24
 
25
25
  # Ignore development testing dir
26
26
  /dir
27
+
28
+ # Ignore stove-away directory
29
+ /hold
data/TODO CHANGED
@@ -1,3 +1,10 @@
1
1
 
2
+ o Check for commits to tags
3
+ o Accumulate version history in prick.versions instead of just having the newest
4
+ o Using rc's in migration syntax: fork-version-fork-version.rc1 ?
2
5
  o Make it possible to execute prick in any subdirecty instead of only in the root
6
+ o Hack migra to create separate file(s) for table changes
7
+ o Also execute subject/ directory if only a subject.sql is found. subject.yml
8
+ should still override everything
9
+ o Track included files - this will make dependency checks much easier
3
10
 
data/exe/prick CHANGED
@@ -24,12 +24,20 @@ SPEC = %(
24
24
  init! u,user=USER
25
25
 
26
26
  info!
27
- list! list.releases! m,migrations c,cancelled list.migrations! list.upgrades! a,all
27
+ list!
28
+ list.releases! m,migrations c,cancelled
29
+ list.migrations!
30
+ list.upgrades! a,all
31
+ list.cache!
28
32
 
29
33
  build! d,database=DATABASE C,nocache
30
- make!
34
+ make! d,database=DATABASE C,nocache
35
+ make.clean! a,all
31
36
  load! d,database=DATABASE
32
- save! d,database=DATABASE
37
+ save!
38
+ drop! a,all
39
+
40
+ diff! m,mark t,tables T,notables
33
41
  migrate!
34
42
 
35
43
  prepare! prepare.release! prepare.migration! prepare.schema! prepare.diff!
@@ -39,6 +47,7 @@ SPEC = %(
39
47
  create! create.release! create.prerelease! create.feature!
40
48
  cancel! cancel.release!
41
49
 
50
+ generate! generate.migration! generate.schema!
42
51
  upgrade!
43
52
  backup!
44
53
  restore!
@@ -72,7 +81,7 @@ HELP = %(
72
81
 
73
82
  COMMANDS
74
83
  INITIALIZATION
75
- init [DIR] --user=USER
84
+ init --user=USER [DIR]
76
85
  Initialize a project in the given directory. DIR defaults to the
77
86
  current directory. The USER is the postgres user, it defaults to
78
87
  the project name
@@ -86,32 +95,45 @@ HELP = %(
86
95
  List releases/migrations/upgrades
87
96
 
88
97
  BUILDING
89
- build -d database -C --nocache [version]
90
- Builds the current database from the content in the schemas/ directory.
91
- With an explicit version the given version is built or loaded from cache
92
- into the associated versioned database. The -C argument force a build even
93
- if a cache file is present. The -d option overrides the database
94
-
95
- make
96
- Not yet implemented
98
+ build -d DATABASE -C --nocache [TAG]
99
+ Build the current database from the content in the schemas/ directory.
100
+ With a tag the version is built into the associated versioned database.
101
+ The result is saved to cache unless the -C option is given. The -d option
102
+ overrides the default database
103
+
104
+ make -d DATABASE -C --nocache [TAG]
105
+ Loads the current database from cache if present and build it
106
+ otherwise. With a tag, the version is built into the associated
107
+ versioned database. The -C option ignores the cache and the -d option
108
+ overrides the default database
109
+
110
+ make clean -a
111
+ Drop versioned databases and remove cached and other temporary files.
112
+ Also drop the project database if the -a option is given
113
+
114
+ load -d DATABASE VERSION|FILE
115
+ Load the cached version or the file into the associated versioned
116
+ database. It is an error if the version hasn't been cached. The
117
+ --database argument overrides the database
118
+
119
+ save VERSION [FILE]
120
+ Save the versioned database associated with version to the cache or the
121
+ given file
122
+
123
+ drop --all [DATABASE]
124
+ Drop the given database or all versioned databases. The --all option also drops the project
125
+ database
97
126
 
98
- load -d database file|version
99
- Load a version or file into a database. If the argument is a version the
100
- assocated versioned database will be loaded from cache. If the argument is
101
- a file the project database is loaded. The -d option overrides what
102
- database is used. This is often used to load a specific version into the
103
- project database ('prick load -d <project-name> <version>') or to load into
104
- an unrelated database not controlled by prick
105
-
106
- save -d database [file]
107
- Save the project database to the given file. Default file name is the
108
- username suffixed with project name, custom name, and branch
127
+ diff [FROM-DATABASE|FROM-VERSION [TO-DATABASE|TO-VERSION]]
128
+ Create a schema diff between the given databases or versions. Default
129
+ to-version is the current schema and default from-version is the base
130
+ version of this branch/tag
109
131
 
110
132
  migrate
111
133
  Not yet implemented
112
134
 
113
135
  PREPARING RELEASES
114
- prepare release
136
+ prepare release [FORK]
115
137
  Populate the current migration directory with migration files
116
138
 
117
139
  prepare feature NAME
@@ -152,6 +174,10 @@ HELP = %(
152
174
  added a special cancel-tag to the release that makes prick ignore it
153
175
 
154
176
  DEPLOYING RELEASES
177
+ generate migration
178
+ generate schema
179
+ Create a PostgreSQL script to migrate or create the database
180
+
155
181
  upgrade
156
182
  Migrate the database to match the current schema
157
183
 
@@ -208,7 +234,7 @@ begin
208
234
  directory = args.expect(0..1)
209
235
  name = opts.name || directory || File.basename(Dir.getwd)
210
236
  user = opts.init.user || name
211
- program.initialize_directory(name, user, directory || ".")
237
+ program.init(name, user, directory || ".")
212
238
  exit 0
213
239
  end
214
240
 
@@ -218,6 +244,8 @@ begin
218
244
  VERSION == file.read.to_s or
219
245
  raise Prick::Fail, ".prick-version required prick-#{file.read} but you're using prick-#{VERSION}"
220
246
 
247
+ # TODO: Check for dirty detached head
248
+
221
249
  # Expect a sub-command
222
250
  opts.subcommand? or raise Prick::Error, "Subcomand expected"
223
251
 
@@ -230,20 +258,41 @@ begin
230
258
  version = args.expect(0..1)
231
259
  program.build(opts.build.database, version, opts.build.nocache)
232
260
 
233
- when :save
234
- file_or_version = args.expect(0..1)
235
- program.save(opts.save.database, file_or_version)
261
+ when :make
262
+ command = opts.make
263
+ case command.subcommand
264
+ when :clean
265
+ args.expect(0)
266
+ program.make_clean(command.clean.all)
267
+ else
268
+ version = args.expect(0..1)
269
+ program.make(opts.make.database, version, opts.make.nocache)
270
+ end
236
271
 
237
272
  when :load
238
- file_or_version = args.expect(1)
239
- program.load(opts.load.database, file_or_version)
273
+ version_or_file = args.expect(1)
274
+ program.load(opts.load.database, version_or_file)
240
275
 
241
- when :make
242
- raise NotYet
276
+ when :save
277
+ version, file = args.expect(1..2)
278
+ program.save(version, file)
279
+
280
+ when :diff
281
+ mark = opts.diff.mark
282
+ tables = opts.diff.tables
283
+ no_tables = opts.diff.notables
284
+ tables.nil? && no_tables.nil? || tables ^ no_tables or
285
+ raise Error, "--tables and --no-tables options are exclusive"
286
+ select = tables ? :tables : (no_tables ? :no_tables : :all)
287
+ from, to = args.expect(0..2)
288
+ program.diff(from, to, mark, select)
243
289
 
244
290
  when :migrate
245
291
  raise NotYet
246
292
 
293
+ when :drop
294
+ program.drop(args.expect(0..1), opts.drop.all)
295
+
247
296
  when :list
248
297
  command = opts.list
249
298
  case command.subcommand
@@ -252,6 +301,9 @@ begin
252
301
  program.list_releases(migrations: obj.migrations?, cancelled: obj.cancelled?)
253
302
  when :migrations; program.list_migrations
254
303
  when :upgrades; program.list_upgrades(*args.expect(0..2).compact)
304
+ when :cache;
305
+ args.expect(0)
306
+ program.list_cache
255
307
  when NilClass; raise Prick::Error, "list requires a releases|migrations|upgrades sub-command"
256
308
  else
257
309
  raise Prick::Internal, "Subcommand #{opts.subcommand}.#{command.subcommand} is not matched"
@@ -260,7 +312,7 @@ begin
260
312
  when :prepare
261
313
  cmd = opts.prepare.subcommand || :release
262
314
  case cmd
263
- when :release; args.expect(0); program.prepare_release
315
+ when :release; program.prepare_release(args.expect(0..1))
264
316
  when :feature; raise NotYet
265
317
  when :migration; program.prepare_migration(args.expect(1))
266
318
  when :schema; program.prepare_schema(args.expect(1))
@@ -300,6 +352,16 @@ begin
300
352
  raise Prick::Internal, "Subcommand #{opts.subcommand}.#{cmd} is not matched"
301
353
  end
302
354
 
355
+ when :generate
356
+ cmd = opts.generate.subcommand
357
+ case cmd
358
+ when :schema; program.generate_schema
359
+ when :migration; program.generate_migration
360
+ when nil; raise Prick::Error, "'genrate' subcommand require a 'schema' or 'migration' argument"
361
+ else
362
+ raise Prick::Internal, "Subcommand #{opts.subcommand}.#{cmd} is not matched"
363
+ end
364
+
303
365
  when :upgrade
304
366
  args.expect(0)
305
367
  program.upgrade
@@ -7,6 +7,7 @@ module FileUtils
7
7
  dir = File.dirname(file)
8
8
  File.exist?(dir) or FileUtils.mkdir_p(dir)
9
9
  touch(file)
10
+ file
10
11
  end
11
12
 
12
13
  def self.ln_sr(from, to)
@@ -16,4 +17,10 @@ module FileUtils
16
17
  relpath = from.relative_path_from(File.dirname(to))
17
18
  Dir.chdir(to_dir) { FileUtils.ln_s(relpath, File.basename(to)) }
18
19
  end
20
+
21
+ def self.empty!(dir)
22
+ Dir.chdir(dir) {
23
+ FileUtils.rm_rf(Dir.children("."))
24
+ }
25
+ end
19
26
  end
@@ -1,17 +1,20 @@
1
- require "semantic" # Defined here instead of in prick/version.rb to avoid having Gem depend on it
1
+
2
+ # 'semantic' is required here instead of in prick/version.rb to avoid having Gem depend on it
3
+ require "semantic"
2
4
 
3
5
  # Needs to go first because it contains class-level methods that is used by other modules
4
6
  require "ext/forward_method.rb"
5
7
 
6
- require "prick/branch.rb"
7
8
  require "prick/builder.rb"
8
9
  require "prick/migration.rb"
10
+ require "prick/cache.rb"
9
11
  require "prick/command.rb"
10
12
  require "prick/constants.rb"
11
13
  require "prick/database.rb"
12
14
  require "prick/diff.rb"
13
15
  require "prick/exceptions.rb"
14
16
  require "prick/git.rb"
17
+ require "prick/head.rb"
15
18
  require "prick/project.rb"
16
19
  require "prick/rdbms.rb"
17
20
  require "prick/schema.rb"
@@ -26,4 +29,3 @@ require "indented_io"
26
29
 
27
30
  module Prick
28
31
  end
29
-
@@ -24,14 +24,19 @@ module Prick
24
24
  attr_reader :database
25
25
  attr_reader :directory
26
26
  attr_reader :default # either "build" or "migrate"
27
+ attr_reader :lines
27
28
 
28
29
  def initialize(database, directory, default)
29
30
  @database = database
30
31
  @directory = directory
31
32
  @default = default
33
+ @execute = true
34
+ @lines = []
32
35
  end
33
36
 
34
- def build(subject = nil)
37
+ def build(subject = default, execute: true)
38
+ @execute = execute
39
+ @lines = []
35
40
  # puts "Building #{subject.inspect}"
36
41
  Dir.chdir(directory) {
37
42
  if subject
@@ -40,6 +45,8 @@ module Prick
40
45
  build_directory(".")
41
46
  end
42
47
  }
48
+ @lines.reject! { |l| l =~ /^\s*--/ || l =~ /^\s*$/ }
49
+ self
43
50
  end
44
51
 
45
52
  def self.yml_file(directory) raise NotThis end
@@ -52,13 +59,26 @@ module Prick
52
59
 
53
60
  def do_sql(path)
54
61
  # puts "do_sql(#{path})"
55
- do_dir(path) { |file| Rdbms.exec_file(database.name, file, user: database.user) }
62
+ do_dir(path) { |file|
63
+ if @execute
64
+ Rdbms.exec_file(database.name, file, user: database.user)
65
+ else
66
+ @lines += IO.readlines(file).map(&:chomp)
67
+ end
68
+ }
56
69
  true
57
70
  end
58
71
 
59
72
  def do_exe(path)
60
73
  # puts "do_exe(#{path})"
61
- do_dir(path) { |file| Command.command "#{file} #{database.name} #{database.user}" } # FIXME Security
74
+ do_dir(path) { |file|
75
+ lines = Command.command "#{file} #{database.name} #{database.user}" # FIXME Security
76
+ if @execute
77
+ Rdbms.exec_sql(database.name, lines.join("\n"), database.user)
78
+ else
79
+ @lines += lines
80
+ end
81
+ }
62
82
  true
63
83
  end
64
84
 
@@ -73,9 +93,9 @@ module Prick
73
93
  def build_subject(subject)
74
94
  if File.file?(subject) && File.executable?(subject)
75
95
  do_exe(subject)
76
- elsif subject.end_with?(".yml")
96
+ elsif File.file?(subject) && subject.end_with?(".yml")
77
97
  do_yml(subject)
78
- elsif subject.end_with?(".sql")
98
+ elsif File.file?(subject) && subject.end_with?(".sql")
79
99
  do_sql(subject)
80
100
  elsif File.exist?(yml_file = "#{subject}.yml")
81
101
  do_yml(yml_file)
@@ -90,7 +110,7 @@ module Prick
90
110
 
91
111
  def build_directory(path)
92
112
  Dir.chdir(path) {
93
- build_subject(File.join(path, "build")) || begin
113
+ build_subject(File.join(path, @default)) || begin
94
114
  if Dir["#{path}/#{default}", "#{path}/#{default}.yml", "#{path}/#{default}.sql"]
95
115
  subjects = [default]
96
116
  else
@@ -119,8 +139,10 @@ module Prick
119
139
  super(database, directory, "build")
120
140
  end
121
141
 
122
- def build(subject = nil)
142
+ def build(subject = nil, execute: true)
123
143
  if subject
144
+ @execute = execute
145
+ @lines = []
124
146
  Dir.chdir(directory) {
125
147
  if File.executable?(subject)
126
148
  do_exe(subject)
@@ -131,8 +153,9 @@ module Prick
131
153
  end
132
154
  }
133
155
  else
134
- super()
156
+ super(execute: execute)
135
157
  end
158
+ self
136
159
  end
137
160
 
138
161
  def self.yml_file(directory) File.join(directory, "build") + ".yml" end
@@ -0,0 +1,34 @@
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
@@ -2,31 +2,16 @@
2
2
  module Prick
3
3
  ### DIRECTORIES AND FILE NAMES
4
4
 
5
- # Path to the .prick-version file
6
- PRICK_VERSION_FILE = ".prick-version"
7
-
8
- # State files
9
- PROJECT_STATE_FILE = ".prick-project"
10
- FEATURES_STATE_FILE = ".prick-features"
11
- MIGRATION_STATE_FILE = ".prick-migration"
12
- MIGRATIONS_FILE = "migrations.sql"
13
-
14
- # Diff file
15
- DIFF_FILE = "diff.sql"
16
-
17
5
  # Shared files (part of the installation)
18
6
  SHARE_PATH = "#{File.dirname(File.dirname(__dir__))}/share"
19
7
  LIBEXEC_PATH = "#{File.dirname(File.dirname(__dir__))}/libexec"
20
8
 
21
- STRIP_COMMENTS_COMMAND = File.join(LIBEXEC_PATH, "strip-comments")
22
-
23
9
  # Project directories
24
10
  DIRS = [
25
- MIGRATIONS_DIR = "migrations",
26
- RELEASES_DIR = "releases",
27
- SCHEMAS_DIR = "schemas",
28
- PRICK_DIR = "#{SCHEMAS_DIR}/prick",
29
- PUBLIC_DIR = "#{SCHEMAS_DIR}/public",
11
+ MIGRATION_DIR = "migration",
12
+ SCHEMA_DIR = "schema",
13
+ PRICK_DIR = "#{SCHEMA_DIR}/prick",
14
+ PUBLIC_DIR = "#{SCHEMA_DIR}/public",
30
15
  VAR_DIR = "var",
31
16
  CACHE_DIR = "#{VAR_DIR}/cache",
32
17
  SPOOL_DIR = "#{VAR_DIR}/spool",
@@ -35,9 +20,42 @@ module Prick
35
20
  SPEC_DIR = "spec"
36
21
  ]
37
22
 
38
- # Path to prick data file
39
- # PRICK_DATA_PATH = File.join(SCHEMAS_DIR, "prick", "data.sql")
40
- SCHEMA_VERSION_PATH = File.join(SCHEMAS_DIR, "prick", "data.sql")
23
+ # The project state file
24
+ PROJECT_STATE_FILE = ".prick-project"
25
+ PROJECT_STATE_PATH = PROJECT_STATE_FILE
26
+
27
+ # The .prick-version file
28
+ PRICK_VERSION_FILE = ".prick-version"
29
+ PRICK_VERSION_PATH = PRICK_VERSION_FILE
30
+
31
+ # The prick.versions data file. This is where the Schema saves its version
32
+ SCHEMA_VERSION_FILE = "data.sql"
33
+ SCHEMA_VERSION_PATH = File.join(PRICK_DIR, SCHEMA_VERSION_FILE)
34
+
35
+ # The the .prick-migration file
36
+ PRICK_MIGRATION_FILE = ".prick-migration"
37
+ PRICK_MIGRATION_PATH = File.join(MIGRATION_DIR, PRICK_MIGRATION_FILE)
38
+
39
+ # The the .prick-feature file
40
+ PRICK_FEATURE_FILE = ".prick-feature"
41
+ PRICK_FEATURE_PATH = File.join(MIGRATION_DIR, PRICK_FEATURE_FILE)
42
+
43
+ # The strip-comments executable
44
+ STRIP_COMMENTS_NAME = "strip-comments"
45
+ STRIP_COMMENTS_PATH = File.join(LIBEXEC_PATH, "strip-comments")
46
+
47
+ # Diff files
48
+ DIFF_FILE = "diff.sql"
49
+ BEFORE_TABLES_DIFF_NAME = "diff.before-tables.sql"
50
+ TABLES_DIFF_NAME = "diff.tables.sql"
51
+ AFTER_TABLES_DIFF_NAME = "diff.after-tables.sql"
52
+
53
+ BEFORE_TABLES_DIFF_PATH = File.join(MIGRATION_DIR, BEFORE_TABLES_DIFF_NAME)
54
+ TABLES_DIFF_PATH = File.join(MIGRATION_DIR, TABLES_DIFF_NAME)
55
+ AFTER_TABLES_DIFF_PATH = File.join(MIGRATION_DIR, AFTER_TABLES_DIFF_NAME)
56
+
57
+ TABLES_DIFF_SHARE_PATH = File.join(SHARE_PATH, "diff", TABLES_DIFF_NAME)
58
+
41
59
 
42
60
  # Dump files
43
61
  DUMP_EXT = "dump.gz"
@@ -46,33 +64,27 @@ module Prick
46
64
 
47
65
  ### REGULAR EXPRESSIONS
48
66
 
67
+ # Matches a system name. System names are used for objects that are external to prick
68
+ # (like usernames)
69
+ NAME_SUB_RE = /[a-z][a-z0-9_-]*/
70
+ NAME_RE = /^#{NAME_SUB_RE}$/
71
+
49
72
  # Matches an identifier. Identifiers consist of lower case letters, digits
50
73
  # and underscores but not dashes because they're used as separators
51
74
  IDENT_SUB_RE = /[a-z][a-z0-9_]*/
52
75
  IDENT_RE = /^#{IDENT_SUB_RE}$/
53
76
 
54
- # Matches an uppercase identifier
55
- # UPCASE_IDENT_SUB_RE = /[A-Z][A-Z0-9_]*/
56
- # UPCASE_IDENT_RE = /#{UPCASE_IDENT_SUB_RE}/
57
-
58
- # A (system) name. Names are used for projects and usernames that are
59
- # external to prick and can include both dashes and underscores but dashes
60
- # have to be followed by a character and not a digit so 'ident-1234' is not
61
- # allowed but 'ident_1234' and 'ident1234' are
62
- NAME_SUB_RE = /#{IDENT_SUB_RE}/
63
- NAME_RE = /^#{NAME_SUB_RE}$/
64
-
65
77
  # Matches a project name
66
- PROJECT_NAME_SUB_RE = NAME_SUB_RE
67
- PROJECT_NAME_RE = NAME_RE
78
+ PROJECT_NAME_SUB_RE = IDENT_SUB_RE
79
+ PROJECT_NAME_RE = IDENT_RE
68
80
 
69
81
  # Matches a custom name
70
- CUSTOM_NAME_SUB_RE = NAME_SUB_RE
71
- CUSTOM_NAME_RE = NAME_RE
82
+ CUSTOM_NAME_SUB_RE = IDENT_SUB_RE
83
+ CUSTOM_NAME_RE = IDENT_RE
72
84
 
73
85
  # Matches a feature name
74
- FEATURE_NAME_SUB_RE = NAME_SUB_RE
75
- FEATURE_NAME_RE = NAME_RE
86
+ FEATURE_NAME_SUB_RE = /(?!initial)#{IDENT_SUB_RE}/
87
+ FEATURE_NAME_RE = /^#{FEATURE_NAME_SUB_RE}$/
76
88
 
77
89
  # Matches a postgres user name
78
90
  USER_NAME_SUB_RE = NAME_SUB_RE
@@ -103,15 +115,48 @@ module Prick
103
115
  SEMVER_SUB_RE = /#{MMP_SEMVER_SUB_RE}(?:-#{PRE_SEMVER_SUB_RE})?/
104
116
  SEMVER_RE = /^#{SEMVER_SUB_RE}$/
105
117
 
106
- # Version RE. The general syntax for a version is '<custom>-<version>_<feature>'
118
+ # Tag RE. The general syntax for a tag is '<custom>-v<version>_<feature>'
119
+ #
120
+ # The RE defines the following captures:
121
+ # $1 - custom name, can be nil
122
+ # $2 - semantic version
123
+ # $3 - feature name, can be nil
124
+ #
125
+ TAG_SUB_RE = /
126
+ (?:(#{CUSTOM_NAME_SUB_RE})-)?
127
+ v
128
+ (#{SEMVER_SUB_RE})
129
+ (?:_(#{FEATURE_NAME_SUB_RE}))?
130
+ /x
131
+ TAG_RE = /^#{TAG_SUB_RE}$/
132
+
133
+ # TODO: Handle initial branches (0.0.0-initial)
134
+
135
+ # Branch RE. The general syntax for a branch is '<custom>-<version>_<feature>'
107
136
  #
108
137
  # The RE defines the following captures:
109
138
  # $1 - custom name, can be nil
110
139
  # $2 - semantic version
111
140
  # $3 - feature name, can be nil
112
141
  #
142
+ BRANCH_SUB_RE = /
143
+ (?:(#{CUSTOM_NAME_SUB_RE})-)?
144
+ (#{SEMVER_SUB_RE})
145
+ (?:_(#{FEATURE_NAME_SUB_RE}))?
146
+ /x
147
+ BRANCH_RE = /^#{BRANCH_SUB_RE}$/
148
+
149
+ # Tag or branch RE. The general syntax for a branch is '<custom>-v?<version>_<feature>'
150
+ #
151
+ # The RE defines the following captures:
152
+ # $1 - custom name, can be nil
153
+ # $2 - tag, nil or 'v'
154
+ # $3 - semantic version
155
+ # $4 - feature name, can be nil
156
+ #
113
157
  VERSION_SUB_RE = /
114
158
  (?:(#{CUSTOM_NAME_SUB_RE})-)?
159
+ (v)?
115
160
  (#{SEMVER_SUB_RE})
116
161
  (?:_(#{FEATURE_NAME_SUB_RE}))?
117
162
  /x
@@ -135,11 +180,11 @@ module Prick
135
180
  # $1 - custom name, can be nil
136
181
  # $2 - semantic version
137
182
  #
138
- RELEASE_SUB_RE = /
139
- (?:(#{CUSTOM_NAME_SUB_RE})-)?
140
- (#{MMP_SEMVER_SUB_RE})
141
- /x
142
- RELEASE_RE = /^#{RELEASE_SUB_RE}$/
183
+ # RELEASE_SUB_RE = /
184
+ # (?:(#{CUSTOM_NAME_SUB_RE})-)?
185
+ # (#{MMP_SEMVER_SUB_RE})
186
+ # /x
187
+ # RELEASE_RE = /^#{RELEASE_SUB_RE}$/
143
188
 
144
189
  # Matches a prerelease branch
145
190
  #
@@ -147,11 +192,11 @@ module Prick
147
192
  # $1 - custom name, can be nil
148
193
  # $2 - semantic version
149
194
  #
150
- PRERELEASE_SUB_RE = /
151
- (?:(#{CUSTOM_NAME_SUB_RE})-)?
152
- (#{MMP_SEMVER_SUB_RE}-#{PRE_SEMVER_SUB_RE})
153
- /x
154
- PRERELEASE_RE = /^#{PRERELEASE_SUB_RE}$/
195
+ # PRERELEASE_SUB_RE = /
196
+ # (?:(#{CUSTOM_NAME_SUB_RE})-)?
197
+ # (#{MMP_SEMVER_SUB_RE}-#{PRE_SEMVER_SUB_RE})
198
+ # /x
199
+ # PRERELEASE_RE = /^#{PRERELEASE_SUB_RE}$/
155
200
 
156
201
  # Matches a feature branch
157
202
  #
@@ -160,8 +205,8 @@ module Prick
160
205
  # $2 - semantic version
161
206
  # $3 - feature name
162
207
  #
163
- FEATURE_SUB_RE = /#{ABSTRACT_RELEASE_SUB_RE}_(#{FEATURE_NAME_SUB_RE})/
164
- FEATURE_RE = /^#{FEATURE_SUB_RE}$/
208
+ # FEATURE_SUB_RE = /#{ABSTRACT_RELEASE_SUB_RE}_(#{FEATURE_NAME_SUB_RE})/
209
+ # FEATURE_RE = /^#{FEATURE_SUB_RE}$/
165
210
 
166
211
  # Migration RE. The syntax is <version>_<version>
167
212
  #
@@ -173,8 +218,8 @@ module Prick
173
218
  # $5 - to custom name, can be nil
174
219
  # $6 - to semantic version
175
220
  #
176
- MIGRATION_SUB_RE = /(#{RELEASE_SUB_RE})_(#{RELEASE_SUB_RE})/
177
- MIGRATION_RE = /^#{MIGRATION_SUB_RE}$/
221
+ # MIGRATION_SUB_RE = /(#{RELEASE_SUB_RE})_(#{RELEASE_SUB_RE})/
222
+ # MIGRATION_RE = /^#{MIGRATION_SUB_RE}$/
178
223
 
179
224
  # Project release RE. The general syntax is '<project>-<custom>-<version>'
180
225
  #
@@ -217,5 +262,12 @@ module Prick
217
262
  ALL_DATABASES_RE = /^#{ALL_DATABASES_SUB_RE}$/
218
263
  def self.all_databases_sub_re(project_name) /(#{project_name})(?:-(#{ABSTRACT_RELEASE_SUB_RE}))?/ end
219
264
  def self.all_databases_re(project_name) /^#{all_databases_sub_re(project_name)}$/ end
265
+
266
+ # Matches temporary databases. Mostly useful when debugging because temporary databases
267
+ # should be deleted on exit
268
+ TMP_DATABASES_SUB_RE = /#{PROJECT_NAME_SUB_RE}-(?:base|next)/
269
+ TMP_DATABASES_RE = /^#{TMP_DATABASES_SUB_RE}$/
270
+ def self.tmp_databases_sub_re(project_name) /#{project_name}-(?:base|next)/ end
271
+ def self.tmp_databases_re(project_name) /^#{tmp_databases_sub_re(project_name)}$/ end
220
272
  end
221
273