kicker 2.1.0 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. data/.gitignore +10 -0
  2. data/.kick +37 -0
  3. data/README.rdoc +24 -21
  4. data/Rakefile +0 -1
  5. data/TODO.rdoc +4 -34
  6. data/VERSION +1 -0
  7. data/html/images/kikker.jpg +0 -0
  8. data/kicker.gemspec +106 -0
  9. data/lib/kicker.rb +46 -60
  10. data/lib/kicker/callback_chain.rb +4 -4
  11. data/lib/kicker/core_ext.rb +9 -1
  12. data/lib/kicker/growl.rb +54 -19
  13. data/lib/kicker/log_status_helper.rb +38 -0
  14. data/lib/kicker/options.rb +59 -34
  15. data/lib/kicker/recipes.rb +58 -0
  16. data/lib/kicker/recipes/could_not_handle_file.rb +5 -3
  17. data/lib/kicker/recipes/dot_kick.rb +17 -5
  18. data/lib/kicker/recipes/execute_cli_command.rb +1 -1
  19. data/lib/kicker/recipes/ignore.rb +8 -6
  20. data/lib/kicker/recipes/jstest.rb +7 -5
  21. data/lib/kicker/recipes/rails.rb +108 -43
  22. data/lib/kicker/recipes/ruby.rb +155 -0
  23. data/lib/kicker/utils.rb +36 -32
  24. data/test/callback_chain_test.rb +1 -1
  25. data/test/core_ext_test.rb +15 -5
  26. data/test/filesystem_change_test.rb +1 -1
  27. data/test/growl_test.rb +85 -0
  28. data/test/initialization_test.rb +25 -56
  29. data/test/log_status_helper_test.rb +56 -0
  30. data/test/options_test.rb +50 -12
  31. data/test/recipes/could_not_handle_file_test.rb +10 -0
  32. data/test/recipes/dot_kick_test.rb +1 -5
  33. data/test/recipes/execute_cli_command_test.rb +3 -3
  34. data/test/recipes/ignore_test.rb +1 -1
  35. data/test/recipes/jstest_test.rb +1 -1
  36. data/test/recipes/rails_test.rb +118 -18
  37. data/test/recipes/ruby_test.rb +154 -0
  38. data/test/recipes_test.rb +39 -0
  39. data/test/test_helper.rb +1 -1
  40. data/test/utils_test.rb +103 -48
  41. metadata +19 -6
  42. data/VERSION.yml +0 -4
  43. data/lib/kicker/validate.rb +0 -24
