alloy-kicker 1.9.0 → 1.9.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -35,19 +35,4 @@ And for fun, ghetto-autotest:
35
35
 
36
36
  == Installation
37
37
 
38
- $ sudo gem install alloy-kicker -s http://gems.github.com
39
-
40
- == TODO
41
-
42
- 15:12 sandbags: ideally i would like all events within a small window (e.g. 2s) to be batched into one
43
- 15:12 sandbags: depending upon whether what is being reported is "file X changed" or "some files in directory X" changed
44
- 15:12 sandbags: i forget the granularity FSEvents supports
45
- 15:13 alloy: Yeah the window can be changed, which is a good idea
46
- 15:13 alloy: FSEvents simply reports changes to files in dir X. nothing more
47
- 15:14 sandbags: btw.. what is your rationale for using "!" in method names?
48
- 15:14 alloy: So in this case we should simply keep the time at which an event occurs and then grep the dirs for files with an higher mtime
49
- 15:14 sandbags: works for me
50
- 15:16 alloy: Well the rationale in these cases was either it could raise something (validate) or it would run something external. But really it was just for kicks :)
51
- 15:16 alloy: It could be cleaned up, as I agree it doesn't help much
52
- 15:17 sandbags: i think it would be easy to grok without them
53
- 15:17 alloy: Yeah indeed
38
+ $ sudo gem install alloy-kicker -s http://gems.github.com
data/TODO.rdoc ADDED
@@ -0,0 +1,78 @@
1
+ == For v2
2
+
3
+ * Create 3 callback chains
4
+ * pre-process: for instance Exclude
5
+ * process: normal callbacks
6
+ * post-process: for instance the default 'could not handle' callback
7
+
8
+ * Add -r option to require recipe files that come bundled with Kicker
9
+
10
+ * Probably easier to let the user mutate the files array instead of having to return an array.
11
+
12
+ * Might be best to create an array of Pathname's instead of simply file path strings.
13
+ Probably a subclass of Pathname with some Kicker specific helpers. (relative_path)
14
+
15
+ * Also maybe add an options/attributes hash to the Pathname subclass onto whch the user
16
+ can add arbitrary attributes for if they spread handing over multiple callbacks.
17
+ But this will make callbacks dependent on each-other...
18
+
19
+ * Add example .kick files. E.g.:
20
+ * remove files in specific dirs from the files stack (log, tmp etc)
21
+ * rewrites the paths for a specific app dir layout so that the JS tests are properly picked up.
22
+
23
+ * Add Rails and jstest recipes from our rails app:
24
+
25
+ def relative_path(path)
26
+ path[(Dir.pwd.length + 1)..-1]
27
+ end
28
+
29
+ # Regular Rails mappings
30
+ Kicker.callback = lambda do |kicker, files|
31
+ test_files = []
32
+
33
+ files.delete_if do |file|
34
+ # Match any ruby test file and run it
35
+ if relative_path(file) =~ /^test\/.+_test\.rb$/
36
+ test_files << relative_path(file)
37
+
38
+ # Match any file in app/ and map it to a test file
39
+ elsif match = relative_path(file).match(%r{^app/(\w+)([\w/]*)/([\w\.]+)\.\w+$})
40
+ type, namespace, file = match[1..3]
41
+
42
+ dir = case type
43
+ when "models"
44
+ "unit"
45
+ when "concerns"
46
+ "unit/concerns"
47
+ when "controllers", "views"
48
+ "functional"
49
+ end
50
+
51
+ if dir
52
+ if type == "views"
53
+ namespace = namespace.split('/')[1..-1]
54
+ file = "#{namespace.pop}_controller"
55
+ end
56
+
57
+ test_files << File.join("test", dir, namespace, "#{file}_test.rb")
58
+ end
59
+ end
60
+ end
61
+
62
+ kicker.execute_command "ruby -r #{test_files.join(' -r ')} -e ''" unless test_files.empty?
63
+ files
64
+ end
65
+
66
+ # Match javascript changes and run with HeadlessSquirrel
67
+ Kicker.callback = lambda do |kicker, files|
68
+ test_files = []
69
+
70
+ files.delete_if do |file|
71
+ if relative_path(file) =~ %r{^test/javascripts/(\w+_test)\.(js|html)$}
72
+ test_files << "test/javascripts/#{$1}.html"
73
+ end
74
+ end
75
+
76
+ kicker.execute_command "jstest #{test_files.join(' ')}" unless test_files.empty?
77
+ files
78
+ end
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
2
  :major: 1
