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
data/lib/ggem/gem.rb
CHANGED
@@ -8,11 +8,12 @@ module GGem
|
|
8
8
|
attr_reader :root_path, :name
|
9
9
|
|
10
10
|
def initialize(path, name)
|
11
|
+
raise NoNameError if name.to_s.empty?
|
11
12
|
@root_path, self.name = path, name
|
12
13
|
end
|
13
14
|
|
14
15
|
def save!
|
15
|
-
Template.new(self).
|
16
|
+
Template.new(self).save
|
16
17
|
self
|
17
18
|
end
|
18
19
|
|
@@ -20,7 +21,10 @@ module GGem
|
|
20
21
|
def name=(name); @name = normalize_name(name); end
|
21
22
|
|
22
23
|
def module_name
|
23
|
-
transforms = {
|
24
|
+
transforms = {
|
25
|
+
'_' => '',
|
26
|
+
'-' => ''
|
27
|
+
}
|
24
28
|
@module_name ||= transform_name(transforms){ |part| part.capitalize }
|
25
29
|
end
|
26
30
|
|
@@ -37,7 +41,7 @@ module GGem
|
|
37
41
|
name.gsub(*und_camelcs).gsub(*rm_dup_und).sub(*rm_lead_und).downcase
|
38
42
|
end
|
39
43
|
|
40
|
-
def transform_name(conditions={}, &block)
|
44
|
+
def transform_name(conditions = {}, &block)
|
41
45
|
n = (block ? block.call(self.name) : self.name)
|
42
46
|
conditions.each do |on, glue|
|
43
47
|
if (a = n.split(on)).size > 1
|
@@ -47,6 +51,8 @@ module GGem
|
|
47
51
|
n
|
48
52
|
end
|
49
53
|
|
54
|
+
NoNameError = Class.new(ArgumentError)
|
55
|
+
|
50
56
|
end
|
51
57
|
|
52
58
|
end
|
data/lib/ggem/gemspec.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'scmd'
|
3
|
+
|
4
|
+
module GGem
|
5
|
+
|
6
|
+
class Gemspec
|
7
|
+
|
8
|
+
PUSH_HOST_META_KEY = 'allowed_push_host'
|
9
|
+
DEFAULT_PUSH_HOST = 'https://rubygems.org'.freeze
|
10
|
+
BUILD_TO_DIRNAME = 'pkg'.freeze
|
11
|
+
|
12
|
+
attr_reader :path, :name, :version, :version_tag
|
13
|
+
attr_reader :gem_file_name, :gem_file, :push_host
|
14
|
+
|
15
|
+
def initialize(root_path)
|
16
|
+
@root = Pathname.new(File.expand_path(root_path))
|
17
|
+
raise NotFoundError unless @root.exist?
|
18
|
+
@path = Pathname.new(Dir[File.join(@root, "{,*}.gemspec")].first.to_s)
|
19
|
+
raise NotFoundError unless @path.exist?
|
20
|
+
|
21
|
+
@spec = load_gemspec(@path)
|
22
|
+
@name = @spec.name
|
23
|
+
@version = @spec.version
|
24
|
+
@version_tag = "v#{@version}"
|
25
|
+
|
26
|
+
@gem_file_name = "#{@name}-#{@version}.gem"
|
27
|
+
@gem_file = File.join(BUILD_TO_DIRNAME, @gem_file_name)
|
28
|
+
@built_gem_path = @root.join(@gem_file)
|
29
|
+
|
30
|
+
@push_host = get_push_host(@spec)
|
31
|
+
end
|
32
|
+
|
33
|
+
def run_build_cmd
|
34
|
+
run_cmd("gem build --verbose #{@path}").tap do
|
35
|
+
gem_path = @root.join(@gem_file_name)
|
36
|
+
run_cmd("mkdir -p #{@built_gem_path.dirname}")
|
37
|
+
run_cmd("mv #{gem_path} #{@built_gem_path}")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def run_install_cmd
|
42
|
+
run_cmd("gem install #{@built_gem_path}")
|
43
|
+
end
|
44
|
+
|
45
|
+
def run_push_cmd
|
46
|
+
run_cmd("gem push #{@built_gem_path} --host #{@push_host}")
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def run_cmd(cmd_string)
|
52
|
+
cmd = Scmd.new(cmd_string)
|
53
|
+
cmd.run
|
54
|
+
if !cmd.success?
|
55
|
+
raise CmdError, "#{cmd_string}\n" \
|
56
|
+
"#{cmd.stderr.empty? ? cmd.stdout : cmd.stderr}"
|
57
|
+
end
|
58
|
+
[cmd_string, cmd.exitstatus, cmd.stdout]
|
59
|
+
end
|
60
|
+
|
61
|
+
def load_gemspec(path)
|
62
|
+
eval(path.read, TOPLEVEL_BINDING, path.expand_path.to_s)
|
63
|
+
rescue ScriptError, StandardError => e
|
64
|
+
original_line = e.backtrace.find{ |line| line.include?(path.to_s) }
|
65
|
+
msg = "There was a #{e.class} while loading #{path.basename}: \n#{e.message}"
|
66
|
+
msg << " from\n #{original_line}" if original_line
|
67
|
+
msg << "\n"
|
68
|
+
raise LoadError, msg
|
69
|
+
end
|
70
|
+
|
71
|
+
def get_push_host(spec)
|
72
|
+
ENV['GGEM_PUSH_HOST'] || get_meta(spec)[PUSH_HOST_META_KEY] || DEFAULT_PUSH_HOST
|
73
|
+
end
|
74
|
+
|
75
|
+
def get_meta(spec)
|
76
|
+
(spec.respond_to?(:metadata) ? spec.metadata : {}) || {}
|
77
|
+
end
|
78
|
+
|
79
|
+
NotFoundError = Class.new(ArgumentError)
|
80
|
+
LoadError = Class.new(ArgumentError)
|
81
|
+
CmdError = Class.new(RuntimeError)
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'scmd'
|
3
|
+
|
4
|
+
module GGem
|
5
|
+
|
6
|
+
class GitRepo
|
7
|
+
|
8
|
+
attr_reader :path
|
9
|
+
|
10
|
+
def initialize(repo_path)
|
11
|
+
@path = Pathname.new(File.expand_path(repo_path))
|
12
|
+
end
|
13
|
+
|
14
|
+
def run_init_cmd
|
15
|
+
run_cmd("git init").tap do
|
16
|
+
run_cmd("git add --all && git add -f *.gitkeep")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def run_validate_clean_cmd
|
21
|
+
run_cmd("git diff --exit-code")
|
22
|
+
end
|
23
|
+
|
24
|
+
def run_validate_committed_cmd
|
25
|
+
run_cmd("git diff-index --quiet --cached HEAD")
|
26
|
+
end
|
27
|
+
|
28
|
+
def run_push_cmd
|
29
|
+
run_cmd("git push").tap do
|
30
|
+
run_cmd("git push --tags")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def run_add_version_tag_cmd(version, tag)
|
35
|
+
run_cmd("git tag -a -m \"Version #{version}\" #{tag}")
|
36
|
+
end
|
37
|
+
|
38
|
+
def run_rm_tag_cmd(tag)
|
39
|
+
run_cmd("git tag -d #{tag}")
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def run_cmd(cmd_string)
|
45
|
+
cmd_string = "cd #{@path} && #{cmd_string}"
|
46
|
+
cmd = Scmd.new(cmd_string)
|
47
|
+
cmd.run
|
48
|
+
if !cmd.success?
|
49
|
+
raise CmdError, "#{cmd_string}\n" \
|
50
|
+
"#{cmd.stderr.empty? ? cmd.stdout : cmd.stderr}"
|
51
|
+
end
|
52
|
+
[cmd_string, cmd.exitstatus, cmd.stdout]
|
53
|
+
end
|
54
|
+
|
55
|
+
NotFoundError = Class.new(ArgumentError)
|
56
|
+
CmdError = Class.new(RuntimeError)
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
data/lib/ggem/template.rb
CHANGED
@@ -2,6 +2,7 @@ require 'erb'
|
|
2
2
|
require 'fileutils'
|
3
3
|
|
4
4
|
module GGem
|
5
|
+
|
5
6
|
class Template
|
6
7
|
|
7
8
|
def initialize(ggem)
|
@@ -20,7 +21,6 @@ module GGem
|
|
20
21
|
save_file('gitignore.erb', '.gitignore')
|
21
22
|
save_file('Gemfile.erb', 'Gemfile')
|
22
23
|
save_file('gemspec.erb', "#{@gem.name}.gemspec")
|
23
|
-
save_file('Rakefile.erb', 'Rakefile')
|
24
24
|
save_file('README.md.erb', 'README.md')
|
25
25
|
save_file('LICENSE.erb', 'LICENSE')
|
26
26
|
|
@@ -34,13 +34,6 @@ module GGem
|
|
34
34
|
save_empty_file('tmp/.gitkeep')
|
35
35
|
end
|
36
36
|
|
37
|
-
def init
|
38
|
-
cmd = "cd #{@gem.path} &&"\
|
39
|
-
" git init && git add --all &&"\
|
40
|
-
" git add -f log/.gitkeep && git add -f tmp/.gitkeep"
|
41
|
-
`#{cmd}`
|
42
|
-
end
|
43
|
-
|
44
37
|
private
|
45
38
|
|
46
39
|
def save_folder(relative_path=nil)
|
@@ -67,4 +60,5 @@ module GGem
|
|
67
60
|
end
|
68
61
|
|
69
62
|
end
|
63
|
+
|
70
64
|
end
|
@@ -8,9 +8,9 @@ Gem::Specification.new do |gem|
|
|
8
8
|
gem.version = <%= @gem.module_name %>::VERSION
|
9
9
|
gem.authors = ["TODO: authors"]
|
10
10
|
gem.email = ["TODO: emails"]
|
11
|
-
gem.
|
12
|
-
gem.
|
13
|
-
gem.homepage = "
|
11
|
+
gem.summary = "TODO: Write a gem summary"
|
12
|
+
gem.description = "TODO: Write a gem description"
|
13
|
+
gem.homepage = "TODO: homepage"
|
14
14
|
gem.license = 'MIT'
|
15
15
|
|
16
16
|
gem.files = `git ls-files`.split($/)
|
@@ -18,7 +18,7 @@ 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"])
|
22
|
-
# TODO: gem.add_dependency("gem-name", ["~> 0.0"])
|
21
|
+
gem.add_development_dependency("assert", ["~> 2.15.0"])
|
22
|
+
# TODO: gem.add_dependency("gem-name", ["~> 0.0.0"])
|
23
23
|
|
24
24
|
end
|
data/lib/ggem/version.rb
CHANGED
data/test/helper.rb
CHANGED
@@ -2,52 +2,13 @@
|
|
2
2
|
# put any test helpers here
|
3
3
|
|
4
4
|
# add the root dir to the load path
|
5
|
-
|
5
|
+
require 'pathname'
|
6
|
+
ROOT_PATH = Pathname.new(File.expand_path('../..', __FILE__))
|
7
|
+
$LOAD_PATH.unshift(ROOT_PATH.to_s)
|
8
|
+
TMP_PATH = ROOT_PATH.join('tmp')
|
9
|
+
TEST_SUPPORT_PATH = ROOT_PATH.join('test/support')
|
6
10
|
|
7
11
|
# require pry for debugging (`binding.pry`)
|
8
12
|
require 'pry'
|
9
13
|
|
10
14
|
require 'test/support/factory'
|
11
|
-
|
12
|
-
class Assert::Context
|
13
|
-
|
14
|
-
TMP_PATH = File.expand_path "../../tmp", __FILE__
|
15
|
-
|
16
|
-
def self.create_paths(name_set)
|
17
|
-
called_from = caller.first
|
18
|
-
folders = name_set.expected_folders
|
19
|
-
files = name_set.expected_files
|
20
|
-
|
21
|
-
paths = (folders + files).collect{|p| File.join(TMP_PATH, name_set.name, p)}
|
22
|
-
macro_name = "create the paths: #{paths.join(', ')}"
|
23
|
-
|
24
|
-
Assert::Macro.new(macro_name) do
|
25
|
-
paths.flatten.each do |path|
|
26
|
-
should "create the path '#{path}'", called_from do
|
27
|
-
assert File.exists?(path), "'#{path}' does not exist"
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
end
|
33
|
-
|
34
|
-
def self.generate_name_set(name_set)
|
35
|
-
called_from = caller.first
|
36
|
-
macro_name = "generate the name_set: #{name_set.inspect}"
|
37
|
-
|
38
|
-
Assert::Macro.new(macro_name) do
|
39
|
-
name_set.variations.each do |variation|
|
40
|
-
[:name, :module_name, :ruby_name].each do |name_type|
|
41
|
-
should "know its :#{name_type} given '#{variation}'", called_from do
|
42
|
-
the_gem = GGem::Gem.new(TMP_PATH, variation)
|
43
|
-
assert_equal name_set.send(name_type), the_gem.send(name_type)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
end
|
50
|
-
|
51
|
-
end
|
52
|
-
|
53
|
-
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'much-plugin'
|
2
|
+
require 'scmd'
|
3
|
+
|
4
|
+
module GGem
|
5
|
+
|
6
|
+
module CmdTestsHelpers
|
7
|
+
include MuchPlugin
|
8
|
+
|
9
|
+
plugin_included do
|
10
|
+
setup do
|
11
|
+
ENV['SCMD_TEST_MODE'] = '1'
|
12
|
+
|
13
|
+
@cmd_spy = nil
|
14
|
+
Scmd.reset
|
15
|
+
|
16
|
+
@exp_cmds_run = []
|
17
|
+
end
|
18
|
+
teardown do
|
19
|
+
Scmd.reset
|
20
|
+
ENV.delete('SCMD_TEST_MODE')
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def assert_exp_cmds_run(&run_cmd_block)
|
26
|
+
cmd_str, exitstatus, stdout = run_cmd_block.call
|
27
|
+
assert_equal @exp_cmds_run, Scmd.calls.map(&:cmd_str)
|
28
|
+
|
29
|
+
assert_equal Scmd.calls.first.cmd_str, cmd_str
|
30
|
+
assert_equal Scmd.calls.first.cmd.exitstatus, exitstatus
|
31
|
+
assert_equal Scmd.calls.first.cmd.stdout, stdout
|
32
|
+
end
|
33
|
+
|
34
|
+
def assert_exp_cmds_error(cmd_error_class, &run_cmd_block)
|
35
|
+
err_cmd_str = @exp_cmds_run.choice
|
36
|
+
Scmd.add_command(err_cmd_str) do |cmd|
|
37
|
+
cmd.exitstatus = 1
|
38
|
+
cmd.stderr = Factory.string
|
39
|
+
@cmd_spy = cmd
|
40
|
+
end
|
41
|
+
err = nil
|
42
|
+
begin; run_cmd_block.call; rescue StandardError => err; end
|
43
|
+
|
44
|
+
assert_kind_of cmd_error_class, err
|
45
|
+
exp = "#{@cmd_spy.cmd_str}\n#{@cmd_spy.stderr}"
|
46
|
+
assert_equal exp, err.message
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
Gem::Specification.new do |gem|
|
3
|
+
gem.name = "gem1"
|
4
|
+
gem.version = "0.1.0"
|
5
|
+
gem.authors = []
|
6
|
+
gem.email = []
|
7
|
+
gem.summary = %q{Gem 1 summary}
|
8
|
+
gem.description = %q{Gem 1 description}
|
9
|
+
gem.license = 'MIT'
|
10
|
+
|
11
|
+
gem.files = []
|
12
|
+
gem.executables = []
|
13
|
+
gem.test_files = []
|
14
|
+
gem.require_paths = []
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
Gem::Specification.new do |gem|
|
3
|
+
gem.name = "gem2"
|
4
|
+
gem.version = "0.2.0"
|
5
|
+
gem.authors = []
|
6
|
+
gem.email = []
|
7
|
+
gem.summary = %q{Gem 2 summary}
|
8
|
+
gem.description = %q{Gem 2 description}
|
9
|
+
gem.license = 'MIT'
|
10
|
+
|
11
|
+
gem.metadata['allowed_push_host'] = 'http://gems.example.com'
|
12
|
+
|
13
|
+
gem.files = []
|
14
|
+
gem.executables = []
|
15
|
+
gem.test_files = []
|
16
|
+
gem.require_paths = []
|
17
|
+
|
18
|
+
end
|
data/test/support/name_set.rb
CHANGED
data/test/system/ggem_tests.rb
CHANGED
@@ -5,39 +5,67 @@ require 'test/support/name_set'
|
|
5
5
|
|
6
6
|
module GGem
|
7
7
|
|
8
|
-
class
|
9
|
-
desc "GGem"
|
8
|
+
class SystemTests < Assert::Context
|
10
9
|
|
11
10
|
NS_SIMPLE = GGem::NameSet::Simple
|
12
11
|
NS_UNDER = GGem::NameSet::Underscored
|
13
12
|
NS_HYPHEN = GGem::NameSet::HyphenatedOther
|
14
13
|
|
15
|
-
|
16
|
-
|
14
|
+
desc "GGem"
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
class GemTests < SystemTests
|
19
|
+
desc "Gem"
|
20
|
+
|
21
|
+
should "know its name attrs for various name styles (simple/underscored/hyphenated)" do
|
22
|
+
[NS_SIMPLE, NS_UNDER, NS_HYPHEN].each do |ns|
|
23
|
+
assert_gem_name_set(ns.new)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def assert_gem_name_set(name_set)
|
30
|
+
name_set.variations.each do |variation|
|
31
|
+
the_gem = GGem::Gem.new(TMP_PATH, variation)
|
32
|
+
[:name, :module_name, :ruby_name].each do |name_type|
|
33
|
+
assert_equal name_set.send(name_type), the_gem.send(name_type)
|
34
|
+
end
|
35
|
+
end
|
17
36
|
end
|
18
37
|
|
19
38
|
end
|
20
39
|
|
21
|
-
class
|
22
|
-
|
23
|
-
setup_once do
|
40
|
+
class GemSaveTests < GemTests
|
41
|
+
setup do
|
24
42
|
FileUtils.rm_rf(TMP_PATH)
|
25
43
|
FileUtils.mkdir_p(TMP_PATH)
|
26
|
-
GGem::Gem.new(TMP_PATH, NS_SIMPLE.new.variations.first).save!
|
27
|
-
GGem::Gem.new(TMP_PATH, NS_UNDER.new.variations.first).save!
|
28
|
-
GGem::Gem.new(TMP_PATH, NS_HYPHEN.new.variations.first).save!
|
29
44
|
end
|
30
|
-
|
45
|
+
teardown do
|
31
46
|
FileUtils.rm_rf(TMP_PATH)
|
32
47
|
end
|
33
48
|
|
34
|
-
should
|
35
|
-
|
36
|
-
|
49
|
+
should "save gems with various name styles (simple/underscored/hyphenated)" do
|
50
|
+
[NS_SIMPLE, NS_UNDER, NS_HYPHEN].each do |ns|
|
51
|
+
init_gem = GGem::Gem.new(TMP_PATH, ns.new.variations.first)
|
52
|
+
gem_from_save = init_gem.save!
|
53
|
+
|
54
|
+
assert_gem_created(ns.new)
|
55
|
+
assert_same init_gem, gem_from_save
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def assert_gem_created(name_set)
|
62
|
+
folders = name_set.expected_folders
|
63
|
+
files = name_set.expected_files
|
64
|
+
paths = (folders + files).collect{ |p| File.join(TMP_PATH, name_set.name, p) }
|
37
65
|
|
38
|
-
|
39
|
-
|
40
|
-
|
66
|
+
paths.flatten.each do |path|
|
67
|
+
assert File.exists?(path), "'#{path}' does not exist"
|
68
|
+
end
|
41
69
|
end
|
42
70
|
|
43
71
|
end
|