@@ -0,0 +1,10 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ rdoc
5
+ pkg
6
+ html/*.html
7
+ html/*.rid
8
+ html/*.css
9
+ html/classes
10
+ html/files
data/.kick ADDED
@@ -0,0 +1,37 @@
1
+ recipe :ignore
2
+ recipe :ruby
3
+
4
+ process do |files|
5
+ test_files = files.take_and_map do |file|
6
+ case file
7
+ when %r{^lib/kicker(\.rb|/validate\.rb|/growl\.rb)$}
8
+ ["test/initialization_test.rb", ("test/filesystem_change_test.rb" if $1 == '.rb')]
9
+ when %r{^lib/kicker/(.+)\.rb$}
10
+ "test/#{$1}_test.rb"
11
+ end
12
+ end
13
+
14
+ Ruby.run_tests test_files
15
+ end
16
+
17
+ process do |files|
18
+ execute("rake docs:generate && open -a Safari html/index.html") if files.delete("README.rdoc")
19
+ end
20
+
21
+ startup do
22
+ log "Good choice mate!"
23
+ end
24
+
25
+ # process do
26
+ # execute "ls -l" do |status|
27
+ # if status.before?
28
+ # status.stdout? ? "Here we go!: #{status.command}" : "Here we go! GROWL"
29
+ # elsif status.after?
30
+ # if status.success?
31
+ # status.stdout? ? "Nice!\n\n#{status.output}" : "Nice!"
32
+ # else
33
+ # status.stdout? ? "Damn brow!\n\n#{status.output}" : "Damn bro!"
34
+ # end
35
+ # end
36
+ # end
37
+ # end
@@ -11,21 +11,22 @@ feel offended; live with it.</i>
11
11
 
12
12
  == Installation
13
13
 
14
- $ sudo gem install kicker -s http://gemcutter.org
14
+ $ gem install kicker -s http://gemcutter.org
15
15
 
16
16
  == The short version
17
17
 
18
- Usage: kicker [options] [paths to watch]
19
- -e, --execute [COMMAND] The command to execute.
18
+ Usage: ./bin/kicker [options] [paths to watch]
19
+
20
+ Available recipes: active_record, ignore, jstest, rails, ruby.
21
+
22
+ -s, --silent Keep output to a minimum.
20
23
  --[no-]growl Whether or not to use Growl. Default is to use growl.
21
24
  --growl-command [COMMAND] The command to execute when the Growl succeeded message is clicked.
22
- -l, --latency [FLOAT] The time to collect file change events before acting on them. Defaults to 1.5 sec.
25
+ -l, --latency [FLOAT] The time to collect file change events before acting on them. Defaults to 1 second.
23
26
  -r, --recipe [NAME] A named recipe to load.
27
+ -e, --execute [COMMAND] The command to execute.
28
+ -b, --ruby [PATH] Use an alternate Ruby binary for spawned test runners. (Default is `ruby')
24
29
 
25
- Available recipes:
26
- - ignore
27
- - jstest
28
- - rails
29
30
 
30
31
  == The long version
31
32
 
@@ -55,9 +56,10 @@ the <tt>rails</tt> recipe will map models, concerns, controllers, helpers, and
55
56
  views to their respective test files. These will then all be ran with Ruby.
56
57
 
57
58
  A few recipes come shipped with Kicker:
59
+ * Typical Ruby library.
58
60
  * Ruby on Rails, as aforementioned.
59
- * JavaScript tests, needs
60
- HeadlessSquirrel[http://github.com/Fingertips/Headless-squirrel] to run.
61
+ * JavaScript tests, to run it needs
62
+ HeadlessSquirrel[http://github.com/Fingertips/Headless-squirrel].
61
63
  * Ignore, ignores logs, tmp, and svn and git files.
62
64
 
63
65
  Add your own shared recipes to <tt>~/.kick</tt>.
@@ -111,7 +113,7 @@ be added:
111
113
  end
112
114
  end
113
115
 
114
- run_ruby_tests test_files
116
+ Ruby.run_tests test_files
115
117
  end
116
118
 
117
119
  The files list is iterated over with the Array#take_and_map method, which both
@@ -119,23 +121,24 @@ removes and maps the results. This is an easy way to do a common thing in
119
121
  recipes. See Kicker::ArrayExt for details.
120
122
 
121
123
  The handler then checks if the file is a mailer view and if so runs the
122
- mailers test case. The <tt>run_ruby_tests</tt> runs them with the following
124
+ mailers test case. Ruby.run_tests runs them with something like the following
123
125
  command:
124
126
 
125
127
  execute "ruby -r #{test_files.join(' -r ')} -e ''" unless test_files.empty?
126
128
 
127
129
  See Kernel for more info on the utility methods.
128
130
 
129
- ==== Addendum
131
+ To load recipes from your <tt>~/.kick</tt> file:
130
132
 
131
- The recipes directory that ships with Kicker and <tt>~/.kick</tt> are both
132
- added to the load path, so any recipes can be required. Once they’re required
133
- they are added to the callback chains.
134
-
135
- As an example, say you might want to ignore files in <tt>./data</tt>:
136
-
137
- require 'ignore'
133
+ recipe :ignore
138
134
  ignore(/^data\//)
139
135
 
140
136
  That’s basically it, just remember that the order of specifying handlers _can_
141
- be important in your decision on where to specify handlers.
137
+ be important in your decision on where to specify handlers.
138
+
139
+ == Contributors
140
+
141
+ * Manfred Stienstra (@manfred)
142
+ * Cristi Balan (@evilchelu)
143
+ * Damir Zekic (@sidonath)
144
+ * Adam Keys (@therealadam)
data/Rakefile CHANGED
@@ -11,7 +11,6 @@ begin
11
11
  gem.email = "eloy.de.enige@gmail.com"
12
12
  gem.homepage = "http://github.com/alloy/kicker"
13
13
  gem.authors = ["Eloy Duran"]
14
- gem.executables << 'kicker'
15
14
  gem.files.concat FileList['vendor/**/*']