3
3
  :minor: 9
4
- :patch: 0
4
+ :patch: 1
data/lib/kicker.rb CHANGED
@@ -40,10 +40,6 @@ class Kicker
40
40
  finished_processing!
41
41
  end
42
42
 
43
- def callback_chain
44
- self.class.callback_chain
45
- end
46
-
47
43
  def start
48
44
  validate_options!
49
45
 
@@ -81,7 +77,7 @@ class Kicker
81
77
 
82
78
  def process(events)
83
79
  unless (files = changed_files(events)).empty?
84
- callback_chain.run(self, files)
80
+ full_chain.call(self, files)
85
81
  finished_processing!
86
82
  end
87
83
  end
@@ -3,19 +3,57 @@ class Kicker
3
3
  alias_method :append_callback, :push
4
4
  alias_method :prepend_callback, :unshift
5
5
 
6
- def run(kicker, files)
6
+ def call(kicker, files)
7
7
  each do |callback|
8
- files = callback.call(kicker, files)
9
- break if !files.is_a?(Array) || files.empty?
8
+ break if files.empty?
9
+ callback.call(kicker, files)
10
10
  end
11
11
  end
12
12
  end
13
13
 
14
- def self.callback_chain
15
- @callback_chain ||= CallbackChain.new
14
+ class << self
15
+ def pre_process_chain
16
+ @pre_process_chain ||= CallbackChain.new
17
+ end
18
+
19
+ def process_chain
20
+ @process_chain ||= CallbackChain.new
21
+ end
22
+
23
+ def post_process_chain
24
+ @post_process_chain ||= CallbackChain.new
25
+ end
26
+
27
+ def full_chain
28
+ @full_chain ||= CallbackChain.new([pre_process_chain, process_chain, post_process_chain])
29
+ end
30
+
31
+ def pre_process_callback=(callback)
32
+ pre_process_chain.append_callback(callback)
33
+ end
34
+
35
+ def process_callback=(callback)
36
+ process_chain.append_callback(callback)
37
+ end
38
+
39
+ def post_process_callback=(callback)
40
+ post_process_chain.prepend_callback(callback)
41
+ end
42
+ end
43
+
44
+ def pre_process_chain
45
+ self.class.pre_process_chain
46
+ end
47
+
48
+ def process_chain
49
+ self.class.process_chain
50
+ end
51
+
52
+ def post_process_chain
53
+ self.class.post_process_chain
16
54
  end
17
55
 
18
- def self.callback=(callback)
19
- callback_chain.prepend_callback(callback)
56
+ def full_chain
57
+ self.class.full_chain
20
58
  end
21
59
  end
@@ -1,7 +1,5 @@
1
- class Kicker
2
- COULD_NOT_HANDLE_CALLBACK = lambda do |kicker, files|
3
- kicker.log("Could not handle: #{files.join(', ')}")
4
- end
5
-
6
- self.callback = COULD_NOT_HANDLE_CALLBACK
1
+ Kicker.post_process_callback = lambda do |kicker, files|
2
+ kicker.log('')
3
+ kicker.log("Could not handle: #{files.join(', ')}")
4
+ kicker.log('')
7
5
  end
@@ -1,7 +1,5 @@
1
- class Kicker
2
- option_parser.on('-e', '--execute [COMMAND]', 'The command to execute.') do |command|
3
- Kicker.callback = lambda do |kicker, _|
4
- kicker.execute_command "sh -c #{command.inspect}"
5
- end
1
+ Kicker.option_parser.on('-e', '--execute [COMMAND]', 'The command to execute.') do |command|
2
+ Kicker.process_callback = lambda do |kicker, _|
3
+ kicker.execute_command "sh -c #{command.inspect}"
6
4
  end
7
5
  end
data/lib/kicker/utils.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  class Kicker
2
2
  def execute_command(command)
