poll-rerun 0.11.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +34 -0
- data/README.md +377 -0
- data/Rakefile +82 -0
- data/bin/rerun +12 -0
- data/icons/rails_grn_sml.png +0 -0
- data/icons/rails_red_sml.png +0 -0
- data/lib/goo.rb +3 -0
- data/lib/rerun/glob.rb +85 -0
- data/lib/rerun/notification.rb +64 -0
- data/lib/rerun/options.rb +124 -0
- data/lib/rerun/runner.rb +339 -0
- data/lib/rerun/system.rb +22 -0
- data/lib/rerun/watcher.rb +130 -0
- data/lib/rerun.rb +15 -0
- data/poll-rerun.gemspec +34 -0
- metadata +78 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: afdc9586c6a6101dea11606085d1d10fc0887d60
|
4
|
+
data.tar.gz: c8129748d4c63516fd44e28c2ff8c728515c788c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4c33ce48a27db3773cd195621f3682d0b3e395d494f939bac3cfcb84155cfa414a2d87f180f7ef82a655f6e26347b93a3a29db387702b79ee798fe7a8a18bca2
|
7
|
+
data.tar.gz: 9b74cab2dae5b506441edfeb8f88b12f3b5768cab495a0b66a108a98fa8d989224fd473c9a9acda0a1678a0394539d61a7423d738313eaa9847888496116b0e7
|
data/LICENSE
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
Rerun
|
2
|
+
Copyright (c) 2009 Alex Chaffee <alex@stinky.com>
|
3
|
+
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
of this software and associated documentation files (the "Software"), to
|
6
|
+
deal in the Software without restriction, including without limitation the
|
7
|
+
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
8
|
+
sell copies of the Software, and to permit persons to whom the Software is
|
9
|
+
furnished to do so, subject to the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be included in
|
12
|
+
all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
17
|
+
THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
18
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
19
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
20
|
+
|
21
|
+
---
|
22
|
+
|
23
|
+
rerun partially based on code from Rspactor
|
24
|
+
Copyright (c) 2009 Mislav Marohnić
|
25
|
+
License as above (MIT open source).
|
26
|
+
|
27
|
+
rerun partially based on code from FileSystemWatcher
|
28
|
+
http://paulhorman.com/filesystemwatcher/
|
29
|
+
No license provided; assumed public domain.
|
30
|
+
|
31
|
+
rerun partially based on code from Shotgun
|
32
|
+
Copyright (c) 2009 Ryan Tomayko <tomayko.com/about>
|
33
|
+
License as above (MIT open source).
|
34
|
+
|
data/README.md
ADDED
@@ -0,0 +1,377 @@
|
|
1
|
+
# Rerun
|
2
|
+
|
3
|
+
This is a fork of the original rerun available here:
|
4
|
+
<http://github.com/alexch/rerun>
|
5
|
+
|
6
|
+
The only difference between this version and the original is the versioning that also includes the `--force-polling` flag.
|
7
|
+
|
8
|
+
Rerun launches your program, then watches the filesystem. If a relevant file
|
9
|
+
changes, then it restarts your program.
|
10
|
+
|
11
|
+
Rerun works for both long-running processes (e.g. apps) and short-running ones
|
12
|
+
(e.g. tests). It's basically a no-frills command-line alternative to Guard,
|
13
|
+
Shotgun, Autotest, etc. that doesn't require config files and works on any
|
14
|
+
command, not just Ruby programs.
|
15
|
+
|
16
|
+
Rerun's advantage is its simple design. Since it uses `exec` and the standard
|
17
|
+
Unix `SIGINT` and `SIGKILL` signals, you're sure the restarted app is really
|
18
|
+
acting just like it was when you ran it from the command line the first time.
|
19
|
+
|
20
|
+
By default it watches files ending in: `rb,js,coffee,css,scss,sass,erb,html,haml,ru,yml,slim,md,feature`.
|
21
|
+
Use the `--pattern` option if you want to change this.
|
22
|
+
|
23
|
+
As of version 0.7.0, we use the Listen gem, which tries to use your OS's
|
24
|
+
built-in facilities for monitoring the filesystem, so CPU use is very light.
|
25
|
+
|
26
|
+
Rerun does not work on Windows. Sorry, but you can't do much relaunching
|
27
|
+
without "fork".
|
28
|
+
|
29
|
+
# Installation:
|
30
|
+
|
31
|
+
gem install rerun
|
32
|
+
|
33
|
+
("sudo" may be required on older systems, but try it without sudo first.)
|
34
|
+
|
35
|
+
If you are using RVM you might want to put this in your global gemset so it's
|
36
|
+
available to all your apps. (There really should be a better way to distinguish
|
37
|
+
gems-as-libraries from gems-as-tools.)
|
38
|
+
|
39
|
+
rvm @global do gem install rerun
|
40
|
+
|
41
|
+
The Listen gem looks for certain platform-dependent gems, and will complain if
|
42
|
+
they're not available. Unfortunately, Rubygems doesn't understand optional
|
43
|
+
dependencies very well, so you may have to install extra gems (and/or put them
|
44
|
+
in your Gemfile) to make Rerun work more smoothly on your system.
|
45
|
+
(Learn more at <https://github.com/guard/listen#listen-adapters>.)
|
46
|
+
For example, on Mac OS X, use
|
47
|
+
|
48
|
+
gem install rb-fsevent
|
49
|
+
|
50
|
+
# Usage:
|
51
|
+
|
52
|
+
rerun [options] [--] cmd
|
53
|
+
|
54
|
+
For example, if you're running a Sinatra app whose main file is `app.rb`:
|
55
|
+
|
56
|
+
rerun ruby app.rb
|
57
|
+
|
58
|
+
If the first part of the command is a `.rb` filename, then `ruby` is
|
59
|
+
optional, so the above can also be accomplished like this:
|
60
|
+
|
61
|
+
rerun app.rb
|
62
|
+
|
63
|
+
Rails doesn't automatically notice all config file changes, so you can force it
|
64
|
+
to restart when you change a config file like this:
|
65
|
+
|
66
|
+
rerun --dir config rails s
|
67
|
+
|
68
|
+
Or if you're using Thin to run a Rack app that's configured in config.ru
|
69
|
+
but you want it on port 4000 and in debug mode, and only want to watch
|
70
|
+
the `app` and `web` subdirectories:
|
71
|
+
|
72
|
+
rerun --dir app,web -- thin start --debug --port=4000 -R config.ru
|
73
|
+
|
74
|
+
The `--` is to separate rerun options from cmd options. You can also
|
75
|
+
use a quoted string for the command, e.g.
|
76
|
+
|
77
|
+
rerun --dir app "thin start --debug --port=4000 -R config.ru"
|
78
|
+
|
79
|
+
Rackup can also be used to launch a Rack server, so let's try that:
|
80
|
+
|
81
|
+
rerun -- rackup --port 4000 config.ru
|
82
|
+
|
83
|
+
Want to mimic [autotest](https://github.com/grosser/autotest)? Try
|
84
|
+
|
85
|
+
rerun -x rake
|
86
|
+
|
87
|
+
or
|
88
|
+
|
89
|
+
rerun -cx rspec
|
90
|
+
|
91
|
+
And if you're using [Spork](https://github.com/sporkrb/spork) with Rails, you
|
92
|
+
need to [restart your spork server](https://github.com/sporkrb/spork/issues/201)
|
93
|
+
whenever certain Rails environment files change, so why not put this in your
|
94
|
+
Rakefile...
|
95
|
+
|
96
|
+
desc "run spork (via rerun)"
|
97
|
+
task :spork do
|
98
|
+
sh "rerun --pattern '{Gemfile,Gemfile.lock,spec/spec_helper.rb,.rspec,spec/factories/**,config/environment.rb,config/environments/test.rb,config/initializers/*.rb,lib/**/*.rb}' -- spork"
|
99
|
+
end
|
100
|
+
|
101
|
+
and start using `rake spork` to launch your spork server?
|
102
|
+
|
103
|
+
(If you're using Guard instead of Rerun, check out
|
104
|
+
[guard-spork](https://github.com/guard/guard-spork)
|
105
|
+
for a similar solution.)
|
106
|
+
|
107
|
+
How about regenerating your HTML files after every change to your
|
108
|
+
[Erector](http://erector.rubyforge.org) widgets?
|
109
|
+
|
110
|
+
rerun -x erector --to-html my_site.rb
|
111
|
+
|
112
|
+
Use Heroku Cedar? `rerun` is now compatible with `foreman`. Run all your
|
113
|
+
Procfile processes locally and restart them all when necessary.
|
114
|
+
|
115
|
+
rerun foreman start
|
116
|
+
|
117
|
+
# Options:
|
118
|
+
|
119
|
+
`--dir` directory (or directories) to watch (default = "."). Separate multiple paths with ',' and/or use multiple `-d` options.
|
120
|
+
|
121
|
+
`--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.
|
122
|
+
By default it watches files ending in: `rb,js,coffee,css,scss,sass,erb,html,haml,ru,yml,slim,md,feature`.
|
123
|
+
On top of this, it also ignores dotfiles, `.tmp` files, and some other files and directories (like `.git` and `log`).
|
124
|
+
Run `rerun --help` to see the actual list.
|
125
|
+
|
126
|
+
`--ignore pattern` file glob to ignore (can be set many times). To ignore a directory, you must append '/*' e.g.
|
127
|
+
`--ignore 'coverage/*'`.
|
128
|
+
|
129
|
+
*On top of --pattern and --ignore, we ignore any changes to files and dirs starting with a dot.*
|
130
|
+
|
131
|
+
`--signal` (or `-s`) use specified signal (instead of the default SIGTERM) to terminate the previous process.
|
132
|
+
This may be useful for forcing the respective process to terminate as quickly as possible.
|
133
|
+
(`--signal KILL` is the equivalent of `kill -9`)
|
134
|
+
|
135
|
+
`--restart` (or `-r`) expect process to restart itself, using signal HUP by default
|
136
|
+
(e.g. `-r -s INT` will send a INT and then resume watching for changes)
|
137
|
+
|
138
|
+
`--clear` (or -c) clear the screen before each run
|
139
|
+
|
140
|
+
`--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.
|
141
|
+
|
142
|
+
`--background` (or -b) disable on-the-fly commands, allowing the process to be backgrounded
|
143
|
+
|
144
|
+
`--notify NOTIFIER` use `growl` or `osx` for notifications (see below)
|
145
|
+
|
146
|
+
`--no-notify` don't use growl (or osx) notifications
|
147
|
+
|
148
|
+
`--name` set the app name (for display)
|
149
|
+
|
150
|
+
`--force-polling` use polling instead of a native filesystem scan (useful for Vagrant)
|
151
|
+
|
152
|
+
Also `--version` and `--help`, naturally.
|
153
|
+
|
154
|
+
# Notifications
|
155
|
+
|
156
|
+
If you have `growlnotify` available on the `PATH`, it sends notifications to
|
157
|
+
growl in addition to the console.
|
158
|
+
If you have `terminal-notifier`, it sends notifications to
|
159
|
+
the OS X notification center in addition to the console.
|
160
|
+
|
161
|
+
If you have both, Rerun will pick one, or you can choose between them using `--notify growl` or `--notify osx` respectively.
|
162
|
+
|
163
|
+
If you have a notifier installed but don't want rerun to use it,
|
164
|
+
set the `--no-notify` option.
|
165
|
+
|
166
|
+
Download [growlnotify here](http://growl.info/downloads.php#generaldownloads)
|
167
|
+
now that Growl has moved to the App Store.
|
168
|
+
|
169
|
+
Install [terminal-notifier](https://github.com/julienXX/terminal-notifier) using `gem install terminal-notifier`. (You may have to put it in your system gemset and/or use `sudo` too.) Using Homebrew to install terminal-notifier is not recommended.
|
170
|
+
|
171
|
+
# On-The-Fly Commands
|
172
|
+
|
173
|
+
While the app is (re)running, you can make things happen by pressing keys:
|
174
|
+
|
175
|
+
* **r** -- restart (as if a file had changed)
|
176
|
+
* **c** -- clear the screen
|
177
|
+
* **x** or **q** -- exit (just like control-C)
|
178
|
+
* **p** -- pause/unpause filesystem watching
|
179
|
+
|
180
|
+
If you're backgrounding or using Pry or a debugger, you might not want these
|
181
|
+
keys to be trapped, so use the `--background` option.
|
182
|
+
|
183
|
+
# Signals
|
184
|
+
|
185
|
+
The current algorithm for killing the process is:
|
186
|
+
|
187
|
+
* send [SIGTERM](http://en.wikipedia.org/wiki/SIGTERM) (or the value of the `--signal` option)
|
188
|
+
* if that doesn't work after 4 seconds, send SIGINT (aka control-C)
|
189
|
+
* if that doesn't work after 2 more seconds, send SIGKILL (aka kill -9)
|
190
|
+
|
191
|
+
This seems like the most gentle and unixy way of doing things, but it does
|
192
|
+
mean that if your program ignores SIGTERM, it takes an extra 4 to 6 seconds to
|
193
|
+
restart.
|
194
|
+
|
195
|
+
# Vagrant and VirtualBox
|
196
|
+
|
197
|
+
If running inside a shared directory using Vagrant and VirtualBox, you must pass the `--force-polling` option. You may also have to pass some extra `--ignore` options too; otherwise each scan can take 10 or more seconds on directories with a large number of files or subdirectories underneath it.
|
198
|
+
|
199
|
+
# Troubleshooting
|
200
|
+
If you are using `zsh` as your shell, and you are specifying your `--pattern` as `**/*.rb`, you may face this error
|
201
|
+
```
|
202
|
+
Errno::EACCES: Permission denied - <filename>
|
203
|
+
```
|
204
|
+
This is because `**/*.rb` gets expanded into the command by `zsh` instead of passing it through to rerun. The solution is to simply quote ('' or "") the pattern.
|
205
|
+
i.e
|
206
|
+
```
|
207
|
+
rerun -p **/*.rb rake test
|
208
|
+
```
|
209
|
+
becomes
|
210
|
+
```
|
211
|
+
rerun -p "**/*.rb" rake test
|
212
|
+
```
|
213
|
+
|
214
|
+
# To Do:
|
215
|
+
|
216
|
+
## Must have for v1.0
|
217
|
+
* ".rerun" file to specify options per project or in $HOME.
|
218
|
+
* Make sure to pass through quoted options correctly to target process [bug]
|
219
|
+
* Optionally do "bundle install" before and "bundle exec" during launch
|
220
|
+
|
221
|
+
## Nice to have
|
222
|
+
* Smarter --signal option (specifying signal to try and a timeout to wait, repeated)
|
223
|
+
* If the last element of the command is a `.ru` file and there's no other command then use `rackup`
|
224
|
+
* Figure out an algorithm so "-x" is not needed (if possible) -- maybe by accepting a "--port" option or reading `config.ru`
|
225
|
+
* Specify (or deduce) port to listen for to determine success of a web server launch
|
226
|
+
* see also [todo.md](todo.md)
|
227
|
+
|
228
|
+
## Wacky Ideas
|
229
|
+
* Make it work on Windows, like Guard now does. See
|
230
|
+
* https://github.com/guard/guard/issues/59
|
231
|
+
* https://github.com/guard/guard/issues/27
|
232
|
+
* On OS X:
|
233
|
+
* use a C library using growl's developer API <http://growl.info/developer/>
|
234
|
+
* Use growl's AppleScript or SDK instead of relying on growlnotify
|
235
|
+
* "Failed" icon for notifications
|
236
|
+
* On Linux:
|
237
|
+
* Use libnotify or notify-send http://www.linuxjournal.com/content/tech-tip-get-notifications-your-scripts-notify-send
|
238
|
+
|
239
|
+
# Other projects that do similar things
|
240
|
+
|
241
|
+
* Restartomatic: <http://github.com/adammck/restartomatic>
|
242
|
+
* Shotgun: <http://github.com/rtomayko/shotgun>
|
243
|
+
* Rack::Reloader middleware: <http://github.com/rack/rack/blob/5ca8f82fb59f0bf0e8fd438e8e91c5acf3d98e44/lib/rack/reloader.rb>
|
244
|
+
* The Sinatra FAQ has a discussion at <http://www.sinatrarb.com/faq.html#reloading>
|
245
|
+
* Kicker: <http://github.com/alloy/kicker/>
|
246
|
+
* Watchr: <https://github.com/mynyml/watchr>
|
247
|
+
* Guard: <http://github.com/guard/guard>
|
248
|
+
* Autotest: <https://github.com/grosser/autotest>
|
249
|
+
|
250
|
+
# Why would I use this instead of Shotgun?
|
251
|
+
|
252
|
+
Shotgun does a "fork" after the web framework has loaded but before
|
253
|
+
your application is loaded. It then loads your app, processes a
|
254
|
+
single request in the child process, then exits the child process.
|
255
|
+
|
256
|
+
Rerun launches the whole app, then when it's time to restart, uses
|
257
|
+
"kill" to shut it down and starts the whole thing up again from
|
258
|
+
scratch.
|
259
|
+
|
260
|
+
So rerun takes somewhat longer than Shotgun to restart the app, but
|
261
|
+
does it much less frequently. And once it's running it behaves more
|
262
|
+
normally and consistently with your production app.
|
263
|
+
|
264
|
+
Also, Shotgun reloads the app on every request, even if it doesn't
|
265
|
+
need to. This is fine if you're loading a single file, but if your web
|
266
|
+
pages all load other files (CSS, JS, media) then that adds up quickly.
|
267
|
+
(I can only assume that the developers of shotgun are using caching or a
|
268
|
+
front web server so this isn't a pain point for them.)
|
269
|
+
|
270
|
+
And hey, does Shotgun reload your Worker processes if you're using Foreman and
|
271
|
+
a Procfile? I'm pretty sure it doesn't.
|
272
|
+
|
273
|
+
YMMV!
|
274
|
+
|
275
|
+
# Why would I use this instead of Rack::Reloader?
|
276
|
+
|
277
|
+
Rack::Reloader is certifiably beautiful code, and is a very elegant use
|
278
|
+
of Rack's middleware architecture. But because it relies on the
|
279
|
+
LOADED_FEATURES variable, it only reloads .rb files that were 'require'd,
|
280
|
+
not 'load'ed. That leaves out (non-Erector) template files, and also,
|
281
|
+
at least the way I was doing it, sub-actions (see
|
282
|
+
[this thread](http://groups.google.com/group/sinatrarb/browse_thread/thread/7329727a9296e96a#
|
283
|
+
)).
|
284
|
+
|
285
|
+
Rack::Reloader also doesn't reload configuration changes or redo other
|
286
|
+
things that happen during app startup. Rerun takes the attitude that if
|
287
|
+
you want to restart an app, you should just restart the whole app. You know?
|
288
|
+
|
289
|
+
# Why would I use this instead of Guard?
|
290
|
+
|
291
|
+
Guard is very powerful but requires some up-front configuration.
|
292
|
+
Rerun is meant as a no-frills command-line alternative requiring no knowledge
|
293
|
+
of Ruby nor config file syntax.
|
294
|
+
|
295
|
+
# Why did you write this?
|
296
|
+
|
297
|
+
I've been using [Sinatra](http://sinatrarb.com) and loving it. In order
|
298
|
+
to simplify their system, the Rat Pack removed auto-reloading from
|
299
|
+
Sinatra proper. I approve of this: a web application framework should be
|
300
|
+
focused on serving requests, not on munging Ruby ObjectSpace for
|
301
|
+
dev-time convenience. But I still wanted automatic reloading during
|
302
|
+
development. Shotgun wasn't working for me (see above) so I spliced
|
303
|
+
Rerun together out of code from Rspactor, FileSystemWatcher, and Shotgun
|
304
|
+
-- with a heavy amount of refactoring and rewriting. In late 2012 I
|
305
|
+
migrated the backend to the Listen gem, which was extracted from Guard,
|
306
|
+
so it should be more reliable and performant on multiple platforms.
|
307
|
+
|
308
|
+
# Credits
|
309
|
+
|
310
|
+
Rerun: [Alex Chaffee](http://alexchaffee.com), <mailto:alex@stinky.com>, <http://github.com/alexch/>
|
311
|
+
|
312
|
+
Based upon and/or inspired by:
|
313
|
+
|
314
|
+
* Shotgun: <http://github.com/rtomayko/shotgun>
|
315
|
+
* Rspactor: <http://github.com/mislav/rspactor>
|
316
|
+
* (In turn based on http://rails.aizatto.com/2007/11/28/taming-the-autotest-beast-with-fsevents/ )
|
317
|
+
* FileSystemWatcher: <http://paulhorman.com/filesystemwatcher/>
|
318
|
+
|
319
|
+
## Patches by:
|
320
|
+
|
321
|
+
* David Billskog <billskog@gmail.com>
|
322
|
+
* Jens B <https://github.com/dpree>
|
323
|
+
* Andrés Botero <https://github.com/anbotero>
|
324
|
+
* Dreamcat4
|
325
|
+
* <https://github.com/FND>
|
326
|
+
* Barry Sia <https://github.com/bsia>
|
327
|
+
* Paul Rangel <https://github.com/ismell>
|
328
|
+
* James Edward Gray II <https://github.com/JEG2>
|
329
|
+
* Raul E Rangel <https://github.com/ismell> and Antonio Terceiro <https://github.com/terceiro>
|
330
|
+
* Mike Pastore <https://github.com/mwpastore>
|
331
|
+
* Andy Duncan <https://github.com/ajduncan>
|
332
|
+
|
333
|
+
# Version History
|
334
|
+
|
335
|
+
*
|
336
|
+
* `--force-polling` option (thanks ajduncan)
|
337
|
+
|
338
|
+
* 0.11.0 7 October 2015
|
339
|
+
* better 'changed' message
|
340
|
+
* `--notify osx` option
|
341
|
+
* `--restart` option (with bugfix by Mike Pastore)
|
342
|
+
* use Listen 3 gem
|
343
|
+
* add `.feature` files to default watchlist (thanks @jmuheim)
|
344
|
+
|
345
|
+
* v0.10.0 4 May 2014
|
346
|
+
* add '.coffee,.slim,.md' to default pattern (thanks @xylinq)
|
347
|
+
* --ignore option
|
348
|
+
|
349
|
+
* v0.9.0 6 March 2014
|
350
|
+
* --dir (or -d) can be specified more than once, for multiple directories (thanks again Barry!)
|
351
|
+
* --name option
|
352
|
+
* press 'p' to pause/unpause filesystem watching (Barry is the man!)
|
353
|
+
* works with Listen 2 (note: needs 2.3 or higher)
|
354
|
+
* cooldown works, thanks to patches to underlying Listen gem
|
355
|
+
* ignore all dotfiles, and add actual list of ignored dirs and files
|
356
|
+
|
357
|
+
* v0.8.2
|
358
|
+
* bugfix, forcing Rerun to use Listen v1.0.3 while we work out the troubles we're having with Listen 1.3 and 2.1
|
359
|
+
|
360
|
+
* v0.8.1
|
361
|
+
* bugfix release (#30 and #34)
|
362
|
+
|
363
|
+
* v0.8.0
|
364
|
+
* --background option (thanks FND!) to disable the keyboard listener
|
365
|
+
* --signal option (thanks FND!)
|
366
|
+
* --no-growl option
|
367
|
+
* --dir supports multiple directories (thanks Barry!)
|
368
|
+
|
369
|
+
* v0.7.1
|
370
|
+
* bugfix: make rails icon work again
|
371
|
+
|
372
|
+
* v0.7.0
|
373
|
+
* uses Listen gem (which uses rb-fsevent for lightweight filesystem snooping)
|
374
|
+
|
375
|
+
# License
|
376
|
+
|
377
|
+
Open Source MIT License. See "LICENSE" file.
|
data/Rakefile
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/clean'
|
3
|
+
require 'rake/testtask'
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
|
6
|
+
task :default => [:spec]
|
7
|
+
task :test => :spec
|
8
|
+
|
9
|
+
desc "Run all specs"
|
10
|
+
RSpec::Core::RakeTask.new('spec') do |t|
|
11
|
+
ENV['ENV'] = "test"
|
12
|
+
t.pattern = 'spec/**/*_spec.rb'
|
13
|
+
t.rspec_opts = ['--color']
|
14
|
+
end
|
15
|
+
|
16
|
+
$rubyforge_project = 'pivotalrb'
|
17
|
+
|
18
|
+
$spec =
|
19
|
+
begin
|
20
|
+
require 'rubygems/specification'
|
21
|
+
data = File.read('rerun.gemspec')
|
22
|
+
spec = nil
|
23
|
+
#Thread.new { spec = eval("$SAFE = 3\n#{data}") }.join
|
24
|
+
spec = eval data
|
25
|
+
spec
|
26
|
+
end
|
27
|
+
|
28
|
+
def package(ext='')
|
29
|
+
"pkg/#{$spec.name}-#{$spec.version}" + ext
|
30
|
+
end
|
31
|
+
|
32
|
+
desc 'Exit if git is dirty'
|
33
|
+
task :check_git do
|
34
|
+
state = `git status 2> /dev/null | tail -n1`
|
35
|
+
clean = (state =~ /working directory clean/)
|
36
|
+
unless clean
|
37
|
+
warn "can't do that on an unclean git dir"
|
38
|
+
exit 1
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
desc 'Build packages'
|
43
|
+
task :package => %w[.gem .tar.gz].map { |e| package(e) }
|
44
|
+
|
45
|
+
desc 'Build and install as local gem'
|
46
|
+
task :install => package('.gem') do
|
47
|
+
sh "gem install #{package('.gem')}"
|
48
|
+
end
|
49
|
+
|
50
|
+
directory 'pkg/'
|
51
|
+
CLOBBER.include('pkg')
|
52
|
+
|
53
|
+
file package('.gem') => %W[pkg/ #{$spec.name}.gemspec] + $spec.files do |f|
|
54
|
+
sh "gem build #{$spec.name}.gemspec"
|
55
|
+
mv File.basename(f.name), f.name
|
56
|
+
end
|
57
|
+
|
58
|
+
file package('.tar.gz') => %w[pkg/] + $spec.files do |f|
|
59
|
+
cmd = <<-SH
|
60
|
+
git archive \
|
61
|
+
--prefix=#{$spec.name}-#{$spec.version}/ \
|
62
|
+
--format=tar \
|
63
|
+
HEAD | gzip > #{f.name}
|
64
|
+
SH
|
65
|
+
sh cmd.gsub(/ +/, ' ')
|
66
|
+
end
|
67
|
+
|
68
|
+
desc 'Publish gem and tarball to rubyforge'
|
69
|
+
task 'release' => [:check_git, package('.gem'), package('.tar.gz')] do |t|
|
70
|
+
puts "Releasing #{$spec.version}"
|
71
|
+
sh "gem push #{package('.gem')}"
|
72
|
+
puts "Tagging and pushing"
|
73
|
+
sh "git tag v#{$spec.version}"
|
74
|
+
sh "git push && git push --tags"
|
75
|
+
end
|
76
|
+
|
77
|
+
desc 'download github issues and pull requests'
|
78
|
+
task 'github' do
|
79
|
+
%w(issues pulls).each do |type|
|
80
|
+
sh "curl -o #{type}.json https://api.github.com/repos/alexch/rerun/#{type}"
|
81
|
+
end
|
82
|
+
end
|
data/bin/rerun
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
libdir = "#{File.expand_path(File.dirname(File.dirname(__FILE__)))}/lib"
|
5
|
+
$LOAD_PATH.unshift libdir unless $LOAD_PATH.include?(libdir)
|
6
|
+
|
7
|
+
require 'rerun'
|
8
|
+
require 'optparse'
|
9
|
+
|
10
|
+
options = Rerun::Options.parse
|
11
|
+
exit if options.nil?
|
12
|
+
runner = Rerun::Runner.keep_running(options[:cmd], options)
|
Binary file
|
Binary file
|
data/lib/goo.rb
ADDED
data/lib/rerun/glob.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
# based on http://cpan.uwinnipeg.ca/htdocs/Text-Glob/Text/Glob.pm.html#glob_to_regex_string-
|
2
|
+
|
3
|
+
# todo: release as separate gem
|
4
|
+
#
|
5
|
+
module Rerun
|
6
|
+
class Glob
|
7
|
+
NO_LEADING_DOT = '(?=[^\.])' # todo
|
8
|
+
START_OF_FILENAME = '(\A|\/)' # beginning of string or a slash
|
9
|
+
END_OF_STRING = '\z'
|
10
|
+
|
11
|
+
def initialize glob_string
|
12
|
+
@glob_string = glob_string
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_regexp_string
|
16
|
+
chars = @glob_string.split('')
|
17
|
+
|
18
|
+
chars = smoosh(chars)
|
19
|
+
|
20
|
+
curlies = 0
|
21
|
+
escaping = false
|
22
|
+
string = chars.map do |char|
|
23
|
+
if escaping
|
24
|
+
escaping = false
|
25
|
+
char
|
26
|
+
else
|
27
|
+
case char
|
28
|
+
when '**'
|
29
|
+
"([^/]+/)*"
|
30
|
+
when '*'
|
31
|
+
".*"
|
32
|
+
when "?"
|
33
|
+
"."
|
34
|
+
when "."
|
35
|
+
"\\."
|
36
|
+
|
37
|
+
when "{"
|
38
|
+
curlies += 1
|
39
|
+
"("
|
40
|
+
when "}"
|
41
|
+
if curlies > 0
|
42
|
+
curlies -= 1
|
43
|
+
")"
|
44
|
+
else
|
45
|
+
char
|
46
|
+
end
|
47
|
+
when ","
|
48
|
+
if curlies > 0
|
49
|
+
"|"
|
50
|
+
else
|
51
|
+
char
|
52
|
+
end
|
53
|
+
when "\\"
|
54
|
+
escaping = true
|
55
|
+
"\\"
|
56
|
+
|
57
|
+
else
|
58
|
+
char
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end.join
|
63
|
+
START_OF_FILENAME + string + END_OF_STRING
|
64
|
+
end
|
65
|
+
|
66
|
+
def to_regexp
|
67
|
+
Regexp.new(to_regexp_string)
|
68
|
+
end
|
69
|
+
|
70
|
+
def smoosh chars
|
71
|
+
out = []
|
72
|
+
until chars.empty?
|
73
|
+
char = chars.shift
|
74
|
+
if char == "*" and chars.first == "*"
|
75
|
+
chars.shift
|
76
|
+
chars.shift if chars.first == "/"
|
77
|
+
out.push("**")
|
78
|
+
else
|
79
|
+
out.push(char)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
out
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# todo: unit tests
|
2
|
+
|
3
|
+
module Rerun
|
4
|
+
class Notification
|
5
|
+
include System
|
6
|
+
|
7
|
+
attr_reader :title, :body, :options
|
8
|
+
|
9
|
+
def initialize(title, body, options = Options::DEFAULTS.dup)
|
10
|
+
@title = title
|
11
|
+
@body = body
|
12
|
+
@options = options
|
13
|
+
end
|
14
|
+
|
15
|
+
def command
|
16
|
+
return unless mac?
|
17
|
+
|
18
|
+
# todo: strategy or subclass
|
19
|
+
|
20
|
+
s = nil
|
21
|
+
|
22
|
+
if options[:notify] == true or options[:notify] == "growl"
|
23
|
+
if (cmd = command_named("growlnotify"))
|
24
|
+
# todo: check version of growlnotify and warn if it's too old
|
25
|
+
icon_str = ("--image \"#{icon}\"" if icon)
|
26
|
+
s = "#{cmd} -n \"#{app_name}\" -m \"#{body}\" \"#{app_name} #{title}\" #{icon_str}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
if s.nil? and options[:notify] == true or options[:notify] == "osx"
|
31
|
+
if (cmd = command_named("terminal-notifier"))
|
32
|
+
icon_str = ("-appIcon \"#{icon}\"" if icon)
|
33
|
+
s = "#{cmd} -title \"#{app_name}\" -message \"#{body}\" \"#{app_name} #{title}\" #{icon_str}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
s
|
38
|
+
end
|
39
|
+
|
40
|
+
def command_named(name)
|
41
|
+
path = `which #{name}`.chomp
|
42
|
+
path.empty? ? nil : path
|
43
|
+
end
|
44
|
+
|
45
|
+
def send(background = true)
|
46
|
+
return unless command
|
47
|
+
`#{command}#{" &" if background}`
|
48
|
+
end
|
49
|
+
|
50
|
+
def app_name
|
51
|
+
options[:name]
|
52
|
+
end
|
53
|
+
|
54
|
+
def icon
|
55
|
+
"#{icon_dir}/rails_red_sml.png" if rails?
|
56
|
+
end
|
57
|
+
|
58
|
+
def icon_dir
|
59
|
+
here = File.expand_path(File.dirname(__FILE__))
|
60
|
+
File.expand_path("#{here}/../../icons")
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|