rerun 0.7.1 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -55,9 +55,9 @@ to restart when you change a config file like this:
55
55
 
56
56
  Or if you're using Thin to run a Rack app that's configured in config.ru
57
57
  but you want it on port 4000 and in debug mode, and only want to watch
58
- the `app` subdirectory:
58
+ the `app` and `web` subdirectories:
59
59
 
60
- rerun --dir app -- thin start --debug --port=4000 -R config.ru
60
+ rerun --dir app,web -- thin start --debug --port=4000 -R config.ru
61
61
 
62
62
  The `--` is to separate rerun options from cmd options. You can also
63
63
  use a quoted string for the command, e.g.
@@ -104,22 +104,31 @@ Procfile processes locally and restart them all when necessary.
104
104
 
105
105
  # Options:
106
106
 
107
- `--dir` directory to watch (default = ".")
107
+ `--dir` directory (or directories) to watch (default = "."). Separate multiple paths with ','.
108
108
 
109
109
  `--pattern` glob to match inside directory. This uses the Ruby Dir glob style -- see <http://www.ruby-doc.org/core/classes/Dir.html#M002322> for details.
110
110
  By default it watches files ending in: `rb,js,css,scss,sass,erb,html,haml,ru`.
111
111
  It also ignores directories named `.rbx .bundle .git .svn log tmp vendor` and files named `.DS_Store`.
112
112
 
113
+ `--signal` (or -s) use specified signal (instead of the default SIGTERM) to terminate the previous process.
114
+ This may be useful for forcing the respective process to terminate as quickly as possible.
115
+ (`--signal KILL` is the equivalent of `kill -9`)
116
+
113
117
  `--clear` (or -c) clear the screen before each run
114
118
 