3
- log "Change occured. Executing command:"
4
- growl(GROWL_NOTIFICATIONS[:change], 'Kicker: Change occured', 'Executing command') if @use_growl
3
+ log "Change occured, executing command: #{command}"
4
+ growl(GROWL_NOTIFICATIONS[:change], 'Kicker: Change occured, executing command:', command) if @use_growl
5
5
 
6
6
  output = `#{command}`
7
7
  output.strip.split("\n").each { |line| log " #{line}" }
@@ -7,7 +7,7 @@ class Kicker
7
7
  end
8
8
 
9
9
  def validate_paths_and_command!
10
- if callback_chain.length == 1
10
+ if process_chain.empty?
11
11
  puts OPTION_PARSER_CALLBACK.call(nil).help
12
12
  exit
13
13
  end
@@ -1,18 +1,53 @@
1
1
  require File.expand_path('../test_helper', __FILE__)
2
2
 
3
- describe "Kicker, concerning its callback chain" do
4
- it "should return the callback chain instance" do
5
- Kicker.callback_chain.should.be.instance_of Kicker::CallbackChain
3
+ describe "Kicker, concerning its callback chains" do
4
+ before do
5
+ @chains = [:pre_process_chain, :process_chain, :post_process_chain, :full_chain]
6
6
  end
7
7
 
8
- it "should provide a shortcut method which prepends a callback" do
9
- Kicker.callback = lambda { :from_callback }
10
- Kicker.callback_chain.first.call.should == :from_callback
8
+ it "should return the callback chain instances" do
9
+ @chains.each do |chain|
10
+ Kicker.send(chain).should.be.instance_of Kicker::CallbackChain
11
+ end
11
12
  end
12
13
 
13
14
  it "should be accessible by an instance" do
14
15
  kicker = Kicker.new({})
15
- kicker.callback_chain.should.be Kicker.callback_chain
16
+
17
+ @chains.each do |chain|
18
+ kicker.send(chain).should.be Kicker.send(chain)
19
+ end
20
+ end
21
+
22
+ it "should provide a shortcut method which appends a callback to the pre-process chain" do
23
+ Kicker.pre_process_chain.expects(:append_callback).with do |callback|
24
+ callback.call == :from_callback
25
+ end
26
+
27
+ Kicker.pre_process_callback = lambda { :from_callback }
28
+ end
29
+
30
+ it "should provide a shortcut method which appends a callback to the process chain" do
31
+ Kicker.process_chain.expects(:append_callback).with do |callback|
32
+ callback.call == :from_callback
33
+ end
34
+
35
+ Kicker.process_callback = lambda { :from_callback }
36
+ end
37
+
38
+ it "should provide a shortcut method which prepends a callback to the post-process chain" do
39
+ Kicker.post_process_chain.expects(:prepend_callback).with do |callback|
40
+ callback.call == :from_callback
41
+ end
42
+
43
+ Kicker.post_process_callback = lambda { :from_callback }
44
+ end
45
+
46
+ it "should have assigned the chains to the `full_chain'" do
47
+ Kicker.full_chain.length.should == 3
48
+ Kicker.full_chain.each_with_index do |chain, index|
49
+ chain.should.be Kicker.send(@chains[index])
50
+ end
16
51
  end
17
52
  end
18
53
 
@@ -45,7 +80,7 @@ describe "An instance of Kicker::CallbackChain, concerning it's API" do
45
80
  end
46
81
  end
47
82
 
48
- describe "An instance of Kicker::CallbackChain, when running the chain" do
83
+ describe "An instance of Kicker::CallbackChain, when calling the chain" do
49
84
  before do
50
85
  @kicker = Kicker.new({})
51
86
 
@@ -56,48 +91,69 @@ describe "An instance of Kicker::CallbackChain, when running the chain" do
56
91
  it "should call the callbacks from first to last" do
57
92
  @chain.append_callback lambda { @result << 1 }
58
93
  @chain.append_callback lambda { @result << 2 }
59
- @chain.run(@kicker, [])
94
+ @chain.call(@kicker, %w{ file })
60
95
  @result.should == [1, 2]
61
96
  end
