shoe 0.1.13 → 0.2.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.
- data/BUNDLER.rdoc +38 -0
- data/README.rdoc +46 -13
- data/Rakefile +2 -5
- data/bin/shoe +2 -30
- data/features/cucumber.feature +5 -24
- data/features/getting_started.feature +14 -11
- data/features/release.feature +11 -22
- data/features/step_definitions/shoe_steps.rb +15 -5
- data/features/support/env.rb +16 -4
- data/lib/shoe.rb +12 -179
- data/lib/shoe/cli.rb +94 -0
- data/lib/shoe/project.rb +26 -0
- data/lib/shoe/tasks.rb +80 -0
- data/lib/shoe/tasks/bin.rb +14 -0
- data/lib/shoe/tasks/clean.rb +18 -0
- data/lib/shoe/tasks/compile.rb +46 -0
- data/lib/shoe/tasks/cucumber.rb +42 -0
- data/lib/shoe/tasks/gemspec.rb +14 -0
- data/lib/shoe/tasks/rdoc.rb +63 -0
- data/lib/shoe/tasks/release.rb +94 -0
- data/lib/shoe/tasks/resources.rb +11 -0
- data/lib/shoe/tasks/shell.rb +20 -0
- data/lib/shoe/tasks/shoulda.rb +12 -0
- data/lib/shoe/tasks/test.rb +28 -0
- data/lib/shoe/templates/gemfile.erb +1 -0
- data/lib/shoe/templates/rakefile.erb +7 -0
- data/lib/shoe/templates/readme.erb +3 -0
- data/lib/shoe/templates/version.erb +3 -0
- data/lib/shoe/version.rb +3 -0
- data/shoe.gemspec +5 -11
- metadata +27 -26
data/lib/shoe/cli.rb
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'erb'
|
4
|
+
require 'pathname'
|
5
|
+
|
6
|
+
class Shoe
|
7
|
+
class CLI
|
8
|
+
class << self
|
9
|
+
def run
|
10
|
+
new.run
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :root
|
15
|
+
attr_reader :spec
|
16
|
+
attr_reader :template_path
|
17
|
+
|
18
|
+
def initialize
|
19
|
+
@root = Pathname.pwd.expand_path
|
20
|
+
|
21
|
+
@spec = Gem::Specification.new do |spec|
|
22
|
+
spec.name = root.basename.to_s
|
23
|
+
spec.version = '0.0.0'
|
24
|
+
end
|
25
|
+
|
26
|
+
@template_path = Pathname.new(__FILE__).dirname.join('templates')
|
27
|
+
end
|
28
|
+
|
29
|
+
def run
|
30
|
+
path('Gemfile').update template('gemfile.erb')
|
31
|
+
|
32
|
+
path('README.rdoc').install template('readme.erb')
|
33
|
+
path('Rakefile').install template('rakefile.erb')
|
34
|
+
path(version_path).install template('version.erb')
|
35
|
+
path(gemspec_path).install spec.to_ruby
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def project
|
41
|
+
spec.name
|
42
|
+
end
|
43
|
+
|
44
|
+
def project_class
|
45
|
+
project.capitalize.gsub(/_(\w)/) { $1.upcase }
|
46
|
+
end
|
47
|
+
|
48
|
+
def project_version
|
49
|
+
spec.version
|
50
|
+
end
|
51
|
+
|
52
|
+
def version_path
|
53
|
+
"lib/#{project}/version.rb"
|
54
|
+
end
|
55
|
+
|
56
|
+
def gemspec_path
|
57
|
+
"#{project}.gemspec"
|
58
|
+
end
|
59
|
+
|
60
|
+
def template(name)
|
61
|
+
ERB.new(template_contents(name)).result(binding)
|
62
|
+
end
|
63
|
+
|
64
|
+
def template_contents(name)
|
65
|
+
template_path.join(name).read
|
66
|
+
end
|
67
|
+
|
68
|
+
def path(name)
|
69
|
+
path = root.join(name)
|
70
|
+
path.dirname.mkpath
|
71
|
+
path.extend(PathExtensions)
|
72
|
+
end
|
73
|
+
|
74
|
+
module PathExtensions
|
75
|
+
def install(contents)
|
76
|
+
if exist?
|
77
|
+
$stderr.puts "#{to_s} exists. Not clobbering."
|
78
|
+
else
|
79
|
+
write(contents, 'w')
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def update(contents)
|
84
|
+
write(contents, 'a')
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def write(contents, mode)
|
90
|
+
open(mode) { |file| file.write(contents) }
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
data/lib/shoe/project.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
module Shoe
|
2
|
+
class Project
|
3
|
+
|
4
|
+
# The Gem::Specification for your project.
|
5
|
+
attr_reader :spec
|
6
|
+
|
7
|
+
# Initializes a Gem::Specification with some nice conventions.
|
8
|
+
def initialize(name, version, summary)
|
9
|
+
@spec = Gem::Specification.new do |spec|
|
10
|
+
spec.name = name
|
11
|
+
spec.version = version
|
12
|
+
spec.summary = summary
|
13
|
+
spec.files = FileList['Rakefile', 'lib/**/*']
|
14
|
+
spec.author = `git config --get user.name`.chomp
|
15
|
+
spec.email = `git config --get user.email`.chomp
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# This is where the magic happens.
|
20
|
+
def define_tasks
|
21
|
+
Shoe::Tasks.each do |task|
|
22
|
+
task.define(spec)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/shoe/tasks.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
module Shoe
|
2
|
+
module Tasks
|
3
|
+
|
4
|
+
autoload :Bin, 'shoe/tasks/bin'
|
5
|
+
autoload :Clean, 'shoe/tasks/clean'
|
6
|
+
autoload :Compile, 'shoe/tasks/compile'
|
7
|
+
autoload :Cucumber, 'shoe/tasks/cucumber'
|
8
|
+
autoload :Gemspec, 'shoe/tasks/gemspec'
|
9
|
+
autoload :Rdoc, 'shoe/tasks/rdoc'
|
10
|
+
autoload :Release, 'shoe/tasks/release'
|
11
|
+
autoload :Resources, 'shoe/tasks/resources'
|
12
|
+
autoload :Shell, 'shoe/tasks/shell'
|
13
|
+
autoload :Shoulda, 'shoe/tasks/shoulda'
|
14
|
+
autoload :Test, 'shoe/tasks/test'
|
15
|
+
|
16
|
+
LOAD_ORDER = %w(
|
17
|
+
Bin
|
18
|
+
Clean
|
19
|
+
Gemspec
|
20
|
+
Rdoc
|
21
|
+
Release
|
22
|
+
Resources
|
23
|
+
Shell
|
24
|
+
Shoulda
|
25
|
+
Test
|
26
|
+
Cucumber
|
27
|
+
Compile
|
28
|
+
)
|
29
|
+
|
30
|
+
def self.each
|
31
|
+
LOAD_ORDER.map { |name| const_get name }.
|
32
|
+
each { |task| yield task }
|
33
|
+
end
|
34
|
+
|
35
|
+
class AbstractTask
|
36
|
+
def self.define(spec)
|
37
|
+
task = new(spec)
|
38
|
+
|
39
|
+
if task.active?
|
40
|
+
task.update_spec
|
41
|
+
task.define
|
42
|
+
end
|
43
|
+
|
44
|
+
task
|
45
|
+
end
|
46
|
+
|
47
|
+
attr_reader :spec
|
48
|
+
|
49
|
+
def initialize(spec)
|
50
|
+
@spec = spec
|
51
|
+
end
|
52
|
+
|
53
|
+
def active?
|
54
|
+
true
|
55
|
+
end
|
56
|
+
|
57
|
+
def define
|
58
|
+
# no-op
|
59
|
+
end
|
60
|
+
|
61
|
+
def update_spec
|
62
|
+
# no-op
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def before(name, dependency)
|
68
|
+
desc Rake::Task[dependency].comment
|
69
|
+
task name => dependency
|
70
|
+
end
|
71
|
+
|
72
|
+
def before_existing(name, dependency)
|
73
|
+
if Rake::Task.task_defined?(name)
|
74
|
+
task name => dependency
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'rubygems/ext'
|
2
|
+
|
3
|
+
module Shoe
|
4
|
+
module Tasks
|
5
|
+
|
6
|
+
class Compile < AbstractTask
|
7
|
+
def active?
|
8
|
+
File.directory?('ext')
|
9
|
+
end
|
10
|
+
|
11
|
+
def define
|
12
|
+
desc 'Compile C extensions'
|
13
|
+
task :compile do
|
14
|
+
top_level_path = File.expand_path('.')
|
15
|
+
destination_path = File.join(top_level_path, spec.require_paths.first)
|
16
|
+
|
17
|
+
spec.extensions.each do |extension|
|
18
|
+
Dir.chdir File.dirname(extension) do
|
19
|
+
Gem::Ext::ExtConfBuilder.build(
|
20
|
+
extension,
|
21
|
+
top_level_path,
|
22
|
+
destination_path,
|
23
|
+
results = []
|
24
|
+
)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
%w(
|
30
|
+
test
|
31
|
+
cucumber:ok
|
32
|
+
cucumber:wip
|
33
|
+
release
|
34
|
+
).each do |name|
|
35
|
+
before_existing(name, :compile)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def update_spec
|
40
|
+
spec.files += Rake::FileList['ext/**/extconf.rb', 'ext/**/*.c']
|
41
|
+
spec.extensions += Rake::FileList['ext/**/extconf.rb']
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Shoe
|
2
|
+
module Tasks
|
3
|
+
|
4
|
+
class Cucumber < AbstractTask
|
5
|
+
def active?
|
6
|
+
File.directory?('features')
|
7
|
+
end
|
8
|
+
|
9
|
+
def define
|
10
|
+
begin
|
11
|
+
require 'cucumber/rake/task'
|
12
|
+
rescue LoadError
|
13
|
+
# no cuke for you
|
14
|
+
else
|
15
|
+
define_tasks
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def update_spec
|
20
|
+
spec.files += Rake::FileList['features/**/*']
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def define_tasks
|
26
|
+
namespace :cucumber do
|
27
|
+
::Cucumber::Rake::Task.new(:ok, 'Run features') do |task|
|
28
|
+
task.cucumber_opts = '--tags ~@wip'
|
29
|
+
end
|
30
|
+
|
31
|
+
::Cucumber::Rake::Task.new(:wip, 'Run work-in-progress features') do |task|
|
32
|
+
task.cucumber_opts = '--tags @wip --wip'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
before(:default, 'cucumber:ok')
|
37
|
+
before(:default, 'cucumber:wip')
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'rubygems/doc_manager'
|
2
|
+
|
3
|
+
module Shoe
|
4
|
+
module Tasks
|
5
|
+
|
6
|
+
class Rdoc < AbstractTask
|
7
|
+
def active?
|
8
|
+
File.directory?('lib')
|
9
|
+
end
|
10
|
+
|
11
|
+
def define
|
12
|
+
desc 'Generate documentation'
|
13
|
+
task :rdoc do
|
14
|
+
LocalDocManager.new(spec).generate_rdoc
|
15
|
+
|
16
|
+
case RUBY_PLATFORM
|
17
|
+
when /darwin/
|
18
|
+
sh 'open rdoc/index.html'
|
19
|
+
when /mswin|mingw/
|
20
|
+
sh 'start rdoc\index.html'
|
21
|
+
else
|
22
|
+
sh 'firefox rdoc/index.html'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def update_spec
|
28
|
+
spec.files += Rake::FileList['**/*.rdoc', 'examples/**/*']
|
29
|
+
|
30
|
+
spec.rdoc_options = %W(
|
31
|
+
--main README.rdoc
|
32
|
+
--title #{spec.full_name}
|
33
|
+
--inline-source
|
34
|
+
)
|
35
|
+
|
36
|
+
spec.extra_rdoc_files += Rake::FileList['**/*.rdoc']
|
37
|
+
|
38
|
+
spec.has_rdoc = true
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
# Using Gem::DocManager instead of Rake::RDocTask means you get to see your
|
44
|
+
# rdoc *exactly* as users who install your gem will.
|
45
|
+
class LocalDocManager < Gem::DocManager #:nodoc:
|
46
|
+
def initialize(spec)
|
47
|
+
@spec = spec
|
48
|
+
@doc_dir = Dir.pwd
|
49
|
+
@rdoc_args = []
|
50
|
+
adjust_spec_so_that_we_can_generate_rdoc_locally
|
51
|
+
end
|
52
|
+
|
53
|
+
def adjust_spec_so_that_we_can_generate_rdoc_locally
|
54
|
+
def @spec.full_gem_path
|
55
|
+
Dir.pwd
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module Shoe
|
2
|
+
module Tasks
|
3
|
+
|
4
|
+
class Release < AbstractTask
|
5
|
+
def active?
|
6
|
+
spec.extend(VersionExtensions)
|
7
|
+
|
8
|
+
spec.has_version_greater_than?('0.0.0') &&
|
9
|
+
there_is_no_tag_for(version_tag(spec.version)) &&
|
10
|
+
we_are_on_the_master_branch
|
11
|
+
end
|
12
|
+
|
13
|
+
def define
|
14
|
+
desc "Release #{spec.full_name}"
|
15
|
+
task :release do
|
16
|
+
File.open("#{spec.name}.gemspec", 'w') do |stream|
|
17
|
+
stream.write(spec.to_ruby)
|
18
|
+
end
|
19
|
+
|
20
|
+
sh "git add #{spec.name}.gemspec"
|
21
|
+
sh "git commit -a -m 'Release #{spec.version}'"
|
22
|
+
sh "git tag #{version_tag(spec.version)}"
|
23
|
+
|
24
|
+
if there_is_no_tag_for('semver')
|
25
|
+
$stderr.puts <<-END.gsub(/^ +/, '')
|
26
|
+
---------------------------------------------
|
27
|
+
SEMANTIC VERSIONING WARNING
|
28
|
+
|
29
|
+
It seems you don't yet have a 'semver' tag.
|
30
|
+
|
31
|
+
Please read more about the emerging consensus
|
32
|
+
around semantic versioning:
|
33
|
+
|
34
|
+
http://semver.org/
|
35
|
+
---------------------------------------------
|
36
|
+
END
|
37
|
+
end
|
38
|
+
|
39
|
+
if there_is_a_remote_called('origin')
|
40
|
+
sh 'git push origin master'
|
41
|
+
sh 'git push --tags origin'
|
42
|
+
end
|
43
|
+
|
44
|
+
sh "gem build #{spec.name}.gemspec"
|
45
|
+
|
46
|
+
if Gem::CommandManager.instance.command_names.include?('push')
|
47
|
+
sh "gem push #{spec.file_name}"
|
48
|
+
else
|
49
|
+
$stderr.puts <<-END.gsub(/^ +/, '')
|
50
|
+
---------------------------------------------
|
51
|
+
GEMCUTTER WARNING
|
52
|
+
|
53
|
+
It seems you don't have gemcutter installed.
|
54
|
+
|
55
|
+
Please `gem install gemcutter` and
|
56
|
+
`gem push #{spec.file_name}`
|
57
|
+
if you would like to make a public release.
|
58
|
+
---------------------------------------------
|
59
|
+
END
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def update_spec
|
65
|
+
spec.files += Rake::FileList['*.gemspec']
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
module VersionExtensions
|
71
|
+
def has_version_greater_than?(string)
|
72
|
+
version > Gem::Version.new(string)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def there_is_a_remote_called(name)
|
77
|
+
`git remote`.to_a.include?("#{name}\n")
|
78
|
+
end
|
79
|
+
|
80
|
+
def there_is_no_tag_for(tag)
|
81
|
+
!`git tag`.to_a.include?("#{tag}\n")
|
82
|
+
end
|
83
|
+
|
84
|
+
def version_tag(version)
|
85
|
+
"v#{spec.version}"
|
86
|
+
end
|
87
|
+
|
88
|
+
def we_are_on_the_master_branch
|
89
|
+
`git symbolic-ref HEAD`.strip == 'refs/heads/master'
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
end
|