prick 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -5
  3. data/Gemfile +4 -1
  4. data/TODO +3 -0
  5. data/doc/prick.txt +114 -0
  6. data/exe/prick +224 -370
  7. data/lib/ext/fileutils.rb +11 -0
  8. data/lib/ext/forward_method.rb +18 -0
  9. data/lib/ext/shortest_path.rb +44 -0
  10. data/lib/prick.rb +17 -9
  11. data/lib/prick/branch.rb +254 -0
  12. data/lib/prick/builder.rb +141 -0
  13. data/lib/prick/command.rb +19 -11
  14. data/lib/prick/constants.rb +42 -20
  15. data/lib/prick/database.rb +5 -3
  16. data/lib/prick/diff.rb +47 -0
  17. data/lib/prick/exceptions.rb +15 -3
  18. data/lib/prick/git.rb +46 -21
  19. data/lib/prick/migration.rb +165 -185
  20. data/lib/prick/program.rb +238 -0
  21. data/lib/prick/project.rb +266 -358
  22. data/lib/prick/rdbms.rb +2 -2
  23. data/lib/prick/schema.rb +19 -88
  24. data/lib/prick/share.rb +64 -0
  25. data/lib/prick/state.rb +137 -0
  26. data/lib/prick/version.rb +34 -14
  27. data/libexec/strip-comments +33 -0
  28. data/make_releases +48 -345
  29. data/make_schema +10 -0
  30. data/prick.gemspec +11 -22
  31. data/share/feature_migration/diff.sql +2 -0
  32. data/share/feature_migration/migrate.sql +2 -0
  33. data/share/release_migration/diff.sql +3 -0
  34. data/share/release_migration/features.yml +6 -0
  35. data/share/release_migration/migrate.sql +5 -0
  36. data/share/release_migration/migrate.yml +5 -0
  37. data/share/schema/build.yml +14 -0
  38. data/share/schema/schema.sql +5 -0
  39. data/share/schemas/build.yml +3 -0
  40. data/share/schemas/prick/build.yml +14 -0
  41. data/share/schemas/prick/data.sql +1 -2
  42. data/share/schemas/prick/schema.sql +0 -15
  43. data/share/schemas/prick/tables.sql +17 -0
  44. data/share/schemas/public/.keep +0 -0
  45. data/share/schemas/public/build.yml +14 -0
  46. data/share/schemas/public/schema.sql +3 -0
  47. data/test_assorted +192 -0
  48. data/test_feature +112 -0
  49. data/test_single_dev +83 -0
  50. metadata +34 -61
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7a41038c7beeb2bb1503ccb199cc45622d6fbe28e113003b98e8e78e10658a37
4
- data.tar.gz: 59cb5055863ce2cd63ad9db5a2adf9a0de33d4386bca210dd8e9f25f602bb5e1
3
+ metadata.gz: cb7c2d20ea8aa16ba957f5139e00b02eec90d92a16316d9a468b97df7f83bc93
4
+ data.tar.gz: 6c2a0acd245344a1bb302aede789bb964757462786aebdc5fec14ea33f43e42f
5
5
  SHA512:
6
- metadata.gz: 0b19d6f150e840101f60aa9337583257a0f72e36e2eb7a84b1403063b274099e7a27716aecd2ccaaaf09484a4f5d4b1f9da6eebde340fe9b69da8bab8342528e
7
- data.tar.gz: 7b71790136d8de6e2f3c77a58fb5d1e432bbbe6f0c910ada86608e05f759c8ea68d255f1cc038ce2b5efebfb7e379f0bb2f607a94cfd99b5f26cf3665f135130
6
+ metadata.gz: 4d350899a5591bc2c6b8d2b6f88948ddf39a6146a535411c1affccf3f5f32dcee4ccb8b30ea0e19060d7bc6a6d1c21064ae10dacf9f19aa3997d04fd2466c892
7
+ data.tar.gz: fad2bbb8a50f18c779160bc17308072a94fd4ca98b1db76c3c16724eafe1c4128c4df4b0485051a136a19cf0315daff9b19dd4035dfe54cdbf624376c7c3c4c4
data/.gitignore CHANGED
@@ -19,10 +19,8 @@
19
19
 
20
20
  # Put your personal ignore files in /home/clr/.config/git/ignore
21
21
 
22
- # Temporary ignores
23
- /releases/
24
- /migrations/
25
- /prick.sh
26
-
27
22
  # Ignore bundle binstubs