62
97
 
63
98
  it "should pass in the Kicker instance with each yield" do
64
99
  kicker = nil
65
100
  @chain.append_callback lambda { |x, _| kicker = x }
66
- @chain.run(@kicker, [])
101
+ @chain.call(@kicker, %w{ file })
67
102
  kicker.should.be @kicker
68
103
  end
69
104
 
70
- it "should pass the files array given to run to the first callback and pass the result array of that call to the next callback and so on" do
105
+ it "should pass the files array given to #call to each callback in the chain" do
106
+ array = %w{ /file/1 }
107
+
71
108
  @chain.append_callback lambda { |_, files|
72
- @result.concat(files)
73
- %w{ /file/3 /file/4 }
109
+ files.should.be array
110
+ files.concat(%w{ /file/2 })
74
111
  }
75
112
 
76
113
  @chain.append_callback lambda { |_, files|
114
+ files.should.be array
77
115
  @result.concat(files)
78
- []
79
116
  }
80
117
 
81
- @chain.run(@kicker, %w{ /file/1 /file/2 })
82
- @result.should == %w{ /file/1 /file/2 /file/3 /file/4 }
118
+ @chain.call(@kicker, array)
119
+ @result.should == %w{ /file/1 /file/2 }
83
120
  end
84
121
 
85
- it "should halt the callback chain once an empty array is returned from a callback" do
86
- @chain.append_callback lambda { @result << 1; [] }
87
- @chain.append_callback lambda { @result << 2 }
88
- @chain.run(@kicker, %w{ /file/1 /file/2 })
122
+ it "should halt the callback chain once the given array is empty" do
123
+ @chain.append_callback lambda { |_, files| @result << 1; files.clear }
124
+ @chain.append_callback lambda { |_, files| @result << 2 }
125
+ @chain.call(@kicker, %w{ /file/1 /file/2 })
89
126
  @result.should == [1]
90
127
  end
91
128
 
92
- it "should halt the callback chain if not an Array instance is returned from a callback" do
93
- [nil, false, ''].each do |object|
94
- @chain.clear
95
- @result.clear
96
-
97
- @chain.append_callback lambda { @result << 1; object }
98
- @chain.append_callback lambda { @result << 2 }
99
- @chain.run(@kicker, %w{ /file/1 /file/2 })
100
- @result.should == [1]
129
+ it "should not call any callback if the given array is empty" do
130
+ @chain.append_callback lambda { |_, files| @result << 1 }
131
+ @chain.call(@kicker, [])
132
+ @result.should == []
133
+ end
134
+
135
+ it "should work with a chain of chains as well" do
136
+ array = %w{ file }
137
+
138
+ kicker_and_files = lambda do |kicker, files|
139
+ kicker.should.be @kicker
140
+ files.should.be array
101
141
  end
142
+
143
+ chain1 = Kicker::CallbackChain.new([
144
+ lambda { |*args| kicker_and_files.call(*args); @result << 1 },
145
+ lambda { |*args| kicker_and_files.call(*args); @result << 2 }
146
+ ])
147
+
148
+ chain2 = Kicker::CallbackChain.new([
149
+ lambda { |*args| kicker_and_files.call(*args); @result << 3 },
150
+ lambda { |*args| kicker_and_files.call(*args); @result << 4 }
151
+ ])
152
+
153
+ @chain.append_callback chain1
154
+ @chain.append_callback chain2
155
+
156
+ @chain.call(@kicker, array)
157
+ @result.should == [1, 2, 3, 4]
102
158
  end
103
159
  end
@@ -40,20 +40,20 @@ describe "Kicker, when a change occurs" do
40
40
  @kicker.send(:changed_files, events).should == [file1, file3]
41
41
  end
42
42
 
43
- it "should run the callback chain with all changed files" do
43
+ it "should call the full_chain with all changed files" do
44
44
  files = %w{ /file/1 /file/2 }
45
45
  events = [event('/file/1'), event('/file/2')]
46
46
 
47
47
  @kicker.expects(:changed_files).with(events).returns(files)
48
- @kicker.callback_chain.expects(:run).with(@kicker, files)
48
+ @kicker.full_chain.expects(:call).with(@kicker, files)
49
49
  @kicker.expects(:finished_processing!)
