ggem 1.7.0 → 1.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9bb7a69fa7315e7512e780ebe935557f2e4b2664
4
+ data.tar.gz: 8aadfede4196531dc4af409a5856805818065ba3
5
+ SHA512:
6
+ metadata.gz: 7f6fe5a9353e8dcc1fb53ab4f3d6115c0d0d53d64f5bd79e4fe47fc85368ba1256916a91d6877ff2f16e62aaa1d4b14038ab98169f4662c3995bcec8ef05421b
7
+ data.tar.gz: f9dd50efd68643021c9a6ea8780c9f3547c5355905917f54ac66c472bec450627fdb559c3ecc5ad75ad6d1d04604d5913eb5a12ae0a074f2ab6de2a3f1b8a7d6
data/README.md CHANGED
@@ -1,25 +1,169 @@
1
1
  # GGem
2
2
 
3
- Consistantly generate a ruby gem project ready to test, build, and deploy. Uses and emulates most of Bundler's gem building features.
3
+ A gem utility CLI.
4
+
5
+ ```
6
+ $ cd /my/projects
7
+ $ ggem -h
8
+ Usage: ggem [COMMAND] [options]
9
+
10
+ Options:
11
+ --version
12
+ --help
13
+
14
+ Commands:
15
+ generate (g) # Create a gem given a GEM-NAME
16
+ $ ggem generate mygem
17
+ created gem in /my/projects/mygem
18
+ initialized gem git repo
19
+ $ cd mygem/
20
+ $ ggem -h
21
+ Usage: ggem [COMMAND] [options]
22
+
23
+ Options:
24
+ --version
25
+ --help
26
+
27
+ Commands:
28
+ generate (g) # Create a gem given a GEM-NAME
29
+ build (b) # Build mygem-0.0.1.gem into the pkg directory
30
+ install (i) # Build and install mygem-0.0.1.gem into system gems
31
+ push (p) # Push built mygem-0.0.1.gem to https://rubygems.org
32
+ tag (t) # Tag v0.0.1 and push git commits/tags
33
+ release (r) # Tag v0.0.1 and push built mygem-0.0.1.gem to https://rubygems.org
34
+ ```
4
35
 
5
36
  ## Usage
6
37
 
38
+ ### Generate
39
+
7
40
  ```
8
- $ ggem --help
9
- $ ggem my-gem
41
+ $ ggem generate -h
42
+ Usage: ggem generate [options] GEM-NAME
43
+
44
+ Options:
45
+ --version
46
+ --help
47
+
48
+ Description:
49
+ Create a gem given a GEM-NAME
50
+ $ ggem generate mygem
10
51
  $ git commit -m "Gem created with ggem"
11
52
  ```
12
53
 
13
- GGem creates a folder and files for developing, testing, and releasing a gem. It is safe to run on existing gem folders, adding/overwriting where necessary.
14
-
15
- ## Features
54
+ The `generate` command creates a folder and files for developing, testing, and releasing a gem. It is safe to run on existing gem folders, adding/overwriting where necessary.
16
55
 
17
56
  * creates `lib` and gem files similar to `bundle gem` (as of Bundler 1.2.4)
18
57
  * creates `test` files
19
- * source control using Git
20
- * test using Assert
21
- * release using Bundler
22
58
  * adds `TODO` entries in files where user input is needed
59
+ * source control using [Git](https://git-scm.com/)
60
+ * test using [Assert](https://github.com/redding/assert)
61
+
62
+ You can also call this command using the `g` alias: `ggem g -h`.
63
+
64
+ ### Build
65
+
66
+ ```
67
+ $ ggem build -h
68
+ Usage: ggem build [options]
69
+
70
+ Options:
71
+ --version
72
+ --help
73
+
74
+ Description:
75
+ Build mygem-0.0.1.gem into the pkg directory
76
+ ```
77
+
78
+ The `build` command creates a .gem file and copies it into the `pkg/` directory. You can also call this command using the `b` alias: `ggem b -h`.
79
+
80
+ ### Install
81
+
82
+ ```
83
+ $ ggem install -h
84
+ Usage: ggem install [options]
85
+
86
+ Options:
87
+ --version
88
+ --help
89
+
90
+ Description:
91
+ Build and install mygem-0.0.1.gem into system gems
92
+ ```
93
+
94
+ The `install` command first builds a .gem file and then installs it. The command is the equivalent of running `ggem build && gem install pkg/mygem-0.0.1.gem`. You can also call this command using the `i` alias: `ggem i -h`.
95
+
96
+ ### Push
97
+
98
+ ```
99
+ Usage: ggem push [options]
100
+
101
+ Options:
102
+ --version
103
+ --help
104
+
105
+ Description:
106
+ Push built mygem-0.0.1.gem to https://rubygems.org
107
+ ```
108
+
109
+ The `push` command first builds a .gem file and then pushes it to a gem host. The command is the equivalent of running `ggem build && gem push pkg/mygem-0.0.1.gem --source https://rubygems.org`. You can also call this command using the `p` alias: `ggem p -h`.
110
+
111
+ #### Using a custom gem host
112
+
113
+ To override the default `https://rubygems.org` push host, add a metadata entry to the .gemspec file:
114
+
115
+ ```ruby
116
+ # ...
117
+ gem.metadata['allowed_push_host'] = "https://gems.example.com"
118
+ # ...
119
+ ```
120
+
121
+ Now GGem will now use the allowed push host when pushing/releasing the gem.
122
+
123
+ ```
124
+ $ ggem push -h
125
+ Usage: ggem push [options]
126
+
127
+ Options:
128
+ --version
129
+ --help
130
+
131
+ Description:
132
+ Push built mygem-0.0.1.gem to https://gems.example.com
133
+ ```
134
+
135
+ ### Tag
136
+
137
+ ```
138
+ $ ggem tag -h
139
+ Usage: ggem tag [options]
140
+
141
+ Options:
142
+ --version
143
+ --help
144
+
145
+ Description:
146
+ Tag v0.0.1 and push git commits/tags
147
+ ```
148
+
149
+ The `tag` command will tag the current git commit with the `version` data from the .gemspec file. It then pushes any commits and tags. The command is the equivalent of running `git tag -a -m "Version {version}" v{version} && git push && git push --tags`. You can also call this command using the `t` alias: `ggem t -h`.
150
+
151
+ ### Release
152
+
153
+ ```
154
+ $ ggem release -h
155
+ Usage: ggem release [options]
156
+
157
+ Options:
158
+ --version
159
+ --help
160
+
161
+ Description:
162
+ Tag v0.0.1 and push built mygem-0.0.1.gem to https://rubygems.org
163
+ (macro for running `ggem tag && ggem push`)
164
+ ```
165
+
166
+ As the help message says, this command is just a macro for running `ggem tag && ggem push`. You can also call this command using the `r` alias: `ggem r -h`.
23
167
 
24
168
  ## Installation
25
169
 
data/bin/ggem CHANGED
@@ -4,4 +4,4 @@
4
4
  #
5
5
 
6
6
  require 'ggem/cli'
7
- GGem::CLI.run *ARGV
7
+ GGem::CLI.run ARGV
@@ -8,8 +8,8 @@ Gem::Specification.new do |gem|
8
8
  gem.version = GGem::VERSION
9
9
  gem.authors = ["Kelly Redding", "Collin Redding"]
10
10
  gem.email = ["kelly@kellyredding.com", "collin.redding@me.com"]
11
- gem.description = %q{"Juh Gem", baby! (a generator of gems this is)}
12
- gem.summary = %q{"Juh Gem", baby! (a generator of gems this is)}
11
+ gem.description = %q{"Juh Gem", baby! (a gem utility CLI)}
12
+ gem.summary = %q{"Juh Gem", baby! (a gem utility CLI)}
13
13
  gem.homepage = "http://github.com/redding/ggem"
14
14
  gem.license = 'MIT'
15
15
 
@@ -18,6 +18,9 @@ Gem::Specification.new do |gem|
18
18
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
19
  gem.require_paths = ["lib"]
20
20
 
21
- gem.add_development_dependency("assert", ["~> 2.15"])
21
+ gem.add_development_dependency("assert", ["~> 2.15.0"])
22
+
23
+ gem.add_dependency("much-plugin", ["~> 0.1.0"])
24
+ gem.add_dependency("scmd", ["~> 3.0.1"])
22
25
 
23
26
  end
@@ -1,106 +1,63 @@
1
- require 'ggem'
2
1
  require 'ggem/version'
2
+ require 'ggem/cli/clirb'
3
+ require 'ggem/cli/commands'
3
4
 
4
5
  module GGem
5
6
 
6
7
  class CLI
7
8
 
8
- def self.run(*args)
9
- self.new.run(*args)
9
+ COMMANDS = CommandSet.new{ |unknown| InvalidCommand.new(unknown) }.tap do |c|
10
+ c.add(GenerateCommand, 'generate', 'g')
11
+ c.add(BuildCommand, 'build', 'b')
12
+ c.add(InstallCommand, 'install', 'i')
13
+ c.add(PushCommand, 'push', 'p')
14
+ c.add(TagCommand, 'tag', 't')
15
+ c.add(ReleaseCommand, 'release', 'r')
10
16
  end
11
17
 
12
- def initialize
13
- @cli = CLIRB.new do
14
- option 'debug', 'run in debug mode'
15
- end
18
+ def self.run(args)
19
+ self.new.run(args)
16
20
  end
17
21
 
18
- def run(*args)
19
- begin
20
- # parse manually in the case that parsing fails before the debug arg
21
- debug_mode ||= args.include?('-d') || args.include?('--debug')
22
- @cli.parse!(args)
23
- raise CLIRB::Error, "please provide a gem name" if @cli.args.size < 1
22
+ def initialize(kernel = nil, stdout = nil, stderr = nil)
23
+ @kernel = kernel || Kernel
24
+ @stdout = stdout || $stdout
25
+ @stderr = stderr || $stderr
26
+ end
24
27
 
25
- path = GGem::Gem.new(Dir.pwd, *args).save!.path
26
- puts "created gem and initialized git repo in #{path}"
28
+ def run(args)
29
+ begin
30
+ cmd_name = args.shift
31
+ cmd = COMMANDS[cmd_name]
32
+ cmd.run(args)
27
33
  rescue CLIRB::HelpExit
28
- puts help
34
+ @stdout.puts cmd.help
29
35
  rescue CLIRB::VersionExit
30
- puts GGem::VERSION
31
- rescue CLIRB::Error => exception
32
- puts "#{exception.message}\n\n"
33
- puts debug_mode ? exception.backtrace.join("\n") : help
34
- exit(1)
35
- rescue Exception => exception
36
- puts "#{exception.class}: #{exception.message}"
37
- puts exception.backtrace.join("\n") if debug_mode
38
- exit(1)
36
+ @stdout.puts GGem::VERSION
37
+ rescue CLIRB::Error, ArgumentError, InvalidCommandError => exception
38
+ display_debug(exception)
39
+ @stderr.puts "#{exception.message}\n\n"
40
+ @stdout.puts cmd.help
41
+ @kernel.exit 1
42
+ rescue CommandExitError
43
+ @kernel.exit 1
44
+ rescue StandardError => exception
45
+ @stderr.puts "#{exception.class}: #{exception.message}"
46
+ @stderr.puts exception.backtrace.join("\n")
47
+ @kernel.exit 1
39
48
  end
40
- exit(0)
49
+ @kernel.exit 0
41
50
  end
42
51
 
43
- def help
44
- "Usage: ggem GEM-NAME\n\n"\
45
- "Options:"\
46
- "#{@cli}"
47
- end
52
+ private
48
53
 
49
- end
50
-
51
- class CLIRB # Version 1.0.0, https://github.com/redding/cli.rb
52
- Error = Class.new(RuntimeError);
53
- HelpExit = Class.new(RuntimeError); VersionExit = Class.new(RuntimeError)
54
- attr_reader :argv, :args, :opts, :data
55
-
56
- def initialize(&block)
57
- @options = []; instance_eval(&block) if block
58
- require 'optparse'
59
- @data, @args, @opts = [], [], {}; @parser = OptionParser.new do |p|
60
- p.banner = ''; @options.each do |o|
61
- @opts[o.name] = o.value; p.on(*o.parser_args){ |v| @opts[o.name] = v }
62
- end
63
- p.on_tail('--version', ''){ |v| raise VersionExit, v.to_s }
64
- p.on_tail('--help', ''){ |v| raise HelpExit, v.to_s }
54
+ def display_debug(exception)
55
+ if ENV['DEBUG']
56
+ @stderr.puts "#{exception.class}: #{exception.message}"
57
+ @stderr.puts exception.backtrace.join("\n")
65
58
  end
66
59
  end
67
60
 
68
- def option(*args); @options << Option.new(*args); end
69
- def parse!(argv)
70
- @args = (argv || []).dup.tap do |args_list|
71
- begin; @parser.parse!(args_list)
72
- rescue OptionParser::ParseError => err; raise Error, err.message; end
73
- end; @data = @args + [@opts]
74
- end
75
- def to_s; @parser.to_s; end
76
- def inspect
77
- "#<#{self.class}:#{'0x0%x' % (object_id << 1)} @data=#{@data.inspect}>"
78
- end
79
-
80
- class Option
81
- attr_reader :name, :opt_name, :desc, :abbrev, :value, :klass, :parser_args
82
-
83
- def initialize(name, *args)
84
- settings, @desc = args.last.kind_of?(::Hash) ? args.pop : {}, args.pop || ''
85
- @name, @opt_name, @abbrev = parse_name_values(name, settings[:abbrev])
86
- @value, @klass = gvalinfo(settings[:value])
87
- @parser_args = if [TrueClass, FalseClass, NilClass].include?(@klass)
88
- ["-#{@abbrev}", "--[no-]#{@opt_name}", @desc]
89
- else
90
- ["-#{@abbrev}", "--#{@opt_name} #{@opt_name.upcase}", @klass, @desc]
91
- end
92
- end
93
-
94
- private
95
-
96
- def parse_name_values(name, custom_abbrev)
97
- [ (processed_name = name.to_s.strip.downcase), processed_name.gsub('_', '-'),
98
- custom_abbrev || processed_name.gsub(/[^a-z]/, '').chars.first || 'a'
99
- ]
100
- end
101
- def gvalinfo(v); v.kind_of?(Class) ? [nil,gklass(v)] : [v,gklass(v.class)]; end
102
- def gklass(k); k == Fixnum ? Integer : k; end
103
- end
104
61
  end
105
62
 
106
63
  end
@@ -0,0 +1,59 @@
1
+ module GGem; end
2
+ class GGem::CLI
3
+
4
+ class CLIRB # Version 1.0.0, https://github.com/redding/cli.rb
5
+ Error = Class.new(RuntimeError);
6
+ HelpExit = Class.new(RuntimeError); VersionExit = Class.new(RuntimeError)
7
+ attr_reader :argv, :args, :opts, :data
8
+
9
+ def initialize(&block)
10
+ @options = []; instance_eval(&block) if block
11
+ require 'optparse'
12
+ @data, @args, @opts = [], [], {}; @parser = OptionParser.new do |p|
13
+ p.banner = ''; @options.each do |o|
14
+ @opts[o.name] = o.value; p.on(*o.parser_args){ |v| @opts[o.name] = v }
15
+ end
16
+ p.on_tail('--version', ''){ |v| raise VersionExit, v.to_s }
17
+ p.on_tail('--help', ''){ |v| raise HelpExit, v.to_s }
18
+ end
19
+ end
20
+
21
+ def option(*args); @options << Option.new(*args); end
22
+ def parse!(argv)
23
+ @args = (argv || []).dup.tap do |args_list|
24
+ begin; @parser.parse!(args_list)
25
+ rescue OptionParser::ParseError => err; raise Error, err.message; end
26
+ end; @data = @args + [@opts]
27
+ end
28
+ def to_s; @parser.to_s; end
29
+ def inspect
30
+ "#<#{self.class}:#{'0x0%x' % (object_id << 1)} @data=#{@data.inspect}>"
31
+ end
32
+
33
+ class Option
34
+ attr_reader :name, :opt_name, :desc, :abbrev, :value, :klass, :parser_args
35
+
36
+ def initialize(name, *args)
37
+ settings, @desc = args.last.kind_of?(::Hash) ? args.pop : {}, args.pop || ''
38
+ @name, @opt_name, @abbrev = parse_name_values(name, settings[:abbrev])
39
+ @value, @klass = gvalinfo(settings[:value])
40
+ @parser_args = if [TrueClass, FalseClass, NilClass].include?(@klass)
41
+ ["-#{@abbrev}", "--[no-]#{@opt_name}", @desc]
42
+ else
43
+ ["-#{@abbrev}", "--#{@opt_name} #{@opt_name.upcase}", @klass, @desc]
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ def parse_name_values(name, custom_abbrev)
50
+ [ (processed_name = name.to_s.strip.downcase), processed_name.gsub('_', '-'),
51
+ custom_abbrev || processed_name.gsub(/[^a-z]/, '').chars.first || 'a'
52
+ ]
53
+ end
54
+ def gvalinfo(v); v.kind_of?(Class) ? [nil,gklass(v)] : [v,gklass(v.class)]; end
55
+ def gklass(k); k == Fixnum ? Integer : k; end
56
+ end
57
+ end
58
+
59
+ end
@@ -0,0 +1,402 @@
1
+ require 'ggem/cli/clirb'
2
+ require 'much-plugin'
3
+
4
+ module GGem; end
5
+ class GGem::CLI
6
+
7
+ InvalidCommandError = Class.new(ArgumentError)
8
+ CommandExitError = Class.new(RuntimeError)
9
+
10
+ class InvalidCommand
11
+
12
+ attr_reader :name, :clirb
13
+
14
+ def initialize(name)
15
+ @name = name
16
+ @clirb = CLIRB.new
17
+ end
18
+
19
+ def new; self; end
20
+
21
+ def run(argv)
22
+ @clirb.parse!([@name, argv].flatten.compact)
23
+ raise CLIRB::HelpExit if @name.to_s.empty?
24
+ raise InvalidCommandError, "'#{self.name}' is not a command."
25
+ end
26
+
27
+ def help
28
+ "Usage: ggem [COMMAND] [options]\n\n" \
29
+ "Options: #{@clirb}\n" \
30
+ "Commands:\n" \
31
+ "#{COMMANDS.to_s.split("\n").map{ |l| " #{l}" }.join("\n")}\n"
32
+ end
33
+
34
+ end
35
+
36
+ module ValidCommand
37
+ include MuchPlugin
38
+
39
+ plugin_included do
40
+ include InstanceMethods
41
+ end
42
+
43
+ module InstanceMethods
44
+
45
+ def initialize
46
+ @clirb = CLIRB.new
47
+ end
48
+
49
+ def clirb; @clirb; end
50
+
51
+ def run(argv, stdout = nil, stderr = nil)
52
+ @clirb.parse!(argv)
53
+ @stdout = stdout || $stdout
54
+ @stderr = stderr || $stderr
55
+ end
56
+
57
+ def summary
58
+ ''
59
+ end
60
+
61
+ end
62
+
63
+ end
64
+
65
+ module NotifyCmdCommand
66
+ include MuchPlugin
67
+
68
+ plugin_included do
69
+ include InstanceMethods
70
+ end
71
+
72
+ module InstanceMethods
73
+
74
+ private
75
+
76
+ def notify(success_msg, &cmd_block)
77
+ cmd(&cmd_block)
78
+ @stdout.puts success_msg
79
+ end
80
+
81
+ def cmd(&cmd_block)
82
+ cmd, status, output = cmd_block.call
83
+ if ENV['DEBUG']
84
+ @stdout.puts cmd
85
+ @stdout.puts output
86
+ end
87
+ end
88
+
89
+ end
90
+
91
+ end
92
+
93
+ module GitRepoCommand
94
+ include MuchPlugin
95
+
96
+ plugin_included do
97
+ include ValidCommand
98
+ include NotifyCmdCommand
99
+ include InstanceMethods
100
+ end
101
+
102
+ module InstanceMethods
103
+ def initialize(*args)
104
+ super
105
+
106
+ require 'ggem/git_repo'
107
+ @repo = GGem::GitRepo.new(Dir.pwd)
108
+ end
109
+
110
+ private
111
+
112
+ def notify(*args, &block)
113
+ begin
114
+ super
115
+ rescue GGem::GitRepo::CmdError => exception
116
+ @stderr.puts exception.message
117
+ raise CommandExitError
118
+ end
119
+ end
120
+
121
+ end
122
+ end
123
+
124
+ class GenerateCommand
125
+ include GitRepoCommand
126
+
127
+ def run(argv, *args)
128
+ super
129
+
130
+ begin
131
+ require 'ggem/gem'
132
+ path = GGem::Gem.new(Dir.pwd, @clirb.args.first).save!.path
133
+ @stdout.puts "created gem in #{path}"
134
+ rescue GGem::Gem::NoNameError => exception
135
+ error = ArgumentError.new("GEM-NAME must be provided")
136
+ error.set_backtrace(exception.backtrace)
137
+ raise error
138
+ end
139
+
140
+ @repo = GGem::GitRepo.new(path)
141
+ notify("initialized gem git repo"){ @repo.run_init_cmd }
142
+ end
143
+
144
+ def summary
145
+ "Create a gem given a GEM-NAME"
146
+ end
147
+
148
+ def help
149
+ "Usage: ggem generate [options] GEM-NAME\n\n" \
150
+ "Options: #{@clirb}\n" \
151
+ "Description:\n" \
152
+ " #{self.summary}"
153
+ end
154
+
155
+ end
156
+
157
+ module GemspecCommand
158
+ include MuchPlugin
159
+
160
+ plugin_included do
161
+ include ValidCommand
162
+ include NotifyCmdCommand
163
+ include InstanceMethods
164
+ end
165
+
166
+ module InstanceMethods
167
+ def initialize(*args)
168
+ super
169
+
170
+ require 'ggem/gemspec'
171
+ begin
172
+ @spec = GGem::Gemspec.new(Dir.pwd)
173
+ rescue GGem::Gemspec::NotFoundError => exception
174
+ error = ArgumentError.new("There are no gemspecs at #{Dir.pwd}")
175
+ error.set_backtrace(exception.backtrace)
176
+ raise error
177
+ end
178
+ end
179
+
180
+ private
181
+
182
+ def notify(*args, &block)
183
+ begin
184
+ super
185
+ rescue GGem::Gemspec::CmdError => exception
186
+ @stderr.puts exception.message
187
+ raise CommandExitError
188
+ end
189
+ end
190
+
191
+ end
192
+ end
193
+
194
+ class BuildCommand
195
+ include GemspecCommand
196
+
197
+ def run(argv, *args)
198
+ super
199
+ notify("#{@spec.name} #{@spec.version} built to #{@spec.gem_file}") do
200
+ @spec.run_build_cmd
201
+ end
202
+ end
203
+
204
+ def summary
205
+ "Build #{@spec.gem_file_name} into the " \
206
+ "#{GGem::Gemspec::BUILD_TO_DIRNAME} directory"
207
+ end
208
+
209
+ def help
210
+ "Usage: ggem build [options]\n\n" \
211
+ "Options: #{@clirb}\n" \
212
+ "Description:\n" \
213
+ " #{self.summary}"
214
+ end
215
+
216
+ end
217
+
218
+ class InstallCommand
219
+ include GemspecCommand
220
+
221
+ def initialize(*args)
222
+ super
223
+ @build_command = BuildCommand.new(*args)
224
+ end
225
+
226
+ def run(argv, *args)
227
+ super
228
+ @build_command.run(argv)
229
+ notify("#{@spec.name} #{@spec.version} installed to system gems") do
230
+ @spec.run_install_cmd
231
+ end
232
+ end
233
+
234
+ def summary
235
+ "Build and install #{@spec.gem_file_name} into system gems"
236
+ end
237
+
238
+ def help
239
+ "Usage: ggem install [options]\n\n" \
240
+ "Options: #{@clirb}\n" \
241
+ "Description:\n" \
242
+ " #{self.summary}"
243
+ end
244
+
245
+ end
246
+
247
+ class PushCommand
248
+ include GemspecCommand
249
+
250
+ def initialize(*args)
251
+ super
252
+ @build_command = BuildCommand.new(*args)
253
+ end
254
+
255
+ def run(argv, *args)
256
+ super
257
+ @build_command.run(argv)
258
+
259
+ @stdout.puts "Pushing #{@spec.gem_file_name} to #{@spec.push_host}..."
260
+ notify("#{@spec.gem_file_name} received.") do
261
+ @spec.run_push_cmd
262
+ end
263
+ end
264
+
265
+ def summary
266
+ "Push built #{@spec.gem_file_name} to #{@spec.push_host}"
267
+ end
268
+
269
+ def help
270
+ "Usage: ggem push [options]\n\n" \
271
+ "Options: #{@clirb}\n" \
272
+ "Description:\n" \
273
+ " #{self.summary}"
274
+ end
275
+
276
+ end
277
+
278
+ class TagCommand
279
+ include GitRepoCommand
280
+ include GemspecCommand
281
+
282
+ def run(argv, *args)
283
+ super
284
+
285
+ begin
286
+ cmd{ @repo.run_validate_clean_cmd }
287
+ cmd{ @repo.run_validate_committed_cmd }
288
+ rescue GGem::GitRepo::CmdError => err
289
+ @stderr.puts "There are files that need to be committed first."
290
+ raise CommandExitError
291
+ end
292
+
293
+ cmd{ @repo.run_add_version_tag_cmd(@spec.version, @spec.version_tag) }
294
+
295
+ @stdout.puts "Tagged #{@spec.version_tag}."
296
+
297
+ begin
298
+ cmd{ @repo.run_push_cmd }
299
+ rescue
300
+ cmd{ @repo.run_rm_tag_cmd(@spec.version_tag) }
301
+ raise
302
+ end
303
+
304
+ @stdout.puts "Pushed git commits and tags."
305
+ rescue GGem::GitRepo::CmdError => err
306
+ @stderr.puts err.message
307
+ raise CommandExitError
308
+ end
309
+
310
+ def summary
311
+ "Tag #{@spec.version_tag} and push git commits/tags"
312
+ end
313
+
314
+ def help
315
+ "Usage: ggem tag [options]\n\n" \
316
+ "Options: #{@clirb}\n" \
317
+ "Description:\n" \
318
+ " #{self.summary}"
319
+ end
320
+
321
+ end
322
+
323
+ class ReleaseCommand
324
+ include GemspecCommand
325
+
326
+ def initialize(*args)
327
+ super
328
+ @tag_command = TagCommand.new(*args)
329
+ @push_command = PushCommand.new(*args)
330
+ end
331
+
332
+ def run(argv, *args)
333
+ super
334
+ @tag_command.run(argv)
335
+ @push_command.run(argv)
336
+ end
337
+
338
+ def summary
339
+ "Tag #{@spec.version_tag} and push built #{@spec.gem_file_name} to " \
340
+ "#{@spec.push_host}"
341
+ end
342
+
343
+ def help
344
+ "Usage: ggem release [options]\n\n" \
345
+ "Options: #{@clirb}\n" \
346
+ "Description:\n" \
347
+ " #{self.summary}\n" \
348
+ " (macro for running `ggem tag && ggem push`)"
349
+ end
350
+
351
+ end
352
+
353
+ class CommandSet
354
+
355
+ def initialize(&unknown_cmd_block)
356
+ @lookup = Hash.new{ |h,k| unknown_cmd_block.call(k) }
357
+ @names = []
358
+ @aliases = {}
359
+ @summaries = {}
360
+ end
361
+
362
+ def add(klass, name, *aliases)
363
+ begin
364
+ cmd = klass.new
365
+ rescue StandardError => err
366
+ # don't add any commands you can't init
367
+ else
368
+ ([name] + aliases).each{ |n| @lookup[n] = cmd }
369
+ @to_s = nil
370
+ @names << name
371
+ @aliases[name] = aliases.empty? ? '' : "(#{aliases.join(', ')})"
372
+ @summaries[name] = cmd.summary.to_s.empty? ? '' : "# #{cmd.summary}"
373
+ end
374
+ end
375
+
376
+ def remove(name)
377
+ @lookup.delete(name)
378
+ @names.delete(name)
379
+ @aliases.delete(name)
380
+ @to_s = nil
381
+ end
382
+
383
+ def [](name)
384
+ @lookup[name]
385
+ end
386
+
387
+ def size
388
+ @names.size
389
+ end
390
+
391
+ def to_s
392
+ max_name_size = @names.map{ |n| n.size }.max || 0
393
+ max_alias_size = @aliases.values.map{ |v| v.size }.max || 0
394
+
395
+ @to_s ||= @names.map do |n|
396
+ "#{n.ljust(max_name_size)} #{@aliases[n].ljust(max_alias_size)} #{@summaries[n]}"
397
+ end.join("\n")
398
+ end
399
+
400
+ end
401
+
402
+ end