rerun 0.6.0 → 0.6.2

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.
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
+