kicker 2.1.0 → 2.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.
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)