Permalink
Browse files

Self-hosting... hell's YEAH

  • Loading branch information...
1 parent b46943c commit 7826d0ba5a932e59df2845692ccf56a736fcd023 @wycats wycats committed May 13, 2008
Showing with 152 additions and 143 deletions.
  1. +2 −25 Rakefile
  2. +17 −81 Thorfile
  3. +12 −7 bin/thor
  4. +76 −0 lib/thor/tasks.rb
  5. +15 −0 spec/fixtures/task.thor
  6. +30 −30 spec/thor_runner_spec.rb
View
@@ -5,7 +5,7 @@ require 'spec/rake/spectask'
require 'date'
GEM = "thor"
-GEM_VERSION = "0.9.1"
+GEM_VERSION = "0.9.2"
AUTHOR = "Yehuda Katz"
EMAIL = "wycats@gmail.com"
HOMEPAGE = "http://yehudakatz.com"
@@ -34,31 +34,8 @@ Rake::GemPackageTask.new(spec) do |pkg|
pkg.gem_spec = spec
end
-task :default => :spec
-desc "Run the specs"
-Spec::Rake::SpecTask.new do |t|
- t.libs << "spec"
- t.spec_files = FileList["spec/**/*_spec.rb"]
- t.spec_opts << "-fs --color"
-end
-
-desc "Run all examples with RCov"
-Spec::Rake::SpecTask.new('rcov') do |t|
- t.spec_files = FileList['spec/**/*_spec.rb']
- t.rcov = true
- t.rcov_opts = %w( --exclude spec --exclude /Library --exclude /Users --exclude task.thor --exclude lib/getopt.rb)
-end
-
-task :specs => :spec
-
+task :default => :install
desc "install the gem locally"
task :install => [:package] do
sh %{sudo gem install pkg/#{GEM}-#{GEM_VERSION} --no-rdoc --no-ri --no-update-sources}
-end
-
-desc "create a gemspec file"
-task :make_spec do
- File.open("#{GEM}.gemspec", "w") do |file|
- file.puts spec.to_ruby
- end
end
View
@@ -1,17 +1,16 @@
require 'rubygems'
-require 'rake/gempackagetask'
require 'rubygems/specification'
-require 'spec/rake/spectask'
-require 'date'
+require 'thor/tasks'
GEM = "thor"
-GEM_VERSION = "0.9.1"
+GEM_VERSION = "0.9.2"
AUTHOR = "Yehuda Katz"
EMAIL = "wycats@gmail.com"
HOMEPAGE = "http://yehudakatz.com"
SUMMARY = "A gem that maps options to a class"
+PROJECT = "thor"
-spec = Gem::Specification.new do |s|
+SPEC = Gem::Specification.new do |s|
s.name = GEM
s.version = GEM_VERSION
s.platform = Gem::Platform::RUBY
@@ -22,88 +21,25 @@ spec = Gem::Specification.new do |s|
s.author = AUTHOR
s.email = EMAIL
s.homepage = HOMEPAGE
+ s.rubyforge_project = PROJECT
s.require_path = 'lib'
- s.autorequire = GEM
s.bindir = "bin"
s.executables = %w( thor )
s.files = %w(LICENSE README.markdown Rakefile) + Dir.glob("{bin,lib,specs}/**/*")
end
-require "spec"
-
-module Spec
- module Rake
- class SpecTask
- def make_thortask(klass)
- spec_name = name
- lib_path = @lib_path
-
- # Make these available in the closure
- spec_file_list = self.spec_file_list
- ruby_opts = self.ruby_opts
- rcov = self.rcov
- warning = self.warning
- rcov_option_list = self.rcov_option_list
- rcov_dir = self.rcov_dir
- spec_option_list = self.spec_option_list
- out = self.out
- failure_message = self.failure_message
- fail_on_error = self.fail_on_error
-
- lib_path = libs.join(File::PATH_SEPARATOR)
- actual_name = Hash === name ? name.keys.first : name
-
- klass.class_eval do
-
- desc "#{spec_name}", "run specs"
- define_method spec_name do
- unless spec_file_list.empty?
- # ruby [ruby_opts] -Ilib -S rcov [rcov_opts] bin/spec -- examples [spec_opts]
- # or
- # ruby [ruby_opts] -Ilib bin/spec examples [spec_opts]
- cmd = "ruby "
-
- rb_opts = ruby_opts.clone
- rb_opts << "-S rcov" if rcov
- rb_opts << "-w" if warning
- cmd << rb_opts.join(" ")
- cmd << " "
- cmd << rcov_option_list
- cmd << %[ -o "#{rcov_dir}" ] if rcov
- cmd << %Q|"#{`which spec`.chomp}"|
- cmd << " "
- cmd << "-- " if rcov
- cmd << spec_file_list.collect { |fn| %["#{fn}"] }.join(' ')
- cmd << " "
- cmd << spec_option_list
- if out
- cmd << " "
- cmd << %Q| > "#{out}"|
- STDERR.puts "The Spec::Rake::SpecTask#out attribute is DEPRECATED and will be removed in a future version. Use --format FORMAT:WHERE instead."
- end
- if verbose
- puts cmd
- end
- unless system(cmd)
- STDERR.puts failure_message if failure_message
- raise("Command #{cmd} failed") if fail_on_error
- end
- end
- end
-
- end
- end
- end
- end
-end
-
-Spec::Thor = Spec::Rake
-
class Meta < Thor
- Spec::Rake::SpecTask.new do |t|
- t.libs << "spec"
- t.spec_files = FileList["spec/**/*_spec.rb"]
- t.spec_opts << "-fs --color"
- end.make_thortask(self)
+ # Set up standard Thortasks
+ spec_task(Dir["spec/**/*_spec.rb"])
+ spec_task(Dir["spec/**/*_spec.rb"], :name => "rcov", :rcov =>
+ {:exclude => %w(spec /Library /Users task.thor lib/getopt.rb)})
+ install_task
+
+ desc "make_spec", "make a gemspec file"
+ def make_spec
+ File.open("#{GEM}.gemspec", "w") do |file|
+ file.puts SPEC.to_ruby
+ end
+ end
end
View
@@ -1,3 +1,5 @@
+#!/usr/bin/env ruby
+
require "thor"
require "open-uri"
require "fileutils"
@@ -163,12 +165,15 @@ class Thor::Runner < Thor
display_klasses(true)
end
- desc "list [SEARCH]", "list the available thor tasks"
- def list(search = "")
+ desc "list [SEARCH]", "list the available thor tasks (--substring means SEARCH can be anywhere in the module)"
+ method_options :substring => :boolean
+ def list(search = "", options = {})
initialize_thorfiles
- search = /.*#{search}.*/
+ search = ".*#{search}" if options["substring"]
+ search = /^#{search}.*/i
- display_klasses
+ display_klasses(false, Thor.subclasses.select {|k|
+ Thor::Util.constant_to_thor_path(k.name) =~ search})
end
def method_missing(meth, *args)
@@ -185,7 +190,7 @@ class Thor::Runner < Thor
yaml = thor_yaml
klass_str = Thor::Util.to_constant(thor_klass)
- files = yaml.inject([]) { |a,(k,v)| a << v[:filename] if v[:constants].include?(klass_str); a }
+ files = yaml.inject([]) { |a,(k,v)| a << v[:filename] if v[:constants] && v[:constants].include?(klass_str); a }
unless files.empty?
files.each do |f|
@@ -232,8 +237,8 @@ class Thor::Runner < Thor
File.open(yaml_file, "w") {|f| f.puts yaml.to_yaml }
end
- def display_klasses(with_modules = false)
- klasses = Thor.subclasses - [Thor::Runner]
+ def display_klasses(with_modules = false, klasses = Thor.subclasses)
+ klasses = klasses - [Thor::Runner]
if klasses.empty?
puts "No thorfiles available"
View
@@ -0,0 +1,76 @@
+require "thor"
+require "fileutils"
+
+class Thor
+ def self.package_task
+ self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
+ desc "package", "package up the gem"
+ def package
+ FileUtils.mkdir_p(File.join(Dir.pwd, "pkg"))
+ Gem::Builder.new(SPEC).build
+ FileUtils.mv(SPEC.file_name, File.join(Dir.pwd, "pkg", SPEC.file_name))
+ end
+ RUBY
+ end
+
+ def self.install_task
+ package_task
+
+ self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
+ desc "install", "install the gem"
+ def install
+ old_stderr, $stderr = $stderr.dup, File.open("/dev/null", "w")
+ package
+ $stderr = old_stderr
+ system %{sudo gem install pkg/#{GEM}-#{GEM_VERSION} --no-rdoc --no-ri --no-update-sources}
+ end
+ RUBY
+ end
+
+ def self.spec_task(file_list, opts = {})
+ name = opts.delete(:name) || "spec"
+ rcov_dir = opts.delete(:rcov_dir) || "coverage"
+ file_list = file_list.map {|f| %["#{f}"]}.join(" ")
+ verbose = opts.delete(:verbose)
+ opts = {:format => "specdoc", :color => true}.merge(opts)
+
+ rcov_opts = convert_task_options(opts.delete(:rcov) || {})
+ rcov = !rcov_opts.empty?
+ options = convert_task_options(opts)
+
+ if rcov
+ FileUtils.rm_rf(File.join(Dir.pwd, rcov_dir))
+ end
+
+ self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
+ desc("#{name}", "spec task")
+ def #{name}
+ cmd = "ruby "
+ if #{rcov.inspect}
+ cmd << "-S rcov -o #{rcov_dir} #{rcov_opts.inspect[1...-1]} "
+ end
+ cmd << `which spec`.chomp
+ cmd << " -- " if #{rcov.inspect}
+ cmd << " "
+ cmd << #{file_list.inspect}
+ cmd << " "
+ cmd << #{options.inspect}
+ puts cmd if #{verbose.inspect}
+ system(cmd)
+ end
+ RUBY
+ end
+
+ private
+ def self.convert_task_options(opts)
+ opts.map do |key, value|
+ if value == true
+ "--#{key}"
+ elsif value.is_a?(Array)
+ value.map {|v| "--#{key} #{v.inspect}"}.join(" ")
+ else
+ "--#{key} #{value.inspect}"
+ end
+ end.join(" ")
+ end
+end
View
@@ -0,0 +1,15 @@
+# module: randomness
+
+class Amazing < Thor
+ desc "describe NAME", "say that someone is amazing"
+ method_options :forcefully => :boolean
+ def describe(name, opts)
+ ret = "#{name} is amazing"
+ puts opts["forcefully"] ? ret.upcase : ret
+ end
+
+ desc "hello", "say hello"
+ def hello
+ puts "Hello"
+ end
+end
View
@@ -106,45 +106,45 @@ class ThorTask2 < Thor
end
end
-describe Thor::Runner, " update" do
- it "updates existing thor files" do
- original_yaml = {"random" =>
+describe Thor::Runner do
+ before :each do
+ @original_yaml = {"random" =>
{:location => "#{File.dirname(__FILE__)}/fixtures/task.thor", :filename => "4a33b894ffce85d7b412fc1b36f88fe0", :constants => ["Amazing"]}}
- YAML.stub!(:load_file).and_return(original_yaml)
+ File.stub!(:exists?).and_return(true)
+ YAML.stub!(:load_file).and_return(@original_yaml)
- runner = Thor::Runner.allocate
- runner.should_receive(:install).with(original_yaml["random"][:location], {"as" => "random"})
+ @runner = Thor::Runner.allocate
+ end
+
+ describe " update" do
+ it "updates existing thor files" do
+ runner = Thor::Runner.allocate
+ runner.should_receive(:install).with(@original_yaml["random"][:location], {"as" => "random"})
- silence_stdout { runner.initialize("update", ["random"]) }
+ silence_stdout { runner.initialize("update", ["random"]) }
+ end
end
-end
-
-describe Thor::Runner, " uninstall" do
- it "uninstalls existing thor modules" do
- original_yaml = {"random" =>
- {:location => "#{File.dirname(__FILE__)}/fixtures/task.thor", :filename => "4a33b894ffce85d7b412fc1b36f88fe0", :constants => ["Amazing"]}}
- YAML.stub!(:load_file).and_return(original_yaml)
- runner = Thor::Runner.allocate
- runner.should_receive(:save_yaml)
+ describe " uninstall" do
+ it "uninstalls existing thor modules" do
+ @runner.should_receive(:save_yaml)
- File.should_receive(:delete).with(File.join(ENV["HOME"], ".thor", "4a33b894ffce85d7b412fc1b36f88fe0.thor"))
- original_yaml.should_receive(:delete).with("random")
+ File.should_receive(:delete).with(File.join(ENV["HOME"], ".thor", "4a33b894ffce85d7b412fc1b36f88fe0.thor"))
+ @original_yaml.should_receive(:delete).with("random")
- silence_stdout { runner.initialize("uninstall", ["random"])}
+ silence_stdout { @runner.initialize("uninstall", ["random"])}
+ end
end
-end
-describe Thor::Runner, " installed" do
- it "displays the modules installed in a pretty way" do
- Dir.stub!(:[]).and_return([])
-
- runner = Thor::Runner.allocate
-
- stdout = stdout_from { runner.initialize("installed", []) }
- stdout.must =~ /random\s*amazing/
- stdout.must =~ /amazing:describe NAME \[\-\-forcefully\]\s*say that someone is amazing/
- stdout.must =~ /amazing:hello\s*say hello/
+ describe " installed" do
+ it "displays the modules installed in a pretty way" do
+ Dir.stub!(:[]).and_return([])
+
+ stdout = stdout_from { @runner.initialize("installed", []) }
+ stdout.must =~ /random\s*amazing/
+ stdout.must =~ /amazing:describe NAME \[\-\-forcefully\]\s*say that someone is amazing/
+ stdout.must =~ /amazing:hello\s*say hello/
+ end
end
end

0 comments on commit 7826d0b

Please sign in to comment.