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.
@@ -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
@@ -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
@@ -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,14 @@
1
+ module Shoe
2
+ module Tasks
3
+
4
+ class Bin < AbstractTask
5
+ def update_spec
6
+ spec.files += Rake::FileList['bin/*']
7
+ spec.executables += Rake::FileList['bin/*'].map do |path|
8
+ File.basename(path)
9
+ end
10
+ end
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,18 @@
1
+ module Shoe
2
+ module Tasks
3
+
4
+ class Clean < AbstractTask
5
+ def active?
6
+ File.directory?('.git')
7
+ end
8
+
9
+ def define
10
+ desc 'Remove ignored files'
11
+ task :clean do
12
+ sh 'git clean -fdX'
13
+ end
14
+ end
15
+ end
16
+
17
+ end
18
+ 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,14 @@
1
+ module Shoe
2
+ module Tasks
3
+
4
+ class Gemspec < AbstractTask
5
+ def define
6
+ desc 'Show latest gemspec contents'
7
+ task :gemspec do
8
+ puts spec.to_ruby
9
+ end
10
+ end
11
+ end
12
+
13
+ end
14
+ 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