shoe 0.1.13 → 0.2.0

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