115
119
  `--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.
116
120
 
121
+ `--background` (or -b) disable on-the-fly commands, allowing the process to be backgrounded
122
+
123
+ `--no-growl` don't use growl
124
+
117
125
  Also --version and --help, naturally.
118
126
 
119
127
  # Growl Notifications
120
128
 
121
129
  If you have `growlnotify` available on the `PATH`, it sends notifications to
122
- growl in addition to the console.
130
+ growl in addition to the console. If you have growl but don't want rerun to use it,
131
+ set the `--no-growl` option.
123
132
 
124
133
  Download [growlnotify here](http://growl.info/downloads.php#generaldownloads)
125
134
  now that Growl has moved to the App Store.
@@ -132,19 +141,29 @@ While the app is (re)running, you can make things happen by pressing keys:
132
141
  * **c** -- clear the screen
133
142
  * **x** or **q** -- exit (just like control-C)
134
143
 
144
+ # Signals
145
+
146
+ The current algorithm for killing the process is:
147
+
148
+ * send [SIGTERM](http://en.wikipedia.org/wiki/SIGTERM)
149
+ * if that doesn't work after 4 seconds, send SIGINT (aka control-C)
150
+ * if that doesn't work after 2 more seconds, send SIGKILL (aka kill -9)
151
+
152
+ This seems like the most gentle and unixy way of doing things, but it does
153
+ mean that if your program ignores SIGTERM, it takes an extra 4 to 6 seconds to
154
+ restart.
155
+
135
156
  # To Do:
136
157
 
137
158
  * Cooldown (so if a dozen files appear in a burst, say from 'git pull', it only restarts once)
138
159
  * If the last element of the command is a `.ru` file and there's no other command then use `rackup`
139
160
  * Exclude files beginning with a dot, unless the pattern explicitly says to include them
140
- * Allow multiple sets of directories and patterns
141
161
  * --exclude pattern
142
162
  * ".rerun" file to specify options per project or in $HOME.
143
163
  * Test on Linux.
144
164
  * On OS X, use a C library using growl's developer API <http://growl.info/developer/>
145
165
  * Use growl's AppleScript or SDK instead of relying on growlnotify
146
166
  * "Failed" icon
147
- * Get Rails icon working
148
167
  * Figure out an algorithm so "-x" is not needed (if possible)
149
168
  * Specify (or deduce) port to listen for to determine success of a web server launch
150
169
  * Make sure to pass through quoted options correctly to target process [bug]
@@ -152,6 +171,7 @@ While the app is (re)running, you can make things happen by pressing keys:
152
171
  * https://github.com/guard/guard/issues/59
153
172
  * https://github.com/guard/guard/issues/27
154
173
  * Optionally do "bundle install" before and "bundle exec" during launch
174
+
155
175
  # Other projects that do similar things
156
176
 
157
177
  * Restartomatic: <http://github.com/adammck/restartomatic>
@@ -236,9 +256,20 @@ Based upon and/or inspired by:
236
256
  * Jens B <https://github.com/dpree>
237
257
  * Andrés Botero <https://github.com/anbotero>
238
258
  * Dreamcat4
259
+ * <https://github.com/FND>
260
+ * Barry Sia <https://github.com/bsia>
239
261
 
240
262
  # Version History
241
263
 
264
+ * v0.8.0
265
+ * --background option (thanks FND!) to disable the keyboard listener
266
+ * --signal option (thanks FND!)
267
+ * --no-growl option
268
+ * --dir supports multiple directories (thanks Barry!)
269
+
270
+ * v0.7.1
271
+ * bugfix: make rails icon work again
272
+
242
273
  * v0.7.0
243
274
  * uses Listen gem (which uses rb-fsevent for lightweight filesystem snooping)
244
275
 
data/bin/rerun CHANGED
@@ -1,66 +1,12 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'rubygems'
4
-
5
4
  libdir = "#{File.expand_path(File.dirname(File.dirname(__FILE__)))}/lib"
6
5
  $LOAD_PATH.unshift libdir unless $LOAD_PATH.include?(libdir)
7
6
 
8
- load "#{libdir}/../rerun.gemspec" # defines "$spec" variable, which we read the version from
9
-
10
7
  require 'rerun'
11
8
  require 'optparse'
12
9
 
13
- options = {}
14
-
15
- opts = OptionParser.new("", 24, ' ') { |opts|
16
- opts.banner = "Usage: rerun [options] [--] cmd"
17
-
18
- opts.separator ""
19
- opts.separator "Launches an app, and restarts it when the filesystem changes."
20
- opts.separator "See http://github.com/alexch/rerun for more info."
21
- opts.separator ""
22
- opts.separator "Options:"
23
-
24
- opts.on("-d dir", "--dir dir", "directory to watch") do |dir|
25
- options[:dir] = dir
26
- end
27
-
28
- opts.on("-p pattern", "--pattern pattern", "file glob, default = \"#{Rerun::DEFAULT_PATTERN}\"") do |pattern|
29
- options[:pattern] = pattern
30
- end
31
-
32
- opts.on("-c", "--clear", "clear screen before each run") do
33
- options[:clear] = true
34
- end
35
-
36
- opts.on("-x", "--exit", "expect the program to exit. With this option, rerun checks the return value; without it, rerun checks that the process is running.") do |dir|
37
- options[:exit] = true
38
- end
39
-
40
- opts.on_tail("-h", "--help", "--usage", "show this message") do
41
- puts opts
42
- exit
43
- end
44
-
45
- opts.on_tail("--version", "show version") do
46
- puts $spec.version
47
- exit
48
- end
49
-
50
- opts.parse! ARGV
51
- }
52
-
53
- #config = ARGV[0] || "config.ru"
54
- #abort "configuration #{config} not found" unless File.exist? config
55
- #
56
- #if config =~ /\.ru$/ && File.read(config)[/^#\\(.*)/]
57
- # opts.parse! $1.split(/\s+/)
58
- #end
59
-
60
- if ARGV.empty?
61
- puts opts
62
- exit
63
- end
64
-
65
- cmd = ARGV.join(" ")
66
- runner = Rerun::Runner.keep_running(cmd, options)
10
+ options = Rerun::Options.parse
11
+ exit if options.nil?
12
+ runner = Rerun::Runner.keep_running(options[:cmd], options)
data/lib/rerun.rb CHANGED
@@ -2,6 +2,7 @@ here = File.expand_path(File.dirname(__FILE__))
2
2
  $: << here unless $:.include?(here)
3
3
 
4
4
  require "listen" # pull in the Listen gem
5
+ require "rerun/options"
5
6
  require "rerun/system"
6
7
  require "rerun/runner"
7
8
  require "rerun/watcher"
@@ -0,0 +1,79 @@
1
+ require 'optparse'
2
+
3
+ libdir = "#{File.expand_path(File.dirname(File.dirname(__FILE__)))}"
4
+ load "#{libdir}/../rerun.gemspec" # defines "$spec" variable, which we read the version from
5
+
6
+ module Rerun
7
+ class Options
8
+ DEFAULT_PATTERN = "**/*.{rb,js,css,scss,sass,erb,html,haml,ru}"
9
+
10
+ DEFAULTS = {
11
+ :dir => ["."],
12
+ :pattern => DEFAULT_PATTERN,
13
+ :signal => "TERM",
14
+ :growl => true,
15
+ }
16
+
17
+ def self.parse args = ARGV
18
+ options = DEFAULTS.dup
19
+ opts = OptionParser.new("", 24, ' ') do |opts|
20
+ opts.banner = "Usage: rerun [options] [--] cmd"
21
+
22
+ opts.separator ""
23
+ opts.separator "Launches an app, and restarts it when the filesystem changes."
24
+ opts.separator "See http://github.com/alexch/rerun for more info."
25
+ opts.separator "Version: #{$spec.version}"
26
+ opts.separator ""
27
+ opts.separator "Options:"
28
+
29
+ opts.on("-d dir", "--dir dir", "directory to watch, default = \"#{DEFAULTS[:dir]}\". Separate multiple paths with ','.") do |dir|
30
+ options[:dir] = dir.split(",")
31
+ end
32
+
33
+ opts.on("-p pattern", "--pattern pattern", "file glob, default = \"#{DEFAULTS[:pattern]}\"") do |pattern|
34
+ options[:pattern] = pattern
35
+ end
36
+
37
+ opts.on("-s", "--signal signal", "terminate process using this signal, default = \"#{DEFAULTS[:signal]}\"") do |signal|
38
+ options[:signal] = signal
39
+ end
40
+
41
+ opts.on("-c", "--clear", "clear screen before each run") do
42
+ options[:clear] = true
43
+ end
44
+
45
+ opts.on("-x", "--exit", "expect the program to exit. With this option, rerun checks the return value; without it, rerun checks that the process is running.") do |dir|
46
+ options[:exit] = true
47
+ end
48
+
49
+ opts.on("-b", "--background", "disable on-the-fly commands, allowing the process to be backgrounded") do
50
+ options[:background] = true
51
+ end
52
+
53
+ opts.on("--no-growl", "don't use growl") do
54
+ options[:growl] = false
55
+ end
56
+
57
+ opts.on_tail("-h", "--help", "--usage", "show this message") do
58
+ puts opts
59
+ return
60
+ end
61
+
62
+ opts.on_tail("--version", "show version") do
63
+ puts $spec.version
64
+ return
65
+ end
66
+ end
67
+
68
+ if args.empty?
69
+ puts opts
70
+ nil
71
+ else
72
+ opts.parse! args
73
+ options[:cmd] = args.join(" ")
74
+ options
75
+ end
76
+ end
77
+
78
+ end
79
+ end
data/lib/rerun/runner.rb CHANGED
@@ -18,6 +18,8 @@ module Rerun
18
18
  end
19
19
 
20
20
  def start_keypress_thread
21
+ return if @options[:background]
22
+
21
23
  @keypress_thread = Thread.new do
22
24
  while true
23
25
  if c = key_pressed
@@ -59,11 +61,15 @@ module Rerun
59
61
  end
60
62
 
61
63
  def dir
64
+ @options[:dir]
65
+ end
66
+
67
+ def dirs
62
68
  @options[:dir] || "."
63
69
  end
64
70
 
65
71
  def pattern
66
- @options[:pattern] || DEFAULT_PATTERN
72
+ @options[:pattern]
67
73
  end
68
74
 
69
75
  def clear?
@@ -140,7 +146,7 @@ module Rerun
140
146
 
141
147
  unless @watcher
142
148
 
143
- watcher = Watcher.new(:directory => dir, :pattern => pattern) do |changes|
149
+ watcher = Watcher.new(:directory => dirs, :pattern => pattern) do |changes|
144
150
 
145
151
  message = [:modified, :added, :removed].map do |change|
146
152
  count = changes[change].size
@@ -181,12 +187,13 @@ module Rerun
181
187
 
182
188
  # todo: test escalation
183
189
  def stop
190
+ default_signal = @options[:signal] || "TERM"
184
191
  if @pid && (@pid != 0)
185
192
  notify "stopping", "All good things must come to an end." unless @restarting
186
193
  begin
187
194
  timeout(4) do # todo: escalation timeout setting
188
195
  # start with a polite SIGTERM
189
- signal("TERM") && Process.wait(@pid)
196
+ signal(default_signal) && Process.wait(@pid)
190
197
  end
191
198
  rescue Timeout::Error
192
199
  begin
@@ -216,7 +223,7 @@ module Rerun
216
223
  end
217
224
 
218
225
  def notify(title, body)
219
- growl title, body
226
+ growl title, body if @options[:growl]
220
227
  puts
221
228
  say "#{app_name} #{title}"
222
229
  end
data/lib/rerun/system.rb CHANGED
@@ -14,7 +14,7 @@ module Rerun
14
14
  end
15
15
 
16
16
  # do we have growl or not?
17
- def growl?
17
+ def growl_available?
18
18
  mac? && (growlcmd != "")
19
19
  end
20
20
 
@@ -37,7 +37,7 @@ module Rerun
37
37
  end
38
38
 
39
39
  def growl(title, body, background = true)
40
- if growl?
40
+ if growl_available?
41
41
  icon_str = ("--image \"#{icon}\"" if icon)
42
42
  s = "#{growlcmd} -n \"#{app_name}\" -m \"#{body}\" \"#{app_name} #{title}\" #{icon_str}"
43
43
  s += " &" if background
data/lib/rerun/watcher.rb CHANGED
@@ -30,25 +30,33 @@ module Rerun
30
30
  }.merge(options)
31
31
 
32
32
  @pattern = options[:pattern]
33
- @directory = options[:directory]
34
- @directory.chomp!("/")
35
- unless FileTest.exists?(@directory) && FileTest.readable?(@directory)
36
- raise InvalidDirectoryError, "Directory '#{@directory}' either doesnt exist or isnt readable"
37
- end
33
+ @directories = options[:directory]
34
+ @directories = sanitize_dirs(@directories)
38
35
  @priority = options[:priority]
39
36
  @thread = nil
40
37
  end
41
38
 
39
+ def sanitize_dirs(dirs)
40
+ dirs = [*dirs]
41
+ dirs.map do |d|
42
+ d.chomp!("/")
43
+ unless FileTest.exists?(d) && FileTest.readable?(d) && FileTest.directory?(d)
44
+ raise InvalidDirectoryError, "Directory '#{d}' either doesnt exist or isnt readable"
45
+ end
46
+ d
47
+ end
48
+ end
49
+
42
50
  def start
43
51
  if @thread then
44
52
  raise RuntimeError, "already started"
45
53
  end
46
54
 
47
55
  @thread = Thread.new do
48
- # todo: multiple dirs
49
-
50
56
  regexp = Glob.new(@pattern).to_regexp
51
- @listener = Listen::Listener.new(@directory, :filter => regexp) do |modified, added, removed|
57
+ dirs = @directories
58
+ params = dirs << { :filter => regexp }
59
+ @listener = Listen::MultiListener.new(*params) do |modified, added, removed|
52
60
  @client_callback.call(:modified => modified, :added => added, :removed => removed)
53
61
  end
54
62
  @listener.start
data/rerun.gemspec CHANGED
@@ -3,7 +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.7.1'
6
+ s.version = '0.8.0'
7
7
 
8
8
  s.description = "Restarts your app when a file changes. A no-frills, command-line alternative to Guard, Shotgun, Autotest, etc."
9
9
  s.summary = "Launches an app, and restarts it whenever the filesystem changes. A no-frills, command-line alternative to Guard, Shotgun, Autotest, etc."
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rerun
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.1
4
+ version: 0.8.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-07-05 00:00:00.000000000 Z
12
+ date: 2013-01-31 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: listen
@@ -44,6 +44,7 @@ files:
44
44
  - icons/rails_grn_sml.png
45
45
  - icons/rails_red_sml.png
46
46
  - lib/rerun/glob.rb
47
+ - lib/rerun/options.rb
47
48
  - lib/rerun/runner.rb
48
49
  - lib/rerun/system.rb
49
50
  - lib/rerun/watcher.rb
@@ -62,7 +63,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
62
63
  version: '0'
63
64
  segments:
64
65
  - 0
65
- hash: 1349085845198859924
66
+ hash: 3891504021895001236
66
67
  required_rubygems_version: !ruby/object:Gem::Requirement
67
68
  none: false
68
69
  requirements: