ggem 1.7.0 → 1.8.0

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