50
50
 
51
51
  @kicker.send(:process, events)
52
52
  end
53
53
 
54
- it "should not run the callback chain if there were no changed files" do
54
+ it "should not call the full_chain if there were no changed files" do
55
55
  @kicker.stubs(:changed_files).returns([])
56
- @kicker.callback_chain.expects(:run).never
56
+ @kicker.full_chain.expects(:call).never
57
57
  @kicker.expects(:finished_processing!).never
58
58
 
59
59
  @kicker.send(:process, [event()])
@@ -51,9 +51,9 @@ describe "Kicker, when starting" do
51
51
  OSX.stubs(:CFRunLoopRun)
52
52
  end
53
53
 
54
- it "should show the usage banner and exit when there is no extra callback defined" do
54
+ it "should show the usage banner and exit when there is no process_callback defined at all" do
55
55
  @kicker.stubs(:validate_paths_exist!)
56
- Kicker.stubs(:callback_chain).returns([1])
56
+ Kicker.stubs(:process_chain).returns([])
57
57
 
58
58
  Kicker::OPTION_PARSER_CALLBACK.stubs(:call).returns(mock('OptionParser', :help => 'help'))
59
59
  @kicker.expects(:puts).with("help")
@@ -3,7 +3,11 @@ require File.expand_path('../../test_helper', __FILE__)
3
3
  describe "Kicker, concerning the default `could not handle file' callback" do
4
4
  it "should log that it could not handle the given files" do
5
5
  kicker = Kicker.new({})
6
+
7
+ kicker.expects(:log).with('')
6
8
  kicker.expects(:log).with("Could not handle: /file/1, /file/2")
7
- Kicker.callback_chain.last.call(kicker, %w{ /file/1 /file/2 })
9
+ kicker.expects(:log).with('')
10
+
11
+ Kicker.post_process_chain.last.call(kicker, %w{ /file/1 /file/2 })
8
12
  end
9
13
  end
@@ -2,19 +2,19 @@ require File.expand_path('../../test_helper', __FILE__)
2
2
 
3
3
  describe "Kicker, concerning the `execute a command-line' callback" do
4
4
  it "should parse the command and add the callback" do
5
- before = Kicker.callback_chain.length
5
+ before = Kicker.process_chain.length
6
6
 
7
7
  Kicker.parse_options(%w{ -e ls })
8
- Kicker.callback_chain.length.should == before + 1
8
+ Kicker.process_chain.length.should == before + 1
9
9
 
10
10
  Kicker.parse_options(%w{ --execute ls })
11
- Kicker.callback_chain.length.should == before + 2
11
+ Kicker.process_chain.length.should == before + 2
12
12
  end
13
13
 
14
14
  it "should call execute_command with the given command" do
15
15
  Kicker.parse_options(%w{ -e ls })
16
16
 
17
- callback = Kicker.callback_chain.first
17
+ callback = Kicker.process_chain.last
18
18
  callback.should.be.instance_of Proc
19
19
 
20
20
  kicker = Kicker.new({})
data/test/utils_test.rb CHANGED
@@ -17,19 +17,19 @@ describe "A Kicker instance, concerning its utility methods" do
17
17
  it "should log the output of the command indented by 2 spaces and whether or not the command succeeded" do
