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