28
23
  /bin/prick
24
+
25
+ # Ignore development testing dir
26
+ /dir
data/Gemfile CHANGED
@@ -1,6 +1,9 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
3
+ git_source(:github) {|repo_name| "https://github.com/clrgit/#{repo_name}" }
4
4
 
5
5
  # Specify your gem's dependencies in prick.gemspec
6
6
  gemspec
7
+
8
+ gem "rake", "~> 12.0"
9
+ gem "rspec", "~> 3.0"
data/TODO ADDED
@@ -0,0 +1,3 @@
1
+
2
+ o Make it possible to execute prick in any subdirecty instead of only in the root
3
+
@@ -0,0 +1,114 @@
1
+
2
+
3
+ MIGRATION STATE FILES
4
+ .prick-migration (State file)
5
+ version: Version
6
+ The target version. The result of running the migration on the base
7
+ release
8
+ base_version: Version
9
+ Base version. Running the migration on a base release yields a release
10
+ of with the same version as the `version` property
11
+
12
+ The 0.0.0 version has base_version equal to nil. A Feature has version
13
+ equal to its base version.
14
+
15
+ Note that while a release's .prick-migration file lives in the release
16
+ directory, it's .prick-features file and the migrations lives in the
17
+ directory of the base release. This separation supports the
18
+ single-developer workflow where the next release is not known beforehand
19
+
20
+ .prick-features (State file)
21
+ features: Array
22
+ A list of features versions
23
+
24
+ MIGRATION FILES
25
+ migrate.sql
26
+ features.sql
27
+ diff.sql
28
+
29
+
30
+ MIGRATION FILE STRUCTURE
31
+ releases/
32
+ 0.0.0/
33
+ .prick-migration -> version: 0.0.0, base_version: nil
34
+ .prick-features -> [feature_a]
35
+ feature_a/
36
+ .prick-migration -> version: nil, base_version: 0.0.0
37
+ .prick-features -> []
38
+ feature_b/ (rebased)
39
+ .prick-migration -> version: 0.2.0, base_version: 0.2.0-pre.1
40
+ .prick-features -> []
41
+
42
+ 0.1.0/
43
+ .prick-migration -> version: 0.1.0, base_version: 0.0.0
44
+ feature_b/ symlinks to ../0.0.0/feature_b/
45
+
46
+ 0.1.0/ (wip - single developer work flow)
47
+ .prick-migration -> version: 0.1.0, base_version: 0.0.0
48
+ .prick-features -> [feature_c]
49
+ feature_c/
50
+ ...
51
+
52
+ 0.2.0/ (doing a pre-release)
53
+ .prick-migration -> version: 0.2.0-pre.1, base_version: 0.1.0
54
+
55
+ migrations/
56
+ 0.0.0_0.1.0/
57
+ .prick-migration -> version: 0.1.0, base_version: 0.0.0
58
+ .prick-features -> []
59
+
60
+
61
+ NOTES
62
+ #
63
+ # Distinguish between running a migration 0.1.0 -> 0.2.0 and running the
64
+ # migration in the 0.2.0 directory in the single-developer workflow
65
+ #
66
+ # prick migrate
67
+ # On a tag: Migrate to that tag
68
+ # On a branch: Run migrations in the release directory
69
+ #
70
+ # prick migrate 0.2.0 <- the version number reflects where to find the migration
71
+ # Runs the migration files in the release directory
72
+ #
73
+ # prick migrate 0.1.0
74
+ # Runs the migration files in the base release directory
75
+ #
76
+ #
77
+ # prick build
78
+ # Builds the current schema into the project database
79
+ #
80
+ # prick build 0.1.0
81
+ # Builds the given schema into a versioned database
82
+
83
+
84
+
85
+
86
+
87
+
88
+
89
+
90
+
91
+
92
+
93
+
94
+
95
+ ######################
96
+
97
+ PRICK FILES
98
+ ./prick-version
99
+ Contains just one line with the version of the prick command that should be
100
+ used with this project (eg. 'prick-0.1.0'). Prick checks this file at
101
+ startup and fails if the required version doesn't match the current command
102
+
103
+ ./prick
104
+ project_name
105
+ Name of the project
106
+
107
+ ./releases/*/.prick
108
+ base_version
109
+ The base version of this release. nil for release 0.0.0
110
+ features
111
+ List of features in a release based on this release. Initially empty
112
+ but filled in when the directory is prepared for a subsequent release.
113
+ To find the set of features in the current release, inspect the prick
114
+ file of the base_version in this branch
data/exe/prick CHANGED
@@ -1,15 +1,18 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'prick.rb'
4
+ require 'prick/program.rb'
4
5
 
5
6
  require 'shellopts'
6
7
  require 'indented_io'
8
+
7
9
  require 'tempfile'
8
- require 'ext/algorithm.rb'
9
10
 
10
11
  include ShellOpts
12
+ include Prick
13
+
14
+ PROGRAM = File.basename($0)
11
15
 
12
- # TODO: Backup & restore
13
16
  SPEC = %(
14
17
  n,name=NAME
15
18
  C,directory=DIR
@@ -18,37 +21,30 @@ SPEC = %(
18
21
  q,quiet
19
22
  version
20
23
 
21
- init!
22
- info!
23
- status!
24
- history!
25
-
26
- checkout!
24
+ init! u,user=USER
27
25
 
28
- feature!
29
- rebase!
26
+ info!
27
+ list! list.releases! m,migrations c,cancelled list.migrations! list.upgrades! a,all
30
28
 
31
- create! create.release! create.prerelease! create.feature! create.migration!
32
- increment! increment.prerelease!
29
+ build! d,database=DATABASE C,nocache
30
+ make!
31
+ load! d,database=DATABASE
32
+ save! d,database=DATABASE
33
+ migrate!
33
34
 
34
- prepare! prepare.release! prepare.prerelease! prepare.feature! prepare.migration!
35
- include!
36
- commit!
37
- prerelease!
38
- release!
35
+ prepare! prepare.release! prepare.migration! prepare.schema! prepare.diff!
36
+ include! include.feature!
37
+ check!
39
38
 
40
- list! list.databases! list.releases! list.prereleases!
41
- build!
42
- use! f,file=FILE
43
- load! f,file=FILE
44
- reload! f,file=FILE
45
- unload!
46
- clean!
39
+ create! create.release! create.prerelease! create.feature!
40
+ cancel! cancel.release!
47
41
 
48
- migrate!
42
+ upgrade!
43
+ backup!
44
+ restore!
49
45
  )
50
46
 
51
- USAGE = "-h -v -n NAME -C DIR COMMAND"
47
+ USAGE = "Usage: #{PROGRAM} -h -v -n NAME -C DIR COMMAND" # FIXME: Why doesn't shellopts include PROGRAM?
52
48
 
53
49
  HELP = %(
54
50
  NAME
@@ -75,387 +71,246 @@ HELP = %(
75
71
  Print prick version
76
72
 
77
73
  COMMANDS
78
- INFO COMMANDS
79
- init [DIR]
80
- Initialize a project directory
74
+ INITIALIZATION
75
+ init [DIR] --user=USER
76
+ Initialize a project in the given directory. DIR defaults to the
77
+ current directory. The USER is the postgres user, it defaults to
78
+ the project name
81
79
 
80
+ INFO COMMANDS
82
81
  info
83
- Print project information
84
82
 
85
- status
86
- Short status
87
-
88
- GENERAL COMMANDS
89
- checkout
90
- As git checkout but does some extra work behind the scenes
83
+ list releases --migrations --cancelled
84
+ list migrations
85
+ list upgrades --all
86
+ List releases/migrations/upgrades
87
+
88
+ 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
97
+
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
91
109
 
92
110
  migrate
93
- Migrate from the current branch in the database to the current branch
94
-
95
-
96
- DEVELOPER COMMANDS
97
- create feature FEATURE
98
- Create a new feature branch and a feature directory under
99
- features/<base-version>. Note that the base version is the base version
100
- of the pre-release
101
-
102
- Features are named <feature>-<base-version>
103
-
104
- prepare migration
105
- Create migration files from the base release to the current schema. It
106
- does not overwrite existing migration files
111
+ Not yet implemented
107
112
 
108
- rebase VERSION
109
- Rebase the feature to HEAD of the release. The rebased feature lives on
110
- a branch of its own and have a symlink from the new base release to the
111
- feature implementation in the original release. Rebased features are
112
- named <feature>-<rebase-version>
113
+ PREPARING RELEASES
114
+ prepare release
115
+ Populate the current migration directory with migration files
113
116
 
117
+ prepare feature NAME
118
+ Create and populate a feature as a subdirectory of the current
119
+ directory. Also prepares the current release directory
114
120
 
115
- RELEASE MANAGER COMMANDS
116
- migrate VERSION|patch|minor|major
117
- Prepare migration from current release to the given version. The branch
118
- will be named <old-version>_<new-version>. Note that the generated
119
- files don't include data migrations so it may be easier to first create a
120
- prerelease and include missing features and then use that release as base
121
- for an empty migration release that just changes the version number
121
+ prepare migration FROM
122
+ Create and populate a migration directory
122
123
 
123
- (need some thought)
124
+ prepare schema NAME
125
+ Create and populate a new schema directory. Existing files and
126
+ directories are kept
124
127
 
125
- prepare VERSION|patch|minor|major
126
- Prepare a new release by branching to <version>.pre.0 and creating a
127
- features directory for the _base_ version. If version is one of the
128
- names patch, minor, or major then the version is constructed by
129
- incrementing the given part of the base release's version
128
+ prepare diff [VERSION]
130
129
 
131
- include FEATURE
132
- Merge a feature branch into the prepared release
130
+ include feature FEATURE
131
+ Include the given feature in the current pre-release
133
132
 
134
- prerelease
135
- Bumps the pre-release serial and create a new branch
133
+ check
134
+ Check that the current migration applied to the base version yields the
135
+ same result as loading the current schema
136
136
 
137
- release [VERSION]
138
- Create a new release. The version is not used if the release was prepared
137
+ CREATING RELEASES
138
+ create release [RELEASE]
139
+ Prepare a release and create release directory and migration file
140
+ before tagging and branching to a release branch. The RELEASE argument
141
+ can be left out if the current branch is a prerelease branch
139
142
 
140
-
141
- MANIPULATING DATABASES AND RELEASES
142
- list [databases|releases|prereleases]
143
- Output a list of databases, releases, or prereleases. List databases by
144
- default
145
-
146
- build [VERSION]
147
- Build the schema in the project database. If a version is given, the
148
- version is built into the versioned database and the release cached
149
- on disk
150
-
151
- load
152
- Load the current cache into the project database
153
-
154
- load -f FILE [VERSION]
155
- Load the cached release into its versioned database. It is an error if
156
- the release isn't cached - use build to create it
143
+ create prerelease RELEASE
144
+ Prepare a release and create release directory and migration file
145
+ before branching to a prerelease branch
157
146
 
158
- reload [VERSION]
159
- Clear the versioned database and reload the release from the cache
147
+ create feature NAME
148
+ Prepare a feature before branching to a feature branch
160
149
 
161
- unload [VERSION]
162
- Delete the versioned database. Default is to delete all project related
163
- databases
150
+ cancel release RELEASE
151
+ Cancel a release. Since tags are immutable, the release is cancelled by
152
+ added a special cancel-tag to the release that makes prick ignore it
164
153
 
165
- clean [VERSION]
166
- Delete the cached release. Default is to delete all cached releases
154
+ DEPLOYING RELEASES
155
+ upgrade
156
+ Migrate the database to match the current schema
167
157
 
158
+ backup [FILE]
159
+ Saves a backup of the database to the given file or to the var/spool
160
+ directory
168
161
 
162
+ restore [FILE]
163
+ Restore the database from the given backup file or from the latest
164
+ backup in the var/spool directory
169
165
  )
170
166
 
171
- INFO_PARAMS = {
172
- "Releases": :releases,
173
- "Pre-releases": :prereleases,
174
- "Features": :features,
175
- "Ignored releases": :ignored_release_nodes,
176
- "Ignored features": :ignored_feature_nodes,
177
- "Orphan disk features": :orphan_feature_nodes,
178
- "Orphan disk releases": :orphan_release_nodes,
179
- "Orphan git branches": :orphan_git_branches
180
- }
181
-
182
- def info(project)
183
- for header, member in INFO_PARAMS
184
- elements = project.send(member)
185
- puts header
186
- if elements.empty?
187
- puts " [none]"
188
- else
189
- if member == :features
190
- project.features.each { |release, features|
191
- puts " #{release}"
192
- features.each { |feature| puts " #{feature.feature}" }
193
- }
194
- else
195
- elements.sort.each { |element| puts " #{element}" }
196
- end
197
- end
198
- end
199
- end
200
-
201
- def compute_version(project, arg)
202
- if arg.nil?
203
- nil
204
- elsif %w(major minor patch).include?(arg)
205
- project.release.version.increment(arg.to_sym)
206
- else
207
- Prick::Version.new(arg)
208
- end
209
- end
210
167
 
211
168
  opts, args = ShellOpts.as_struct(SPEC, ARGV)
212
169
 
213
170
  # Handle --help
214
- if opts.help?
215
- begin
216
- file = Tempfile.new("prick")
217
- file.puts HELP.split("\n").map { |l| l.sub(/^ /, "") }
218
- file.flush
219
- system "less #{file.path}"
220
- ensure
221
- file.close
222
- end
223
- exit
224
- end
171
+ if opts.help?
172
+ begin
173
+ file = Tempfile.new("prick")
174
+ file.puts HELP.split("\n").map { |l| l.sub(/^ /, "") }
175
+ file.flush
176
+ system "less #{file.path}"
177
+ ensure
178
+ file.close
179
+ end
180
+ exit
181
+ end
225
182
 
226
183
  # Handle --version
227
- if opts.version?
228
- puts "prick-#{Prick::VERSION}"
229
- exit
184
+ if opts.version?
185
+ puts "prick-#{VERSION}"
186
+ exit
230
187
  end
231
188
 
232
189
  begin
233
190
  # Honor -C option
234
191
  if opts.directory
235
- begin
236
- Dir.chdir(opts.directory)
237
- rescue Errno::ENOENT
238
- raise Prick::Error, "Can't cd to '#{directory}'"
192
+ if File.exist?(opts.directory)
193
+ begin
194
+ Dir.chdir(opts.directory)
195
+ rescue Errno::ENOENT
196
+ raise Prick::Error, "Can't cd to '#{opts.directory}'"
197
+ end
198
+ else
199
+ raise Prick::Error, "Can't find directory: #{opts.directory}"
239
200
  end
240
201
  end
241
202
 
242
- name = opts.name || ENV["PRICK_PROJECT"] || File.basename(Dir.getwd)
243
- verbose = opts.verbose?
203
+ # Create program object
204
+ program = Program.new(quiet: opts.quiet?, verbose: opts.verbose?)
244
205
 
245
- # :init! is processed separately because the project object can't be
246
- # constructed before the directory has been initialized
206
+ # Handle init command
247
207
  if opts.subcommand == :init
248
- dir = args.expect(1)
249
- Prick::Project.initialize_directory(dir)
250
- Dir.chdir(dir) {
251
- Prick::Project.initialize_project(name)
252
- }
253
- if File.basename(dir) != name
254
- puts "Initialized project #{name} in #{dir}" if !opts.quiet?
255
- else
256
- puts "Initialized project #{name}" if !opts.quiet?
257
- end
208
+ directory = args.expect(0..1)
209
+ name = opts.name || directory || File.basename(Dir.getwd)
210
+ user = opts.init.user || name
211
+ program.initialize_directory(name, user, directory || ".")
212
+ exit 0
213
+ end
214
+
215
+ # Check prick version
216
+ file = PrickVersion.new
217
+ file.exist? or raise Prick::Error, "Can't find prick version file '#{file.path}'"
218
+ VERSION == file.read.to_s or
219
+ raise Prick::Fail, ".prick-version required prick-#{file.read} but you're using prick-#{VERSION}"
220
+
221
+ # Expect a sub-command
222
+ opts.subcommand? or raise Prick::Error, "Subcomand expected"
223
+
224
+ case opts.subcommand
225
+ when :info
226
+ args.expect(0)
227
+ program.info
228
+
229
+ when :build
230
+ version = args.expect(0..1)
231
+ program.build(opts.build.database, version, opts.build.nocache)
232
+
233
+ when :save
234
+ file_or_version = args.expect(0..1)
235
+ program.save(opts.save.database, file_or_version)
236
+
237
+ when :load
238
+ file_or_version = args.expect(1)
239
+ program.load(opts.load.database, file_or_version)
240
+
241
+ when :make
242
+ raise NotYet
243
+
244
+ when :migrate
245
+ raise NotYet
246
+
247
+ when :list
248
+ command = opts.list
249
+ case command.subcommand
250
+ when :releases;
251
+ obj = command.releases
252
+ program.list_releases(migrations: obj.migrations?, cancelled: obj.cancelled?)
253
+ when :migrations; program.list_migrations
254
+ when :upgrades; program.list_upgrades(*args.expect(0..2).compact)
255
+ when NilClass; raise Prick::Error, "list requires a releases|migrations|upgrades sub-command"
256
+ else
257
+ raise Prick::Internal, "Subcommand #{opts.subcommand}.#{command.subcommand} is not matched"
258
+ end
259
+
260
+ when :prepare
261
+ cmd = opts.prepare.subcommand || :release
262
+ case cmd
263
+ when :release; args.expect(0); program.prepare_release
264
+ when :feature; raise NotYet
265
+ when :migration; program.prepare_migration(args.expect(1))
266
+ when :schema; program.prepare_schema(args.expect(1))
267
+ when :diff; program.prepare_diff(args.expect(0..1))
268
+ else
269
+ raise Prick::Internal, "Subcommand #{opts.subcommand}.#{cmd} is not matched"
270
+ end
271
+
272
+ when :include
273
+ cmd = opts.include.subcommand || :feature
274
+ case cmd
275
+ when :feature; program.include_feature(args.expect(1))
276
+ else
277
+ raise Prick::Internal, "Subcommand #{opts.subcommand}.#{cmd} is not matched"
278
+ end
279
+
280
+ when :check
281
+ args.expect(0)
282
+ program.check
283
+
284
+ when :create
285
+ cmd = opts.create.subcommand || :release
286
+ case cmd
287
+ when :release; program.create_release(args.expect(0..1))
288
+ when :prerelease; program.create_prerelease(args.expect(0..1))
289
+ when :feature; program.create_feature(args.expect(1))
290
+ else
291
+ raise Prick::Internal, "Subcommand #{opts.subcommand}.#{cmd} is not matched"
292
+ end
293
+
294
+ when :cancel
295
+ cmd = opts.cancel.subcommand
296
+ case cmd
297
+ when :release; program.cancel_release(args.expect(1))
298
+ when nil; raise Prick::Error, "'cancel' subcommand require a release argument"
299
+ else
300
+ raise Prick::Internal, "Subcommand #{opts.subcommand}.#{cmd} is not matched"
301
+ end
302
+
303
+ when :upgrade
304
+ args.expect(0)
305
+ program.upgrade
306
+
307
+ when :backup
308
+ program.backup(args.expect(0..1))
309
+
310
+ when :restore
311
+ program.restore(args.expect(0..1))
258
312
  else
259
- project = Prick::Project.new(name)
260
-
261
- case cmd = opts.subcommand
262
-
263
- # INFO COMMANDS #########################################################
264
- #
265
- when :info
266
- args.expect(0)
267
-
268
- puts "Current branch"
269
- puts " #{project.release&.version || 'nil'}"
270
-
271
- puts "Project database"
272
- db = project.database
273
- if db.exist?
274
- print " #{project.database.name}"
275
- print " (present)" if project.database.exist? && !project.database.loaded?
276
- print " (using #{project.database.version})" if project.database.loaded?
277
- else
278
- print " [missing]" if !project.database.exist?
279
- end
280
- puts
281
-
282
- puts "Releases"
283
- project.releases.each { |release|
284
- print " #{release}"
285
- if release.database.exist?
286
- if release.database.version
287
- print " loaded"
288
- else
289
- print " (empty database)"
290
- end
291
- end
292
- if release.cached?
293
- print ", cached"
294
- end
295
- print " <#{release.database.name}>"
296
- print "\n"
297
- }
298
- puts
299
- info(project)
300
-
301
- when :status
302
- args.expect(0)
303
- puts "On branch #{project.release}" + (project.dirty? ? " (dirty)" : "")
304
-
305
- when :history
306
- args.expect(0)
307
- history = project.release.history
308
- history.each { |release, features|
309
- puts release.to_s
310
- indent {
311
- features.map { |feature|
312
- puts "#{feature}, base release: #{feature.base_release}"
313
- }
314
- }
315
- }
316
-
317
-
318
- # GENERAL COMMANDS ######################################################
319
- #
320
- when :checkout
321
- version = args.expect(1)
322
- project.checkout(version)
323
- puts "Checked out #{version}"
324
-
325
- when :migrate
326
- project.migrate
327
-
328
-
329
- # DEVELOPER COMMANDS ####################################################
330
- #
331
- when :feature # Shorthand for 'create feature'
332
-
333
- when :rebase
334
-
335
- when :prepare
336
- args.expect(0)
337
- if object = opts.prepare.subcommand!
338
- case object
339
- when :migration
340
- project.prepare_migration
341
- puts "Prepared migration"
342
- else
343
- raise "Oops: subcommand #{opts.subcommand.inspect} not matched"
344
- end
345
- else
346
- args.expect(0)
347
- project.prepare_release
348
- puts "Prepared new release" if !opts.quiet?
349
- end
350
-
351
-
352
- # RELEASE MANAGER COMMANDS ##############################################
353
- #
354
- when :create
355
- object = opts.create.subcommand!
356
- release =
357
- case object
358
- when :release
359
- version = compute_version(project, args.expect(0..1))
360
- project.create_release(version)
361
- when :prerelease
362
- version = compute_version(project, args.expect(1))
363
- project.create_prerelease(version)
364
- when :feature
365
- project.create_feature(args.expect(1))
366
- else
367
- raise "Oops: subcommand #{opts.subcommand.inspect} not matched"
368
- end
369
- puts "Created #{object} #{release.version}" if !opts.quiet?
370
-
371
- when :increment # and 'increment prerelease'
372
- args.expect(0)
373
- release = project.increment_prerelease
374
- puts "Created prerelease #{release.version}" if !opts.quiet?
375
-
376
- when :release # Shorthand for 'create release'
377
- version = compute_version(project, args.expect(0..1))
378
- release = project.create_release(version)
379
- puts "Created release #{release.version}" if !opts.quiet?
380
-
381
- when :prerelease # Shorthand for 'create prerelease' and 'increment'
382
- release =
383
- if project.release?
384
- version = compute_version(project, args.expect(1))
385
- project.create_prerelease(version)
386
- elsif project.prerelease?
387
- args.expect(0)
388
- project.increment_prerelease
389
- end
390
- puts "Created prerelease #{release.version}" if !opts.quiet?
391
-
392
- when :include
393
- name = args.expect(1)
394
- project.include_feature(name)
395
- puts "Included feature #{name}" if !opts.quiet?
396
- puts "Please check changed files and then commit using 'prick commit'"
397
-
398
- when :commit
399
- msg = project.commit_feature
400
- puts msg if !opts.quiet?
401
- puts "Committed changes" if !opts.quiet?
402
-
403
-
404
- # MANIPULATING DATABASES AND RELEASES ###################################
405
- #
406
- when :list
407
- # TODO: Mark cached releases as such
408
- args.expect(0)
409
- case opts.list.subcommand
410
- when :databases, nil; project.databases.map(&:name)
411
- when :releases; project.releases.map(&:name)
412
- when :prereleases; project.prereleases.map(&:version)
413
- else
414
- ShellOpts.error "Illegal list type: '#{opts.list.subcommand}"
415
- end.each { |e| puts e }
416
-
417
- when :build
418
- version = args.expect(0..1)
419
- project.build(version)
420
- if version
421
- puts "Built #{version}"
422
- else
423
- puts "Built current version"
424
- end
425
-
426
- when :use
427
- file = opts.use.file
428
- version = args.expect(0..1)
429
- file || version or raise Error, "Need either a version or a -f FILE argument"
430
- file.nil? != version.nil? or raise Error, "Not both version and -f FILE arguments can be specified"
431
- file ||= project[version].archive.path
432
- project.load_database(nil, file)
433
-
434
- when :load
435
- file = opts.load.file
436
- version = args.expect(1)
437
- project.load_database(version, file)
438
-
439
- when :reload
440
- file = opts.reload.file
441
- version = args.expect(1)
442
- project.reload(version, file)
443
-
444
- when :unload
445
- version = args.expect(0..1)
446
- project.unload(version)
447
-
448
- when :clean
449
- version = args.expect(0..1)
450
- project.clean(version, project: true)
451
-
452
- when NilClass
453
- if args.size > 0
454
- ShellOpts.error "#{args.first} is not a command"
455
- end
456
- else
457
- raise "Oops: subcommand #{opts.subcommand.inspect} not matched"
458
- end
313
+ raise Prick::Internal, "Subcommand #{opts.subcommand} is not matched"
459
314
  end
460
315
 
461
316
  rescue Prick::Fail => ex # Handling of Fail has to come first because Fail < Error
@@ -464,4 +319,3 @@ rescue Prick::Error => ex
464
319
  ShellOpts.error(ex.message)
465
320
  end
466
321
 
467
-