16
15
  gem.require_paths = ["lib", "vendor"]
17
16
  gem.has_rdoc = true
data/TODO.rdoc CHANGED
@@ -1,35 +1,5 @@
1
+ * Move larger parts of README to the GitHub wiki so the README is to the point.
1
2
  * Add a recipe which implements the basic autotest mapping API.
2
- * Need to figure out how this can occur:
3
-
4
- [Thu Oct 01 17:21:04 +0200 2009] Could not handle: tmp/_variants/banners/bn, tmp/_variants/banners/bn/85, tmp/_variants/banners/bn/85/kz, tmp/_variants/banners/bn/85/kz/44, tmp/_variants/images/zx, tmp/_variants/images/zx/10, tmp/_variants/images/zx/10/nx, tmp/_variants/images/zx/10/nx/71
5
- [Thu Oct 01 17:21:04 +0200 2009]
6
- [Thu Oct 01 17:21:05 +0200 2009]
7
- [Thu Oct 01 17:21:05 +0200 2009] Could not handle: tmp/_variants, tmp/_variants/review_photos, tmp/_variants/review_photos/kh, tmp/_variants/review_photos/kh/57, tmp/_variants/review_photos/kh/57/ll, tmp/_variants/review_photos/kh/57/ll/40
8
- [Thu Oct 01 17:21:05 +0200 2009]
9
- [Thu Oct 01 17:21:15 +0200 2009]
10
- [Thu Oct 01 17:21:15 +0200 2009] Could not handle: tmp/_variants, tmp/_variants/flyers, tmp/_variants/flyers/rx, tmp/_variants/flyers/rx/84, tmp/_variants/flyers/rx/84/mc, tmp/_variants/flyers/rx/84/mc/22
11
- [Thu Oct 01 17:21:15 +0200 2009]
12
- [Thu Oct 01 17:21:16 +0200 2009]
13
- [Thu Oct 01 17:21:16 +0200 2009] Could not handle: tmp/_variants, tmp/_variants/images, tmp/_variants/images/mr, tmp/_variants/images/mr/36, tmp/_variants/images/mr/36/as, tmp/_variants/images/mr/36/as/85
14
- [Thu Oct 01 17:21:16 +0200 2009]
15
- [Thu Oct 01 17:21:17 +0200 2009]
16
- [Thu Oct 01 17:21:17 +0200 2009] Could not handle: tmp/_variants/images/zm/86/ez/68
17
- [Thu Oct 01 17:21:17 +0200 2009]
18
- [Thu Oct 01 17:21:19 +0200 2009]
19
- [Thu Oct 01 17:21:19 +0200 2009] Could not handle: tmp/_variants, tmp/_variants/review_photos, tmp/_variants/review_photos/xd, tmp/_variants/review_photos/xd/81, tmp/_variants/review_photos/xd/81/wd, tmp/_variants/review_photos/xd/81/wd/97
20
- [Thu Oct 01 17:21:19 +0200 2009]
21
- /Library/Ruby/Gems/1.8/gems/kicker-2.0.2/lib/kicker.rb:115:in `files_in_directory': undefined method `map' for nil:NilClass (NoMethodError)
22
- from /Library/Ruby/Gems/1.8/gems/kicker-2.0.2/lib/kicker.rb:110:in `changed_files'
23
- from /Library/Ruby/Gems/1.8/gems/kicker-2.0.2/lib/kicker.rb:109:in `map'
24
- from /Library/Ruby/Gems/1.8/gems/kicker-2.0.2/lib/kicker.rb:109:in `changed_files'
25
- from /Library/Ruby/Gems/1.8/gems/kicker-2.0.2/lib/kicker.rb:102:in `process'
26
- from /Library/Ruby/Gems/1.8/gems/kicker-2.0.2/lib/kicker.rb:88:in `run_watch_dog!'
27
- from /Library/Ruby/Gems/1.8/gems/kicker-2.0.2/vendor/rucola/fsevents.rb:112:in `call'
28
- from /Library/Ruby/Gems/1.8/gems/kicker-2.0.2/vendor/rucola/fsevents.rb:112:in `initialize'
29
- from /Library/Ruby/Gems/1.8/gems/kicker-2.0.2/lib/kicker.rb:81:in `call'
30
- from /Library/Ruby/Gems/1.8/gems/kicker-2.0.2/lib/kicker.rb:81:in `CFRunLoopRun'
31
- from /Library/Ruby/Gems/1.8/gems/kicker-2.0.2/lib/kicker.rb:81:in `start'
32
- from /Library/Ruby/Gems/1.8/gems/kicker-2.0.2/lib/kicker.rb:35:in `run'
33
- from /Library/Ruby/Gems/1.8/gems/kicker-2.0.2/bin/kicker:5
34
- from /usr/bin/kicker:19:in `load'
35
- from /usr/bin/kicker:19
3
+ * Make the loggers, stdout and growl, work in a chain so one can add others.
4
+ This should improve portability as well, as people can easily insert growl
5
+ alternatives for their platform.
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 2.2.0
Binary file
@@ -0,0 +1,106 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{kicker}
8
+ s.version = "2.2.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Eloy Duran"]
12
+ s.date = %q{2009-11-29}
13
+ s.default_executable = %q{kicker}
14
+ s.email = %q{eloy.de.enige@gmail.com}
15
+ s.executables = ["kicker"]
16
+ s.extra_rdoc_files = [
17
+ "LICENSE",
18
+ "README.rdoc"
19
+ ]
20
+ s.files = [
21
+ ".gitignore",
22
+ ".kick",
23
+ "LICENSE",
24
+ "README.rdoc",
25
+ "Rakefile",
26
+ "TODO.rdoc",
27
+ "VERSION",
28
+ "bin/kicker",
29
+ "html/images/kikker.jpg",
30
+ "kicker.gemspec",
31
+ "lib/kicker.rb",
32
+ "lib/kicker/callback_chain.rb",
33
+ "lib/kicker/core_ext.rb",
34
+ "lib/kicker/growl.rb",
35
+ "lib/kicker/log_status_helper.rb",
36
+ "lib/kicker/options.rb",
37
+ "lib/kicker/recipes.rb",
38
+ "lib/kicker/recipes/could_not_handle_file.rb",
39
+ "lib/kicker/recipes/dot_kick.rb",
40
+ "lib/kicker/recipes/execute_cli_command.rb",
41
+ "lib/kicker/recipes/ignore.rb",
42
+ "lib/kicker/recipes/jstest.rb",
43
+ "lib/kicker/recipes/rails.rb",
44
+ "lib/kicker/recipes/ruby.rb",
45
+ "lib/kicker/utils.rb",
46
+ "test/callback_chain_test.rb",
47
+ "test/core_ext_test.rb",
48
+ "test/filesystem_change_test.rb",
49
+ "test/fixtures/a_file_thats_reloaded.rb",
50
+ "test/growl_test.rb",
51
+ "test/initialization_test.rb",
52
+ "test/log_status_helper_test.rb",
53
+ "test/options_test.rb",
54
+ "test/recipes/could_not_handle_file_test.rb",
55
+ "test/recipes/dot_kick_test.rb",
56
+ "test/recipes/execute_cli_command_test.rb",
57
+ "test/recipes/ignore_test.rb",
58
+ "test/recipes/jstest_test.rb",
59
+ "test/recipes/rails_test.rb",
60
+ "test/recipes/ruby_test.rb",
61
+ "test/recipes_test.rb",
62
+ "test/test_helper.rb",
63
+ "test/utils_test.rb",
64
+ "vendor/growlnotifier/growl.rb",
65
+ "vendor/growlnotifier/growl.rb",
66
+ "vendor/growlnotifier/growl_helpers.rb",
67
+ "vendor/growlnotifier/growl_helpers.rb",
68
+ "vendor/rucola/fsevents.rb",
69
+ "vendor/rucola/fsevents.rb"
70
+ ]
71
+ s.homepage = %q{http://github.com/alloy/kicker}
72
+ s.rdoc_options = ["--charset=UTF-8"]
73
+ s.require_paths = ["lib", "vendor"]
74
+ s.rubygems_version = %q{1.3.5}
75
+ s.summary = %q{A lean, agnostic, flexible file-change watcher, using OS X FSEvents.}
76
+ s.test_files = [
77
+ "test/callback_chain_test.rb",
78
+ "test/core_ext_test.rb",
79
+ "test/filesystem_change_test.rb",
80
+ "test/fixtures/a_file_thats_reloaded.rb",
81
+ "test/growl_test.rb",
82
+ "test/initialization_test.rb",
83
+ "test/log_status_helper_test.rb",
84
+ "test/options_test.rb",
85
+ "test/recipes/could_not_handle_file_test.rb",
86
+ "test/recipes/dot_kick_test.rb",
87
+ "test/recipes/execute_cli_command_test.rb",
88
+ "test/recipes/ignore_test.rb",
89
+ "test/recipes/jstest_test.rb",
90
+ "test/recipes/rails_test.rb",
91
+ "test/recipes/ruby_test.rb",
92
+ "test/recipes_test.rb",
93
+ "test/test_helper.rb",
94
+ "test/utils_test.rb"
95
+ ]
96
+
97
+ if s.respond_to? :specification_version then
98
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
99
+ s.specification_version = 3
100
+
101
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
102
+ else
103
+ end
104
+ else
105
+ end
106
+ end
@@ -4,89 +4,67 @@ require 'rucola/fsevents'
4
4
  require 'kicker/callback_chain'
5
5
  require 'kicker/core_ext'
6
6
  require 'kicker/growl'
7
+ require 'kicker/log_status_helper'
7
8
  require 'kicker/options'
8
9
  require 'kicker/utils'
9
- require 'kicker/validate'
10
-
11
- RECIPES_DIR = File.expand_path('../kicker/recipes', __FILE__)
12
- $:.unshift RECIPES_DIR
13
- require 'could_not_handle_file'
14
- require 'execute_cli_command'
15
-
16
- USER_RECIPES_DIR = File.expand_path('~/.kick')
17
- $:.unshift USER_RECIPES_DIR if File.exist?(USER_RECIPES_DIR)
18
10
 
19
11
  class Kicker #:nodoc:
20
- class << self
21
- attr_accessor :latency
22
-
23
- def latency
24
- @latency ||= 1
25
- end
26
-
27
- def paths
28
- @paths ||= %w{ . }
29
- end
30
-
31
- def run(argv = ARGV)
32
- options = parse_options(argv)
33
- load_recipes(options[:recipes]) if options[:recipes]
34
- load_dot_kick
35
- new(options).start
36
- end
37
-
38
- private
39
-
40
- def load_dot_kick
41
- if File.exist?('.kick')
42
- require 'dot_kick'
43
- ReloadDotKick.save_state
44
- load '.kick'
45
- end
46
- end
47
-
48
- def load_recipes(recipes)
49
- recipes.each do |recipe|
50
- raise "Recipe `#{recipe}' does not exist." unless recipe_exists?(recipe)
51
- require recipe
52
- end
53
- end
54
-
55
- def recipe_exists?(recipe)
56
- File.exist?("#{RECIPES_DIR}/#{recipe}.rb") || File.exist?("#{USER_RECIPES_DIR}/#{recipe}.rb")
57
- end
12
+ def self.run(argv = ARGV)
13
+ Kicker::Options.parse(argv)
14
+ new.start
58
15
  end
59
16
 
60
- attr_reader :latency, :paths, :last_event_processed_at
17
+ attr_reader :last_event_processed_at
61
18
 
62
- def initialize(options)
63
- @paths = (options[:paths] ? options[:paths] : Kicker.paths).map { |path| File.expand_path(path) }
64
- @latency = options[:latency] || self.class.latency
65
-
66
- self.class.use_growl = options[:growl]
67
- self.class.growl_command = options[:growl_command]
68
-
19
+ def initialize
69
20
  finished_processing!
70
21
  end
71
22
 
23
+ def paths
24
+ @paths ||= Kicker.paths.map { |path| File.expand_path(path) }
25
+ end
26
+
72
27
  def start
73
28
  validate_options!
74
29
 
75
- log "Watching for changes on: #{@paths.join(', ')}"
30
+ log "Watching for changes on: #{paths.join(', ')}"
76
31
  log ''
77
32
 
78
33
  run_watch_dog!
79
- start_growl! if self.class.use_growl
80
- startup_chain.call([], false)
34
+ Kicker::Growl.start! if Kicker::Growl.use?
35
+ run_startup_chain
81
36
 
82
37
  OSX.CFRunLoopRun
83
38
  end
84
39
 
85
40
  private
86
41
 
42
+ def validate_options!
43
+ validate_paths_and_command!
44
+ validate_paths_exist!
45
+ end
46
+
47
+ def validate_paths_and_command!
48
+ if startup_chain.empty?
49
+ puts Kicker::Options.parser.help
50
+ exit
51
+ end
52
+ end
53
+
54
+ def validate_paths_exist!
55
+ paths.each do |path|
56
+ unless File.exist?(path)
57
+ puts "The given path `#{path}' does not exist"
58
+ exit 1
59
+ end
60
+ end
61
+ end
62
+
87
63
  def run_watch_dog!
88
64
  dirs = @paths.map { |path| File.directory?(path) ? path : File.dirname(path) }
89
- watch_dog = Rucola::FSEvents.start_watching(dirs, :latency => @latency) { |events| process(events) }
65
+ watch_dog = Rucola::FSEvents.start_watching(dirs, :latency => self.class.latency) do |events|
66
+ process events
67
+ end
90
68
 
91
69
  trap('INT') do
92
70
  log "Exiting…"
@@ -95,6 +73,10 @@ class Kicker #:nodoc:
95
73
  end
96
74
  end
97
75
 
76
+ def run_startup_chain
77
+ startup_chain.call([], false)
78
+ end
79
+
98
80
  def finished_processing!
99
81
  @last_event_processed_at = Time.now
100
82
  end
@@ -135,4 +117,8 @@ class Kicker #:nodoc:
135
117
  end
136
118
  end
137
119
  end
138
- end
120
+ end
121
+
122
+ # Load this as last, because it actually loads all recipes, so everything has
123
+ # to be defined before that.
124
+ require 'kicker/recipes'
@@ -1,5 +1,5 @@
1
1
  class Kicker
2
- class CallbackChain < Array
2
+ class CallbackChain < Array #:nodoc:
3
3
  alias_method :append_callback, :push
4
4
  alias_method :prepend_callback, :unshift
5
5
 
@@ -60,9 +60,9 @@ class Kicker
60
60
  end
61
61
 
62
62
  module Kernel
63
- # Adds a handler to the startup chain. This chain is ran before the once
64
- # Kicker is done loading. Note that an empty files array is given to the
65
- # callback.
63
+ # Adds a handler to the startup chain. This chain is ran once Kicker is done
64
+ # loading _before_ starting the normal operations. Note that an empty files
65
+ # array is given to the callback.
66
66
  #
67
67
  # Takes a +callback+ object that responds to <tt>#call</tt>, or a block.
68
68
  def startup(callback = nil, &block)