18
18
  @kicker.stubs(:`).returns("line 1\nline 2")
19
19
 
20
- @kicker.expects(:log).with('Change occured. Executing command:')
20
+ @kicker.expects(:log).with('Change occured, executing command: ls')
21
21
  @kicker.expects(:log).with(' line 1')
22
22
  @kicker.expects(:log).with(' line 2')
23
23
  @kicker.expects(:log).with('Command succeeded')
24
- @kicker.execute_command('')
24
+ @kicker.execute_command('ls')
25
25
 
26
26
  @kicker.stubs(:last_command_succeeded?).returns(false)
27
27
  @kicker.stubs(:last_command_status).returns(123)
28
- @kicker.expects(:log).with('Change occured. Executing command:')
28
+ @kicker.expects(:log).with('Change occured, executing command: ls')
29
29
  @kicker.expects(:log).with(' line 1')
30
30
  @kicker.expects(:log).with(' line 2')
31
31
  @kicker.expects(:log).with('Command failed (123)')
32
- @kicker.execute_command('')
32
+ @kicker.execute_command('ls')
33
33
  end
34
34
 
35
35
  it "should send the Growl messages with the default click callback" do
@@ -40,15 +40,15 @@ describe "A Kicker instance, concerning its utility methods" do
40
40
 
41
41
  OSX::NSWorkspace.sharedWorkspace.expects(:launchApplication).with('Terminal').times(2)
42
42
 
43
- @kicker.expects(:growl).with(Kicker::GROWL_NOTIFICATIONS[:change], 'Kicker: Change occured', 'Executing command')
43
+ @kicker.expects(:growl).with(Kicker::GROWL_NOTIFICATIONS[:change], 'Kicker: Change occured, executing command:', 'ls')
44
44
  @kicker.expects(:growl).with(Kicker::GROWL_NOTIFICATIONS[:succeeded], 'Kicker: Command succeeded', "line 1\nline 2").yields
45
- @kicker.execute_command('')
45
+ @kicker.execute_command('ls')
46
46
 
47
47
  @kicker.stubs(:last_command_succeeded?).returns(false)
48
48
  @kicker.stubs(:last_command_status).returns(123)
49
- @kicker.expects(:growl).with(Kicker::GROWL_NOTIFICATIONS[:change], 'Kicker: Change occured', 'Executing command')
49
+ @kicker.expects(:growl).with(Kicker::GROWL_NOTIFICATIONS[:change], 'Kicker: Change occured, executing command:', 'ls')
50
50
  @kicker.expects(:growl).with(Kicker::GROWL_NOTIFICATIONS[:failed], 'Kicker: Command failed (123)', "line 1\nline 2").yields
51
- @kicker.execute_command('')
51
+ @kicker.execute_command('ls')
52
52
  end
53
53
 
54
54
  it "should send the Growl messages with a click callback which executes the specified growl command when succeeded" do
@@ -61,14 +61,14 @@ describe "A Kicker instance, concerning its utility methods" do
61
61
  @kicker.expects(:system).with('ls -l').times(1)
62
62
  OSX::NSWorkspace.sharedWorkspace.expects(:launchApplication).with('Terminal').times(1)
63
63
 
64
- @kicker.expects(:growl).with(Kicker::GROWL_NOTIFICATIONS[:change], 'Kicker: Change occured', 'Executing command')
64
+ @kicker.expects(:growl).with(Kicker::GROWL_NOTIFICATIONS[:change], 'Kicker: Change occured, executing command:', 'ls')
65
65
  @kicker.expects(:growl).with(Kicker::GROWL_NOTIFICATIONS[:succeeded], 'Kicker: Command succeeded', "line 1\nline 2").yields
66
- @kicker.execute_command('')
66
+ @kicker.execute_command('ls')
67
67
 
68
68
  @kicker.stubs(:last_command_succeeded?).returns(false)
69
69
  @kicker.stubs(:last_command_status).returns(123)
70
- @kicker.expects(:growl).with(Kicker::GROWL_NOTIFICATIONS[:change], 'Kicker: Change occured', 'Executing command')
70
+ @kicker.expects(:growl).with(Kicker::GROWL_NOTIFICATIONS[:change], 'Kicker: Change occured, executing command:', 'ls')
71
71
  @kicker.expects(:growl).with(Kicker::GROWL_NOTIFICATIONS[:failed], 'Kicker: Command failed (123)', "line 1\nline 2").yields
72
- @kicker.execute_command('')
72
+ @kicker.execute_command('ls')
73
73
  end
74
74
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: alloy-kicker
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.9.0
4
+ version: 1.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eloy Duran
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-06-25 00:00:00 -07:00
12
+ date: 2009-06-27 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -27,6 +27,7 @@ files:
27
27
  - LICENSE
28
28
  - README.rdoc
29
29
  - Rakefile
30
+ - TODO.rdoc
30
31
  - VERSION.yml
31
32
  - bin/kicker
32
33
  - lib/kicker.rb