rerun 0.6.0 → 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -53,6 +53,17 @@ Rackup can also be used to launch a Rack server, so let's try that:
53
53
 
54
54
  rerun -- rackup --port 4000 config.ru
55
55
 
56
+ Want to mimic [autotest](https://github.com/grosser/autotest)? Try
57
+
58
+ rerun -x rake
59
+
60
+ or
61
+
62
+ rerun -cx rspec
63
+
64
+ How about regenerating your HTML files after every change to your [Erector](http://erector.rubyforge.org) widgets?
65
+
66
+ rerun -x erector --to-html my_site.rb
56
67
 
57
68
  # Options:
58
69
 
@@ -63,7 +74,7 @@ By default it watches these files: `rb,js,css,scss,sass,erb,html,haml,ru`.
63
74
 
64
75
  --clear (or -c) clear the screen before each run
65
76
 
66
- --exit (or -x) expect the program to exit. With this option, rerun checks the return value; without it, rerun checks that the process is running.
77
+ --exit (or -x) expect the program to exit. With this option, rerun checks the return value; without it, rerun checks that the launched process is still running.
67
78
 
68
79
  Also --version and --help.
69
80
 
@@ -76,6 +87,9 @@ Also --version and --help.
76
87
  * Test on Linux.
77
88
  * Merge with Kicker (using it as a library and writing a Rerun recipe) or Watchr
78
89
  * On OS X, use a C library using growl's developer API <http://growl.info/developer/>
90
+ * "Failed" icon
91
+ * Get Rails icon working
92
+ * Figure out an algorithm so "-x" is not needed (if possible)
79
93
 
80
94
  # Other projects that do similar things
81
95
 
@@ -139,17 +153,17 @@ Rerun: Alex Chaffee, <mailto:alex@stinky.com>, <http://github.com/alexch/>
139
153
 
140
154
  Based upon and/or inspired by:
141
155
 
142
- Shotgun: <http://github.com/rtomayko/shotgun>
143
-
144
- Rspactor: <http://github.com/mislav/rspactor>
145
- (In turn based on http://rails.aizatto.com/2007/11/28/taming-the-autotest-beast-with-fsevents/ )
146
-
147
- FileSystemWatcher: <http://paulhorman.com/filesystemwatcher/>
156
+ * Shotgun: <http://github.com/rtomayko/shotgun>
157
+ * Rspactor: <http://github.com/mislav/rspactor>
158
+ * (In turn based on http://rails.aizatto.com/2007/11/28/taming-the-autotest-beast-with-fsevents/ )
159
+ * FileSystemWatcher: <http://paulhorman.com/filesystemwatcher/>
148
160
 
149
- Patches by:
161
+ ## Patches by:
150
162
 
151
- David Billskog <billskog@gmail.com>
152
- Jens B <https://github.com/dpree>
163
+ * David Billskog <billskog@gmail.com>
164
+ * Jens B <https://github.com/dpree>
165
+ * Andrés Botero <https://github.com/anbotero>
166
+ * Dreamcat4
153
167
 
154
168
  # License
155
169
 
@@ -7,13 +7,13 @@ module Rerun
7
7
  class OSXWatcher < Rerun::Watcher
8
8
  attr_reader :last_check, :valid_extensions
9
9
  attr_reader :stream
10
-
10
+
11
11
  def start
12
12
  prime
13
13
  timestamp_checked
14
14
 
15
15
  dirs = Array(directories.map{|d| d.dir})
16
-
16
+
17
17
  mac_callback = lambda do |stream, ctx, num_events, paths, marks, event_ids|
18
18
  examine
19
19
  # changed_files = extract_changed_files_from_paths(split_paths(paths, num_events))
data/lib/rerun/runner.rb CHANGED
@@ -22,7 +22,7 @@ module Rerun
22
22
  def pattern
23
23
  @options[:pattern] || DEFAULT_PATTERN
24
24
  end
25
-
25
+
26
26
  def clear?
27
27
  @options[:clear]
28
28
  end
@@ -70,7 +70,7 @@ module Rerun
70
70
  stop # first stop the child
71
71
  exit
72
72
  end
73
-
73
+
74
74
  begin
75
75
  sleep 2
76
76
  rescue Interrupt => e
@@ -84,7 +84,7 @@ module Rerun
84
84
  if status.success?
85
85
  notify "succeeded", ""
86
86
  else
87
- notify "failed", "Exit status #{status.exitstatus}"
87
+ notify "failed", "Exit status #{status.exitstatus}"
88
88
  end
89
89
  else
90
90
  if !running?
@@ -100,7 +100,7 @@ module Rerun
100
100
  watcher = watcher_class.new do
101
101
  restart unless @restarting
102
102
  end
103
- puts "Watching #{dir}/#{pattern}"
103
+ say "Watching #{dir}/#{pattern}"
104
104
  watcher.add_directory(dir, pattern)
105
105
  watcher.sleep_time = 1
106
106
  watcher.start
@@ -126,7 +126,7 @@ module Rerun
126
126
 
127
127
  def stop
128
128
  if @pid && (@pid != 0)
129
- notify "Stopped", "All good things must come to an end." unless @restarting
129
+ notify "stopped", "All good things must come to an end." unless @restarting
130
130
  signal("KILL") && Process.wait(@pid)
131
131
  end
132
132
  rescue => e
@@ -147,7 +147,11 @@ module Rerun
147
147
  def notify(title, body)
148
148
  growl title, body
149
149
  puts
150
- puts "#{Time.now.strftime("%T")} - #{app_name} #{title}"
150
+ say "#{app_name} #{title}"
151
+ end
152
+
153
+ def say msg
154
+ puts "#{Time.now.strftime("%T")} - #{msg}"
151
155
  end
152
156
 
153
157
  end
data/lib/rerun/system.rb CHANGED
@@ -6,7 +6,7 @@ module Rerun
6
6
  RUBY_PLATFORM =~ /darwin/i
7
7
  end
8
8
 
9
- def osx_foundation?
9
+ def osx_foundation?
10
10
  mac? and begin
11
11
  if $osx_foundation.nil?
12
12
  require 'osx/foundation'
@@ -16,7 +16,7 @@ module Rerun
16
16
  $osx_foundation
17
17
  rescue LoadError
18
18
  $osx_foundation = false
19
- end
19
+ end
20
20
  end
21
21
 
22
22
  def windows?
@@ -35,7 +35,7 @@ module Rerun
35
35
  def growlcmd
36
36
  `which growlnotify`.chomp
37
37
  end
38
-
38
+
39
39
  def app_name
40
40
  # todo: make sure this works in non-Mac and non-Unix environments
41
41
  File.expand_path(".").gsub(/^.*\//, '').capitalize
@@ -45,7 +45,7 @@ module Rerun
45
45
  libdir = "#{File.expand_path(File.dirname(File.dirname(__FILE__)))}/lib"
46
46
  $LOAD_PATH.unshift libdir unless $LOAD_PATH.include?(libdir)
47
47
 
48
- rails_sig_file = File.expand_path(".")+"/config/boot.rb"
48
+ rails_sig_file = File.expand_path(".")+"/config/boot.rb"
49
49
  return "#{libdir}/../icons/rails_red_sml.png" if File.exists? rails_sig_file
50
50
  return nil
51
51
  end
@@ -58,6 +58,6 @@ module Rerun
58
58
  `#{s}`
59
59
  end
60
60
  end
61
-
61
+
62
62
  end
63
63
  end
data/lib/rerun/watcher.rb CHANGED
@@ -1,203 +1,203 @@
1
-
2
- Thread.abort_on_exception = true
3
-
4
- # This class will watch a directory or a set of directories and alert you of
5
- # new files, modified files, deleted files.
6
- #
7
- # Author: Paul Horman, http://paulhorman.com/filesystemwatcher/
8
- # Author: Alex Chaffee
9
- module Rerun
10
- class Watcher
11
- CREATED = 0
12
- MODIFIED = 1
13
- DELETED = 2
14
-
15
- attr_accessor :sleep_time, :priority
16
- attr_reader :directories
17
-
18
- def initialize(&client_callback)
19
- @client_callback = client_callback
20
-
21
- @sleep_time = 1
22
- @priority = 0
23
-
24
- @directories = []
25
- @files = []
26
-
27
- @found = nil
28
- @first_time = true
29
- @thread = nil
30
-
31
- end
32
-
33
- # add a directory to be watched
34
- # @param dir the directory to watch
35
- # @param expression the glob pattern to search under the watched directory
36
- def add_directory(dir, expression="**/*")
37
- if FileTest.exists?(dir) && FileTest.readable?(dir) then
38
- @directories << Directory.new(dir, expression)
39
- else
40
- raise InvalidDirectoryError, "Dir '#{dir}' either doesnt exist or isnt readable"
41
- end
42
- end
43
-
44
- def remove_directory(dir)
45
- @directories.delete(dir)
46
- end
47
-
48
- # add a specific file to the watch list
49
- # @param file the file to watch
50
- def add_file(file)
51
- if FileTest.exists?(file) && FileTest.readable?(file) then
52
- @files << file
53
- else
54
- raise InvalidFileError, "File '#{file}' either doesnt exist or isnt readable"
55
- end
56
- end
57
-
58
- def remove_file(file)
59
- @files.delete(file)
60
- end
61
-
62
- def prime
63
- @first_time = true
64
- @found = Hash.new()
65
- examine
66
- @first_time = false
67
- end
68
-
69
- def start
70
- if @thread then
71
- raise RuntimeError, "already started"
72
- end
73
-
74
- prime
75
-
76
- @thread = Thread.new do
77
- while true do
78
- examine
79
- sleep(@sleep_time)
80
- end
81
- end
82
-
83
- @thread.priority = @priority
84
-
85
- at_exit { stop } #?
86
-
87
- end
88
-
89
- # kill the filewatcher thread
90
- def stop
91
- begin
92
- @thread.wakeup
93
- rescue ThreadError => e
94
- # ignore
95
- end
96
- begin
97
- @thread.kill
98
- rescue ThreadError => e
99
- # ignore
100
- end
101
- end
102
-
103
- # wait for the filewatcher to finish
104
- def join
105
- @thread.join() if @thread
106
- rescue Interrupt => e
107
- # don't care
108
- end
109
-
110
- private
111
-
112
- def examine
113
- already_examined = Hash.new()
114
-
115
- @directories.each do |directory|
116
- examine_files(directory.files(), already_examined)
117
- end
118
-
119
- examine_files(@files, already_examined) if not @files.empty?
120
-
121
- # now diff the found files and the examined files to see if
122
- # something has been deleted
123
- all_found_files = @found.keys()
124
- all_examined_files = already_examined.keys()
125
- intersection = all_found_files - all_examined_files
126
- intersection.each do |file_name|
127
- @client_callback.call(DELETED, file_name)
128
- @found.delete(file_name)
129
- end
130
-
131
- end
132
-
133
- # loops over the file list check for new or modified files
134
- def examine_files(files, already_examined)
135
- files.each do |file_name|
136
- # expand the file name to the fully qual path
137
- full_file_name = File.expand_path(file_name)
138
-
139
- # we cant do much if the file isnt readable anyway
140
- if File.readable?(full_file_name) then
141
- already_examined[full_file_name] = true
142
- stat = File.stat(full_file_name)
143
- mod_time = stat.mtime
144
- size = stat.size
145
-
146
- # on the first iteration just load all of the files into the foundList
147
- if @first_time then
148
- @found[full_file_name] = FoundFile.new(full_file_name, mod_time, size)
149
- else
150
- # see if we have found this file already
151
- found_file = @found[full_file_name]
152
- @found[full_file_name] = FoundFile.new(full_file_name, mod_time, size)
153
-
154
- if found_file
155
- if mod_time > found_file.mod_time || size != found_file.size then
156
- @client_callback.call(MODIFIED, full_file_name)
157
- end
158
- else
159
- @client_callback.call(CREATED, full_file_name)
160
- end
161
- end
162
- end
163
- end
164
- end
165
-
166
- class Directory
167
- attr_reader :dir, :expression
168
-
169
- def initialize(dir, expression)
170
- @dir, @expression = dir, expression
171
- @dir.chop! if @dir =~ %r{/$}
172
- end
173
-
174
- def files()
175
- return Dir["#{@dir}/#{@expression}"]
176
- end
177
- end
178
-
179
- class FoundFile
180
- attr_reader :status, :file_name, :mod_time, :size
181
-
182
- def initialize(file_name, mod_time, size)
183
- @file_name, @mod_time, @size = file_name, mod_time, size
184
- end
185
-
186
- def modified(mod_time)
187
- @mod_time = mod_time
188
- end
189
-
190
- def to_s
191
- "FoundFile[file_name=#{file_name}, mod_time=#{mod_time.to_i}, size=#{size}]"
192
- end
193
- end
194
-
195
- # if the directory you want to watch doesnt exist or isn't readable this is thrown
196
- class InvalidDirectoryError < StandardError;
197
- end
198
-
199
- # if the file you want to watch doesnt exist or isn't readable this is thrown
200
- class InvalidFileError < StandardError;
201
- end
202
- end
203
- end
1
+
2
+ Thread.abort_on_exception = true
3
+
4
+ # This class will watch a directory or a set of directories and alert you of
5
+ # new files, modified files, deleted files.
6
+ #
7
+ # Author: Paul Horman, http://paulhorman.com/filesystemwatcher/
8
+ # Author: Alex Chaffee
9
+ module Rerun
10
+ class Watcher
11
+ CREATED = 0
12
+ MODIFIED = 1
13
+ DELETED = 2
14
+
15
+ attr_accessor :sleep_time, :priority
16
+ attr_reader :directories
17
+
18
+ def initialize(&client_callback)
19
+ @client_callback = client_callback
20
+
21
+ @sleep_time = 1
22
+ @priority = 0
23
+
24
+ @directories = []
25
+ @files = []
26
+
27
+ @found = nil
28
+ @first_time = true
29
+ @thread = nil
30
+
31
+ end
32
+
33
+ # add a directory to be watched
34
+ # @param dir the directory to watch
35
+ # @param expression the glob pattern to search under the watched directory
36
+ def add_directory(dir, expression="**/*")
37
+ if FileTest.exists?(dir) && FileTest.readable?(dir) then
38
+ @directories << Directory.new(dir, expression)
39
+ else
40
+ raise InvalidDirectoryError, "Dir '#{dir}' either doesnt exist or isnt readable"
41
+ end
42
+ end
43
+
44
+ def remove_directory(dir)
45
+ @directories.delete(dir)
46
+ end
47
+
48
+ # add a specific file to the watch list
49
+ # @param file the file to watch
50
+ def add_file(file)
51
+ if FileTest.exists?(file) && FileTest.readable?(file) then
52
+ @files << file
53
+ else
54
+ raise InvalidFileError, "File '#{file}' either doesnt exist or isnt readable"
55
+ end
56
+ end
57
+
58
+ def remove_file(file)
59
+ @files.delete(file)
60
+ end
61
+
62
+ def prime
63
+ @first_time = true
64
+ @found = Hash.new()
65
+ examine
66
+ @first_time = false
67
+ end
68
+
69
+ def start
70
+ if @thread then
71
+ raise RuntimeError, "already started"
72
+ end
73
+
74
+ prime
75
+
76
+ @thread = Thread.new do
77
+ while true do
78
+ examine
79
+ sleep(@sleep_time)
80
+ end
81
+ end
82
+
83
+ @thread.priority = @priority
84
+
85
+ at_exit { stop } #?
86
+
87
+ end
88
+
89
+ # kill the filewatcher thread
90
+ def stop
91
+ begin
92
+ @thread.wakeup
93
+ rescue ThreadError => e
94
+ # ignore
95
+ end
96
+ begin
97
+ @thread.kill
98
+ rescue ThreadError => e
99
+ # ignore
100
+ end
101
+ end
102
+
103
+ # wait for the filewatcher to finish
104
+ def join
105
+ @thread.join() if @thread
106
+ rescue Interrupt => e
107
+ # don't care
108
+ end
109
+
110
+ private
111
+
112
+ def examine
113
+ already_examined = Hash.new()
114
+
115
+ @directories.each do |directory|
116
+ examine_files(directory.files(), already_examined)
117
+ end
118
+
119
+ examine_files(@files, already_examined) if not @files.empty?
120
+
121
+ # now diff the found files and the examined files to see if
122
+ # something has been deleted
123
+ all_found_files = @found.keys()
124
+ all_examined_files = already_examined.keys()
125
+ intersection = all_found_files - all_examined_files
126
+ intersection.each do |file_name|
127
+ @client_callback.call(DELETED, file_name)
128
+ @found.delete(file_name)
129
+ end
130
+
131
+ end
132
+
133
+ # loops over the file list check for new or modified files
134
+ def examine_files(files, already_examined)
135
+ files.each do |file_name|
136
+ # expand the file name to the fully qual path
137
+ full_file_name = File.expand_path(file_name)
138
+
139
+ # we cant do much if the file isnt readable anyway
140
+ if File.readable?(full_file_name) then
141
+ already_examined[full_file_name] = true
142
+ stat = File.stat(full_file_name)
143
+ mod_time = stat.mtime
144
+ size = stat.size
145
+
146
+ # on the first iteration just load all of the files into the foundList
147
+ if @first_time then
148
+ @found[full_file_name] = FoundFile.new(full_file_name, mod_time, size)
149
+ else
150
+ # see if we have found this file already
151
+ found_file = @found[full_file_name]
152
+ @found[full_file_name] = FoundFile.new(full_file_name, mod_time, size)
153
+
154
+ if found_file
155
+ if mod_time > found_file.mod_time || size != found_file.size then
156
+ @client_callback.call(MODIFIED, full_file_name)
157
+ end
158
+ else
159
+ @client_callback.call(CREATED, full_file_name)
160
+ end
161
+ end
162
+ end
163
+ end
164
+ end
165
+
166
+ class Directory
167
+ attr_reader :dir, :expression
168
+
169
+ def initialize(dir, expression)
170
+ @dir, @expression = dir, expression
171
+ @dir.chop! if @dir =~ %r{/$}
172
+ end
173
+
174
+ def files()
175
+ return Dir["#{@dir}/#{@expression}"]
176
+ end
177
+ end
178
+
179
+ class FoundFile
180
+ attr_reader :status, :file_name, :mod_time, :size
181
+
182
+ def initialize(file_name, mod_time, size)
183
+ @file_name, @mod_time, @size = file_name, mod_time, size
184
+ end
185
+
186
+ def modified(mod_time)
187
+ @mod_time = mod_time
188
+ end
189
+
190
+ def to_s
191
+ "FoundFile[file_name=#{file_name}, mod_time=#{mod_time.to_i}, size=#{size}]"
192
+ end
193
+ end
194
+
195
+ # if the directory you want to watch doesnt exist or isn't readable this is thrown
196
+ class InvalidDirectoryError < StandardError;
197
+ end
198
+
199
+ # if the file you want to watch doesnt exist or isn't readable this is thrown
200
+ class InvalidFileError < StandardError;
201
+ end
202
+ end
203
+ end
data/rerun.gemspec CHANGED
@@ -3,8 +3,7 @@ $spec = Gem::Specification.new do |s|
3
3
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
4
4
 
5
5
  s.name = 'rerun'
6
- s.version = '0.6.0'
7
- s.date = '2011-05-15'
6
+ s.version = '0.6.2'
8
7
 
9
8
  s.description = "Restarts your app when a file changes"
10
9
  s.summary = "Launches an app, and restarts it whenever the filesystem changes."
metadata CHANGED
@@ -1,24 +1,33 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: rerun
3
- version: !ruby/object:Gem::Version
4
- version: 0.6.0
5
- prerelease:
3
+ version: !ruby/object:Gem::Version
4
+ hash: 3
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 6
9
+ - 2
10
+ version: 0.6.2
6
11
  platform: ruby
7
- authors:
12
+ authors:
8
13
  - Alex Chaffee
9
14
  autorequire:
10
15
  bindir: bin
11
16
  cert_chain: []
12
- date: 2011-05-15 00:00:00.000000000Z
17
+
18
+ date: 2011-05-18 00:00:00 -07:00
19
+ default_executable:
13
20
  dependencies: []
21
+
14
22
  description: Restarts your app when a file changes
15
23
  email: alex@stinky.com
16
- executables:
24
+ executables:
17
25
  - rerun
18
26
  extensions: []
19
- extra_rdoc_files:
27
+
28
+ extra_rdoc_files:
20
29
  - README.md
21
- files:
30
+ files:
22
31
  - README.md
23
32
  - LICENSE
24
33
  - Rakefile
@@ -32,28 +41,39 @@ files:
32
41
  - lib/rerun/runner.rb
33
42
  - lib/rerun/system.rb
34
43
  - lib/rerun/watcher.rb
44
+ has_rdoc: true
35
45
  homepage: http://github.com/alexch/rerun/
36
46
  licenses: []
47
+
37
48
  post_install_message:
38
49
  rdoc_options: []
39
- require_paths:
50
+
51
+ require_paths:
40
52
  - lib
41
- required_ruby_version: !ruby/object:Gem::Requirement
53
+ required_ruby_version: !ruby/object:Gem::Requirement
42
54
  none: false
43
- requirements:
44
- - - ! '>='
45
- - !ruby/object:Gem::Version
46
- version: '0'
47
- required_rubygems_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ hash: 3
59
+ segments:
60
+ - 0
61
+ version: "0"
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
48
63
  none: false
49
- requirements:
50
- - - ! '>='
51
- - !ruby/object:Gem::Version
52
- version: '0'
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ hash: 3
68
+ segments:
69
+ - 0
70
+ version: "0"
53
71
  requirements: []
72
+
54
73
  rubyforge_project: pivotalrb
55
- rubygems_version: 1.8.1
74
+ rubygems_version: 1.3.7
56
75
  signing_key:
57
76
  specification_version: 2
58
77
  summary: Launches an app, and restarts it whenever the filesystem changes.
59
78
  test_files: []
79
+