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