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.
- checksums.yaml +7 -0
- data/README.md +153 -9
- data/bin/ggem +1 -1
- data/ggem.gemspec +6 -3
- data/lib/ggem/cli.rb +40 -83
- data/lib/ggem/cli/clirb.rb +59 -0
- data/lib/ggem/cli/commands.rb +402 -0
- data/lib/ggem/gem.rb +9 -3
- data/lib/ggem/gemspec.rb +85 -0
- data/lib/ggem/git_repo.rb +60 -0
- data/lib/ggem/template.rb +2 -8
- data/lib/ggem/template_file/Gemfile.erb +1 -2
- data/lib/ggem/template_file/gemspec.erb +5 -5
- data/lib/ggem/version.rb +1 -1
- data/test/helper.rb +5 -44
- data/test/support/cmd_tests_helpers.rb +53 -0
- data/test/support/gem1/gem1.gemspec +16 -0
- data/test/support/gem2/gem2.gemspec +18 -0
- data/test/support/name_set.rb +0 -1
- data/test/system/ggem_tests.rb +45 -17
- data/test/unit/cli_tests.rb +1012 -0
- data/test/unit/gem_tests.rb +21 -4
- data/test/unit/gemspec_tests.rb +154 -0
- data/test/unit/git_repo_tests.rb +162 -0
- metadata +50 -33
- data/lib/ggem/template_file/Rakefile.erb +0 -1
checksums.yaml
ADDED
@@ -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
|
-
|
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
|
9
|
-
|
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
|
-
|
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
data/ggem.gemspec
CHANGED
@@ -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
|
12
|
-
gem.summary = %q{"Juh Gem", baby! (a
|
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
|
data/lib/ggem/cli.rb
CHANGED
@@ -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
|
-
|
9
|
-
|
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
|
13
|
-
|
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
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
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
|
-
|
26
|
-
|
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
|
-
|
33
|
-
puts
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
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
|
49
|
+
@kernel.exit 0
|
41
50
|
end
|
42
51
|
|
43
|
-
|
44
|
-
"Usage: ggem GEM-NAME\n\n"\
|
45
|
-
"Options:"\
|
46
|
-
"#{@cli}"
|
47
|
-
end
|
52
|
+
private
|
48
53
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
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
|