Permalink
Browse files

version 0.1.0

  • Loading branch information...
mordaroso committed Aug 10, 2012
1 parent bc548ba commit 4508be7753ccfb7af0fe898b29b993180fcb1970
View
@@ -0,0 +1,2 @@
+rvm:
+ - 1.9.3
View
@@ -2,3 +2,7 @@ source 'https://rubygems.org'
# Specify your gem's dependencies in guard-motion.gemspec
gemspec
+
+platforms :ruby do
+ gem 'rb-readline'
+end
View
@@ -0,0 +1,9 @@
+# A sample Guardfile
+# More info at https://github.com/guard/guard#readme
+
+guard 'rspec', :version => 2 do
+ watch(%r{^spec/.+_spec\.rb$})
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
+ watch('spec/spec_helper.rb') { "spec" }
+end
+
View
102 README.md
@@ -1,29 +1,99 @@
-# Guard::Motion
+# Guard::Motion [![Build Status](https://secure.travis-ci.org/mordaroso/guard-motion.png?branch=master)](http://travis-ci.org/mordaroso/guard-motion)
-TODO: Write a gem description
+Motion guard allows to automatically & intelligently launch [RubyMotion](http://www.rubymotion.com/) specs when files are modified.
-## Installation
+## Install
-Add this line to your application's Gemfile:
+Please be sure to have [Guard](https://github.com/guard/guard) installed before continue.
- gem 'guard-motion'
+Install the gem:
-And then execute:
+```
+$ gem install guard-motion
+```
- $ bundle
+Add it to your Gemfile (inside development group):
-Or install it yourself as:
+``` ruby
+gem 'guard-motion'
+```
- $ gem install guard-motion
+Add guard definition to your Guardfile by running this command:
+
+```
+$ guard init motion
+```
+
+Make sure Guard::Motion is loaded in your project Rakefile:
+
+```
+require 'guard/motion'
+```
## Usage
-TODO: Write usage instructions here
+Please read [Guard usage doc](https://github.com/guard/guard#readme)
+
+## Guardfile
+
+Motion guard can be really adapted to all kind of project setup.
+
+### Typical RubyMotion App
+
+``` ruby
+guard 'motion' do
+ watch(%r{^spec/.+_spec\.rb$})
+ watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
+end
+```
+
+### Typical RubyMotion library
+
+``` ruby
+guard 'motion' do
+ watch(%r{^spec/.+_spec\.rb$})
+ watch(%r{^lib/[^/]+/(.+)\.rb$}) { |m| "./spec/#{m[1]}_spec.rb" }
+end
+```
+
+Please read [Guard doc](https://github.com/guard/guard#readme) for more information about the Guardfile DSL.
+
+## Options
+
+By default, Guard::Motion will only look for spec files within `spec` in your project root. You can configure Guard::Motion to look in additional paths by using the `:spec_paths` option:
+
+``` ruby
+guard 'motion', :spec_paths => ["spec", "vendor/other_project/spec"] do
+ # ...
+end
+```
+If you have only one path to look, you can configure `:spec_paths` option with a string:
+
+``` ruby
+guard 'motion', :spec_paths => "test" do
+ # ...
+end
+```
+
+### List of available options:
+
+``` ruby
+:bundler => false # use "bundle exec" to run the rake command, default: true
+:binstubs => true # use "bin/rake" to run the rake command (takes precedence over :bundle), default: false
+:notification => false # display Growl (or Libnotify) notification after the specs are done running, default: true
+:all_after_pass => false # run all specs after changed specs pass, default: true
+:all_on_start => false # run all the specs at startup, default: true
+:keep_failed => false # keep failed specs until they pass, default: true
+:spec_paths => ["spec"] # specify an array of paths that contain spec files
+```
+
+You can also use a custom binstubs directory using `:binstubs => 'some-dir'`.
+
+Development
+-----------
-## Contributing
+* Source hosted at [GitHub](https://github.com/mordaroso/guard-motion)
+* Report issues/Questions/Feature requests on [GitHub Issues](https://github.com/mordaroso/guard-motion/issues)
-1. Fork it
-2. Create your feature branch (`git checkout -b my-new-feature`)
-3. Commit your changes (`git commit -am 'Added some feature'`)
-4. Push to the branch (`git push origin my-new-feature`)
-5. Create new Pull Request
+Pull requests are very welcome! Make sure your patches are well tested. Please create a topic branch for every separate change
+you make.
View
@@ -4,11 +4,9 @@ require File.expand_path('../lib/guard/motion/version', __FILE__)
Gem::Specification.new do |gem|
gem.authors = ["mordaroso"]
gem.email = ["mordaroso@gmail.com"]
- gem.description = %q{TODO: Write a gem description}
- gem.summary = %q{TODO: Write a gem summary}
gem.homepage = 'http://rubygems.org/gems/guard-motion'
gem.summary = 'Guard gem for RubyMotion'
- gem.description = 'Guard::Motion automatically runs RubyMotion specs'
+ gem.description = 'Guard::Motion automatically run your specs (much like autotest).'
gem.files = `git ls-files`.split($\)
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
@@ -18,6 +16,7 @@ Gem::Specification.new do |gem|
gem.version = Guard::MotionVersion::VERSION
gem.add_dependency 'guard', '>= 1.1.0'
+ gem.add_dependency 'rake', '>= 0.9'
gem.add_development_dependency 'bundler', '~> 1.1.0'
gem.add_development_dependency 'rspec', '~> 2.10'
View
@@ -0,0 +1,86 @@
+require 'guard'
+require 'guard/guard'
+
+require 'guard/motion/tasks'
+
+module Guard
+ class Motion < Guard
+ autoload :Runner, 'guard/motion/runner'
+
+ # Initialize a Guard.
+ # @param [Array<Guard::Watcher>] watchers the Guard file watchers
+ # @param [Hash] options the custom Guard options
+ def initialize(watchers = [], options = {})
+ super
+ @options = {
+ :all_after_pass => true,
+ :all_on_start => true,
+ :keep_failed => true,
+ :spec_paths => ["spec"]
+ }.merge(options)
+ @last_failed = false
+ @failed_paths = []
+
+ @runner = Runner.new(@options)
+ end
+
+ # Call once when Guard starts. Please override initialize method to init stuff.
+ # @raise [:task_has_failed] when start has failed
+ def start
+ UI.info "Guard::Motion is running"
+ run_all if @options[:all_on_start]
+ end
+
+ # Called when `reload|r|z + enter` is pressed.
+ # This method should be mainly used for "reload" (really!) actions like reloading passenger/spork/bundler/...
+ # @raise [:task_has_failed] when reload has failed
+ def reload
+ @failed_paths = []
+ end
+
+ # Called when just `enter` is pressed
+ # This method should be principally used for long action like running all specs/tests/...
+ # @raise [:task_has_failed] when run_all has failed
+ def run_all
+ passed = @runner.run
+
+ unless @last_failed = !passed
+ @failed_paths = []
+ else
+ throw :task_has_failed
+ end
+ end
+
+ # Called on file(s) modifications that the Guard watches.
+ # @param [Array<String>] paths the changes files or paths
+ # @raise [:task_has_failed] when run_on_change has failed
+ def run_on_changes(paths)
+ paths += @failed_paths if @options[:keep_failed]
+
+ if passed = @runner.run(paths)
+ remove_failed(paths)
+
+ # run all the specs if the run before this one failed
+ if @last_failed && @options[:all_after_pass]
+ @last_failed = false
+ run_all
+ end
+ else
+ @last_failed = true
+ add_failed(paths)
+
+ throw :task_has_failed
+ end
+ end
+
+ private
+ def remove_failed(paths)
+ @failed_paths -= paths if @options[:keep_failed]
+ end
+
+ def add_failed(paths)
+ @failed_paths += paths if @options[:keep_failed]
+ end
+
+ end
+end
View
@@ -0,0 +1,93 @@
+module Guard
+ class Motion
+ class Runner
+
+ def initialize(options = {})
+ @options = {
+ :bundler => true,
+ :binstubs => false,
+ :notification => true,
+ }.merge(options)
+ end
+
+ def run(paths = nil, options = {})
+ if paths.nil?
+ paths = all_spec_paths
+ message = options[:message] || "Running all specs"
+ else
+ message = options[:message] || "Running: #{paths.join(' ')}"
+ end
+
+ UI.info(message, :reset => true)
+
+ run_via_shell rake_command(paths)
+ end
+
+ def rake_executable
+ @rake_executable ||= begin
+ binstubs? ? "#{binstubs}/rake" : 'rake'
+ end
+ end
+
+ def rake_command(paths)
+ cmd_parts = []
+ cmd_parts << "bundle exec" if bundle_exec?
+ cmd_parts << rake_executable
+ cmd_parts << "spec:specific[\"#{paths.join(';')}\"]"
+ cmd_parts.compact.join(' ')
+ end
+
+ def run_via_shell(command)
+ success = system(command)
+
+ if @options[:notification] && !success
+ Notifier.notify("Failed", :title => "Motion spec results", :image => :failed, :priority => 2)
+ end
+
+ success
+ end
+
+ def all_spec_paths
+ @options[:spec_paths].map { |spec_path|
+ Dir.glob("#{spec_path}/**/*_spec.rb")
+ }.flatten
+ end
+
+ def bundler_allowed?
+ if @bundler_allowed.nil?
+ @bundler_allowed = File.exist?("#{Dir.pwd}/Gemfile")
+ else
+ @bundler_allowed
+ end
+ end
+
+ def bundler?
+ if @bundler.nil?
+ @bundler = bundler_allowed? && @options[:bundler]
+ else
+ @bundler
+ end
+ end
+
+ def binstubs?
+ if @binstubs.nil?
+ @binstubs = !!@options[:binstubs]
+ else
+ @binstubs
+ end
+ end
+
+ def binstubs
+ if @options[:binstubs] == true
+ "bin"
+ else
+ @options[:binstubs]
+ end
+ end
+
+ def bundle_exec?
+ bundler? && !binstubs?
+ end
+ end
+ end
+end
View
@@ -0,0 +1,21 @@
+# include rake task spec:specific only if included in a rake file
+if Kernel.const_defined?(:Rake)
+ desc "Run a specific list of motion specs"
+ namespace :spec do
+ task :specific, :files do |task, args|
+ files = args[:files]
+
+ if files.nil? || files.empty?
+ puts "No spec file passed to the task."
+ puts "Please run the task like this: `rake spec:specific[./spec/app_delegate_spec.rb;./spec/other_spec.rb]`"
+ exit 1
+ end
+
+ App.config.spec_mode = true
+ spec_files = App.config.spec_files.select{|file_path| !(file_path =~ /_spec.rb$/)}
+ spec_files += files.split(';')
+ App.config.instance_variable_set("@spec_files", spec_files)
+ Rake::Task["simulator"].invoke
+ end
+ end
+end
@@ -2,8 +2,8 @@ guard 'motion' do
watch(%r{^spec/.+_spec\.rb$})
# RubyMotion App example
- watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
+ watch(%r{^app/(.+)\.rb$}) { |m| "./spec/#{m[1]}_spec.rb" }
# RubyMotion gem example
- watch(%r{^lib/[^/]+/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
+ watch(%r{^lib/[^/]+/(.+)\.rb$}) { |m| "./spec/#{m[1]}_spec.rb" }
end
@@ -1,5 +1,5 @@
module Guard
module MotionVersion
- VERSION = "0.0.1"
+ VERSION = "0.1.0"
end
end
Oops, something went wrong.

0 comments on commit 4508be7

Please sign in to comment.