pax_global_header00006660000000000000000000000064126052235170014515gustar00rootroot0000000000000052 comment=724ba37104ca644e632403da406d3beab1821b20 rerun-0.11.0/000077500000000000000000000000001260522351700127275ustar00rootroot00000000000000rerun-0.11.0/.gitignore000066400000000000000000000000371260522351700147170ustar00rootroot00000000000000.idea pkg Gemfile.lock doc tmp rerun-0.11.0/.rspec000066400000000000000000000000371260522351700140440ustar00rootroot00000000000000--color --format=documentation rerun-0.11.0/.travis.yml000066400000000000000000000001101260522351700150300ustar00rootroot00000000000000--- language: ruby rvm: - 2.0.0 - 2.2.0 sudo: false cache: bundler rerun-0.11.0/Gemfile000066400000000000000000000005021260522351700142170ustar00rootroot00000000000000source 'https://rubygems.org' gemspec # :ruby = Unix Rubies (OSX, Linux) # but rb-fsevent is OSX-only, so how to distinguish between OSX and Linux? platform :ruby do gem 'rb-fsevent', '>= 0.9.3' end group :development do gem "rake", '>= 0.10' end group :test do gem 'rspec', ">=3.0" gem 'wrong', ">=0.6.2" end rerun-0.11.0/LICENSE000066400000000000000000000026551260522351700137440ustar00rootroot00000000000000Rerun Copyright (c) 2009 Alex Chaffee Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --- rerun partially based on code from Rspactor Copyright (c) 2009 Mislav Marohnić License as above (MIT open source). rerun partially based on code from FileSystemWatcher http://paulhorman.com/filesystemwatcher/ No license provided; assumed public domain. rerun partially based on code from Shotgun Copyright (c) 2009 Ryan Tomayko License as above (MIT open source). rerun-0.11.0/README.md000066400000000000000000000342211260522351700142100ustar00rootroot00000000000000# Rerun Rerun launches your program, then watches the filesystem. If a relevant file changes, then it restarts your program. Rerun works for both long-running processes (e.g. apps) and short-running ones (e.g. tests). It's basically a no-frills command-line alternative to Guard, Shotgun, Autotest, etc. that doesn't require config files and works on any command, not just Ruby programs. Rerun's advantage is its simple design. Since it uses `exec` and the standard Unix `SIGINT` and `SIGKILL` signals, you're sure the restarted app is really acting just like it was when you ran it from the command line the first time. By default it watches files ending in: `rb,js,coffee,css,scss,sass,erb,html,haml,ru,yml,slim,md,feature`. Use the `--pattern` option if you want to change this. As of version 0.7.0, we use the Listen gem, which tries to use your OS's built-in facilities for monitoring the filesystem, so CPU use is very light. Rerun does not work on Windows. Sorry, but you can't do much relaunching without "fork". # Installation: gem install rerun ("sudo" may be required on older systems, but try it without sudo first.) If you are using RVM you might want to put this in your global gemset so it's available to all your apps. (There really should be a better way to distinguish gems-as-libraries from gems-as-tools.) rvm @global do gem install rerun The Listen gem looks for certain platform-dependent gems, and will complain if they're not available. Unfortunately, Rubygems doesn't understand optional dependencies very well, so you may have to install extra gems (and/or put them in your Gemfile) to make Rerun work more smoothly on your system. (Learn more at .) For example, on Mac OS X, use gem install rb-fsevent # Usage: rerun [options] [--] cmd For example, if you're running a Sinatra app whose main file is `app.rb`: rerun ruby app.rb If the first part of the command is a `.rb` filename, then `ruby` is optional, so the above can also be accomplished like this: rerun app.rb Rails doesn't automatically notice all config file changes, so you can force it to restart when you change a config file like this: rerun --dir config rails s Or if you're using Thin to run a Rack app that's configured in config.ru but you want it on port 4000 and in debug mode, and only want to watch the `app` and `web` subdirectories: rerun --dir app,web -- thin start --debug --port=4000 -R config.ru The `--` is to separate rerun options from cmd options. You can also use a quoted string for the command, e.g. rerun --dir app "thin start --debug --port=4000 -R config.ru" Rackup can also be used to launch a Rack server, so let's try that: rerun -- rackup --port 4000 config.ru Want to mimic [autotest](https://github.com/grosser/autotest)? Try rerun -x rake or rerun -cx rspec And if you're using [Spork](https://github.com/sporkrb/spork) with Rails, you need to [restart your spork server](https://github.com/sporkrb/spork/issues/201) whenever certain Rails environment files change, so why not put this in your Rakefile... desc "run spork (via rerun)" task :spork do 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" end and start using `rake spork` to launch your spork server? (If you're using Guard instead of Rerun, check out [guard-spork](https://github.com/guard/guard-spork) for a similar solution.) How about regenerating your HTML files after every change to your [Erector](http://erector.rubyforge.org) widgets? rerun -x erector --to-html my_site.rb Use Heroku Cedar? `rerun` is now compatible with `foreman`. Run all your Procfile processes locally and restart them all when necessary. rerun foreman start # Options: `--dir` directory (or directories) to watch (default = "."). Separate multiple paths with ',' and/or use multiple `-d` options. `--pattern` glob to match inside directory. This uses the Ruby Dir glob style -- see for details. By default it watches files ending in: `rb,js,coffee,css,scss,sass,erb,html,haml,ru,yml,slim,md,feature`. On top of this, it also ignores dotfiles, `.tmp` files, and some other files and directories (like `.git` and `log`). Run `rerun --help` to see the actual list. `--ignore pattern` file glob to ignore (can be set many times). To ignore a directory, you must append '/*' e.g. `--ignore 'coverage/*'`. *On top of --pattern and --ignore, we ignore any changes to files and dirs starting with a dot.* `--signal` (or `-s`) use specified signal (instead of the default SIGTERM) to terminate the previous process. This may be useful for forcing the respective process to terminate as quickly as possible. (`--signal KILL` is the equivalent of `kill -9`) `--restart` (or `-r`) expect process to restart itself, using signal HUP by default (e.g. `-r -s INT` will send a INT and then resume watching for changes) `--clear` (or -c) clear the screen before each run `--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. `--background` (or -b) disable on-the-fly commands, allowing the process to be backgrounded `--notify NOTIFIER` use `growl` or `osx` for notifications (see below) `--no-notify` don't use growl (or osx) notifications `--name` set the app name (for display) Also `--version` and `--help`, naturally. # Notifications If you have `growlnotify` available on the `PATH`, it sends notifications to growl in addition to the console. If you have `terminal-notifier`, it sends notifications to the OS X notification center in addition to the console. If you have both, Rerun will pick one, or you can choose between them using `--notify growl` or `--notify osx` respectively. If you have a notifier installed but don't want rerun to use it, set the `--no-notify` option. Download [growlnotify here](http://growl.info/downloads.php#generaldownloads) now that Growl has moved to the App Store. 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. # On-The-Fly Commands While the app is (re)running, you can make things happen by pressing keys: * **r** -- restart (as if a file had changed) * **c** -- clear the screen * **x** or **q** -- exit (just like control-C) * **p** -- pause/unpause filesystem watching If you're backgrounding or using Pry or a debugger, you might not want these keys to be trapped, so use the `--background` option. # Signals The current algorithm for killing the process is: * send [SIGTERM](http://en.wikipedia.org/wiki/SIGTERM) (or the value of the `--signal` option) * if that doesn't work after 4 seconds, send SIGINT (aka control-C) * if that doesn't work after 2 more seconds, send SIGKILL (aka kill -9) This seems like the most gentle and unixy way of doing things, but it does mean that if your program ignores SIGTERM, it takes an extra 4 to 6 seconds to restart. # Troubleshooting If you are using `zsh` as your shell, and you are specifying your `--pattern` as `**/*.rb`, you may face this error ``` Errno::EACCES: Permission denied - ``` 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. i.e ``` rerun -p **/*.rb rake test ``` becomes ``` rerun -p "**/*.rb" rake test ``` # To Do: ## Must have for v1.0 * ".rerun" file to specify options per project or in $HOME. * Make sure to pass through quoted options correctly to target process [bug] * Optionally do "bundle install" before and "bundle exec" during launch ## Nice to have * Smarter --signal option (specifying signal to try and a timeout to wait, repeated) * If the last element of the command is a `.ru` file and there's no other command then use `rackup` * Figure out an algorithm so "-x" is not needed (if possible) -- maybe by accepting a "--port" option or reading `config.ru` * Specify (or deduce) port to listen for to determine success of a web server launch * see also [todo.md](todo.md) ## Wacky Ideas * Make it work on Windows, like Guard now does. See * https://github.com/guard/guard/issues/59 * https://github.com/guard/guard/issues/27 * On OS X: * use a C library using growl's developer API * Use growl's AppleScript or SDK instead of relying on growlnotify * Use OS X notifications * "Failed" icon for notifications * On Linux: * Test on Linux. * Use libnotify or notify-send http://www.linuxjournal.com/content/tech-tip-get-notifications-your-scripts-notify-send # Other projects that do similar things * Restartomatic: * Shotgun: * Rack::Reloader middleware: * The Sinatra FAQ has a discussion at * Kicker: * Watchr: * Guard: * Autotest: # Why would I use this instead of Shotgun? Shotgun does a "fork" after the web framework has loaded but before your application is loaded. It then loads your app, processes a single request in the child process, then exits the child process. Rerun launches the whole app, then when it's time to restart, uses "kill" to shut it down and starts the whole thing up again from scratch. So rerun takes somewhat longer than Shotgun to restart the app, but does it much less frequently. And once it's running it behaves more normally and consistently with your production app. Also, Shotgun reloads the app on every request, even if it doesn't need to. This is fine if you're loading a single file, but if your web pages all load other files (CSS, JS, media) then that adds up quickly. (I can only assume that the developers of shotgun are using caching or a front web server so this isn't a pain point for them.) And hey, does Shotgun reload your Worker processes if you're using Foreman and a Procfile? I'm pretty sure it doesn't. YMMV! # Why would I use this instead of Rack::Reloader? Rack::Reloader is certifiably beautiful code, and is a very elegant use of Rack's middleware architecture. But because it relies on the LOADED_FEATURES variable, it only reloads .rb files that were 'require'd, not 'load'ed. That leaves out (non-Erector) template files, and also, at least the way I was doing it, sub-actions (see [this thread](http://groups.google.com/group/sinatrarb/browse_thread/thread/7329727a9296e96a# )). Rack::Reloader also doesn't reload configuration changes or redo other things that happen during app startup. Rerun takes the attitude that if you want to restart an app, you should just restart the whole app. You know? # Why would I use this instead of Guard? Guard is very powerful but requires some up-front configuration. Rerun is meant as a no-frills command-line alternative requiring no knowledge of Ruby nor config file syntax. # Why did you write this? I've been using [Sinatra](http://sinatrarb.com) and loving it. In order to simplify their system, the Rat Pack removed auto-reloading from Sinatra proper. I approve of this: a web application framework should be focused on serving requests, not on munging Ruby ObjectSpace for dev-time convenience. But I still wanted automatic reloading during development. Shotgun wasn't working for me (see above) so I spliced Rerun together out of code from Rspactor, FileSystemWatcher, and Shotgun -- with a heavy amount of refactoring and rewriting. In late 2012 I migrated the backend to the Listen gem, which was extracted from Guard, so it should be more reliable and performant on multiple platforms. # Credits Rerun: [Alex Chaffee](http://alexchaffee.com), , Based upon and/or inspired by: * Shotgun: * Rspactor: * (In turn based on http://rails.aizatto.com/2007/11/28/taming-the-autotest-beast-with-fsevents/ ) * FileSystemWatcher: ## Patches by: * David Billskog * Jens B * Andrés Botero * Dreamcat4 * * Barry Sia * Paul Rangel * James Edward Gray II * Raul E Rangel and Antonio Terceiro * Mike Pastore # Version History * 0.11.0 7 October 2015 * better 'changed' message * `--notify osx` option * `--restart` option (with bugfix by Mike Pastore) * use Listen 3 gem * add `.feature` files to default watchlist (thanks @jmuheim) * v0.10.0 4 May 2014 * add '.coffee,.slim,.md' to default pattern (thanks @xylinq) * --ignore option * v0.9.0 6 March 2014 * --dir (or -d) can be specified more than once, for multiple directories (thanks again Barry!) * --name option * press 'p' to pause/unpause filesystem watching (Barry is the man!) * works with Listen 2 (note: needs 2.3 or higher) * cooldown works, thanks to patches to underlying Listen gem * ignore all dotfiles, and add actual list of ignored dirs and files * v0.8.2 * 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 * v0.8.1 * bugfix release (#30 and #34) * v0.8.0 * --background option (thanks FND!) to disable the keyboard listener * --signal option (thanks FND!) * --no-growl option * --dir supports multiple directories (thanks Barry!) * v0.7.1 * bugfix: make rails icon work again * v0.7.0 * uses Listen gem (which uses rb-fsevent for lightweight filesystem snooping) # License Open Source MIT License. See "LICENSE" file. rerun-0.11.0/Rakefile000066400000000000000000000035771260522351700144100ustar00rootroot00000000000000require 'rake' require 'rake/clean' require 'rake/testtask' require 'rspec/core/rake_task' task :default => [:spec] task :test => :spec desc "Run all specs" RSpec::Core::RakeTask.new('spec') do |t| ENV['ENV'] = "test" t.pattern = 'spec/**/*_spec.rb' t.rspec_opts = ['--color'] end $rubyforge_project = 'pivotalrb' $spec = begin require 'rubygems/specification' data = File.read('rerun.gemspec') spec = nil #Thread.new { spec = eval("$SAFE = 3\n#{data}") }.join spec = eval data spec end def package(ext='') "pkg/#{$spec.name}-#{$spec.version}" + ext end desc 'Exit if git is dirty' task :check_git do state = `git status 2> /dev/null | tail -n1` clean = (state =~ /working directory clean/) unless clean warn "can't do that on an unclean git dir" exit 1 end end desc 'Build packages' task :package => %w[.gem .tar.gz].map { |e| package(e) } desc 'Build and install as local gem' task :install => package('.gem') do sh "gem install #{package('.gem')}" end directory 'pkg/' CLOBBER.include('pkg') file package('.gem') => %W[pkg/ #{$spec.name}.gemspec] + $spec.files do |f| sh "gem build #{$spec.name}.gemspec" mv File.basename(f.name), f.name end file package('.tar.gz') => %w[pkg/] + $spec.files do |f| cmd = <<-SH git archive \ --prefix=#{$spec.name}-#{$spec.version}/ \ --format=tar \ HEAD | gzip > #{f.name} SH sh cmd.gsub(/ +/, ' ') end desc 'Publish gem and tarball to rubyforge' task 'release' => [:check_git, package('.gem'), package('.tar.gz')] do |t| puts "Releasing #{$spec.version}" sh "gem push #{package('.gem')}" puts "Tagging and pushing" sh "git tag v#{$spec.version}" sh "git push && git push --tags" end desc 'download github issues and pull requests' task 'github' do %w(issues pulls).each do |type| sh "curl -o #{type}.json https://api.github.com/repos/alexch/rerun/#{type}" end end rerun-0.11.0/bin/000077500000000000000000000000001260522351700134775ustar00rootroot00000000000000rerun-0.11.0/bin/rerun000077500000000000000000000005031260522351700145560ustar00rootroot00000000000000#!/usr/bin/env ruby require 'rubygems' libdir = "#{File.expand_path(File.dirname(File.dirname(__FILE__)))}/lib" $LOAD_PATH.unshift libdir unless $LOAD_PATH.include?(libdir) require 'rerun' require 'optparse' options = Rerun::Options.parse exit if options.nil? runner = Rerun::Runner.keep_running(options[:cmd], options) rerun-0.11.0/geminstaller.yml000066400000000000000000000000561260522351700161410ustar00rootroot00000000000000--- gems: - name: rspec version: '>= 1.2.6' rerun-0.11.0/icons/000077500000000000000000000000001260522351700140425ustar00rootroot00000000000000rerun-0.11.0/icons/rails_grn_sml.png000066400000000000000000000034141260522351700174050ustar00rootroot00000000000000PNG  IHDR2@o IsBITOPLTEջʭù⼢㶠ߩְ֚ܢՍrՌ{rg{so^spgk_ZjwUc]ROWZZGJ^=PDpiN8K?P4NNK.d]OEB*M)F dXL@aFG'L6? @*A#Q pHYs  ~tEXtSoftwareMacromedia Fireworks 8hxIDATHic<z (j27*r$ݵ<$L&YBnC<@l,uI5< 9Xyy8~Ϯq Ȓ_]96!Jyw<2]&d@7fD[ T9IqΛznV8Ȁ . yGLȈn Js…qp_|XdBTͅ#c֓wTtF$+ 'D-90A$qHH#Nʛˉw֎;mPչԇjmе=Byp[ Əl>or" I]iggsab(JbN0\n½B&+M33 I:&3f!74?JRs G|!  [` 4Ɠ 3TW5IjEאIAD@̱(I-iV+(=HG1D`d,r3M jHC"<k1$30yFʖAI !57W^,0#A&3WeC=]Ap!@c+4wHz~ߘĒ+Obabe I)ԫC`tca*}I㫐I L,K4Z*lڴ|wpԧwX(,rkVIw,ړuCk"A5~erwĿPq[rv CkX=%eyO,vB~8+ FgFaТ U<]2ϓ߈q}6&B'}gF4Ӑ'# ɯ߷"3{oD0#:3NEexLw:Df>do1~q#F}8xt:Ћ*<_lj|+4CȃV-X]l(1>މ L>:v`3Cވ2+st/Kِ|~y@ F ȧ>}r-1Ipi"?9>nD7P:+g7$8(_w&m ۭb\2eE8|%/QPe/߷Ȳ"(M Jz %:ݧǬ_ީ_ f"ҵ˘}V宴{W!#" !_)<0d{p8Nb|Yɶ1'AC/Pú00%,±eiPKae" /pIDATxڔ[cJ `xEEDET`=If@ypw-_33(@Pt]UU]7?U'_.I* T CՕaqe?+ٶ$ _L@y3d-5ϛOW$W ?,M.G%oA@R<$a$;Ncܜß~+"6d(0$ !!%մbWV ]ysD Zl\}X#!1`eO+ M xCKN)> iM(AR8f?{gNqKp6/eF JK4Yz :sS&l\ >(Ӂ/G$̜N4ey!@L39Mgx !II@ Af 94*dO^#gapdYgE@$|>'KHj/ @Kis(=XHn6Daqqs} LjA!< GE πX< #nK+A9mLr̒/mؑCAH3$%fK[=Im:3ϛIY40H7YnAS[s 7>Y<Ӱs]MB^} JvX5邏Ɗ!͙QQ7o,Q9I_!|K M;HsY(JN[nF|W,@~=?y]엯,"+>>_H(-YA[M~~X=%.O!F E`V@(E!8]rA߈\{4+'Q|#&iHCJύ +:Sgtf,ɎM۩f yI@;]v$r#Q[i3^T|,աNLCDjl($띄Wg1NG"Vt.;t!+@`ZmHU>>JC.D6f C \W}L⭛P;dD6Fsr^BT'xbםA^b<47aEY ~ I/׋(aHs a-\+lIH$c5[Ixp*DbC>;_Dڀ˚hH^?^QOxt$vHIC٧'krH ;N?=@]1r{h黆,^8i;dC!! BR$$'][k$r M.6N4#RwEK~u b6És`EuX柒N$£EwyR+FυxDx [[_%BKj(;WTO,#yM+\c$[m_؉p!SIv+pH M 3eIENDB`rerun-0.11.0/inc.rb000066400000000000000000000011251260522351700140240ustar00rootroot00000000000000STDOUT.sync = true Signal.trap("TERM") do say "exiting" exit end def say msg puts "\t[inc] #{Time.now.strftime("%T")} #{$$} #{msg}" end class Inc def initialize file @file = file end def run launched = Time.now.to_i say "launching in #{File.dirname(@file)}" i = 0 while i < 100 say "writing #{launched}/#{i} to #{File.basename(@file)}" File.open(@file, "w") do |f| f.puts(launched) f.puts(i) f.puts($$) f.puts(Process.ppid) end sleep 0.5 i+=1 end end end Inc.new(ARGV[0] || "./inc.txt").run rerun-0.11.0/issues.json000066400000000000000000001431451260522351700151450ustar00rootroot00000000000000[ { "url": "https://api.github.com/repos/alexch/rerun/issues/63", "labels_url": "https://api.github.com/repos/alexch/rerun/issues/63/labels{/name}", "comments_url": "https://api.github.com/repos/alexch/rerun/issues/63/comments", "events_url": "https://api.github.com/repos/alexch/rerun/issues/63/events", "html_url": "https://github.com/alexch/rerun/issues/63", "id": 36379723, "number": 63, "title": "support libnotify for popup notifications on linux", "user": { "login": "abargnesi", "id": 149445, "avatar_url": "https://avatars.githubusercontent.com/u/149445?v=1", "gravatar_id": "bb63c54edecfe79a732014647b379261", "url": "https://api.github.com/users/abargnesi", "html_url": "https://github.com/abargnesi", "followers_url": "https://api.github.com/users/abargnesi/followers", "following_url": "https://api.github.com/users/abargnesi/following{/other_user}", "gists_url": "https://api.github.com/users/abargnesi/gists{/gist_id}", "starred_url": "https://api.github.com/users/abargnesi/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/abargnesi/subscriptions", "organizations_url": "https://api.github.com/users/abargnesi/orgs", "repos_url": "https://api.github.com/users/abargnesi/repos", "events_url": "https://api.github.com/users/abargnesi/events{/privacy}", "received_events_url": "https://api.github.com/users/abargnesi/received_events", "type": "User", "site_admin": false }, "labels": [ ], "state": "open", "assignee": null, "milestone": null, "comments": 0, "created_at": "2014-06-24T12:41:15Z", "updated_at": "2014-06-24T12:41:15Z", "closed_at": null, "body": "Popup notifications using libnotify are common on linux. One would need a notification daemon running like gnome's `notification-daemon`, [`dunst`](https://github.com/knopwob/dunst), etc..\r\n\r\nThere is a [`libnotify gem`](https://github.com/splattael/libnotify) by Peter Suschlik that works well with my setup using dunst. This gem depends on the `ffi` gem to call C functions from libnotify." }, { "url": "https://api.github.com/repos/alexch/rerun/issues/61", "labels_url": "https://api.github.com/repos/alexch/rerun/issues/61/labels{/name}", "comments_url": "https://api.github.com/repos/alexch/rerun/issues/61/comments", "events_url": "https://api.github.com/repos/alexch/rerun/issues/61/events", "html_url": "https://github.com/alexch/rerun/pull/61", "id": 34212919, "number": 61, "title": "load .rerun file from $HOME and project directory in case it exists", "user": { "login": "dagi3d", "id": 11283, "avatar_url": "https://avatars.githubusercontent.com/u/11283?v=1", "gravatar_id": "90ea347c45cdfbc1c5767dd6304d9c10", "url": "https://api.github.com/users/dagi3d", "html_url": "https://github.com/dagi3d", "followers_url": "https://api.github.com/users/dagi3d/followers", "following_url": "https://api.github.com/users/dagi3d/following{/other_user}", "gists_url": "https://api.github.com/users/dagi3d/gists{/gist_id}", "starred_url": "https://api.github.com/users/dagi3d/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/dagi3d/subscriptions", "organizations_url": "https://api.github.com/users/dagi3d/orgs", "repos_url": "https://api.github.com/users/dagi3d/repos", "events_url": "https://api.github.com/users/dagi3d/events{/privacy}", "received_events_url": "https://api.github.com/users/dagi3d/received_events", "type": "User", "site_admin": false }, "labels": [ ], "state": "open", "assignee": null, "milestone": null, "comments": 2, "created_at": "2014-05-23T21:40:31Z", "updated_at": "2014-05-27T12:52:27Z", "closed_at": null, "pull_request": { "url": "https://api.github.com/repos/alexch/rerun/pulls/61", "html_url": "https://github.com/alexch/rerun/pull/61", "diff_url": "https://github.com/alexch/rerun/pull/61.diff", "patch_url": "https://github.com/alexch/rerun/pull/61.patch" }, "body": "Now it loads the .rerun file from the project directory and $HOME in case it exists\r\nCommand line arguments have precedence over the params declared in the project\r\nParams declared in the project directory have precedence over the params in the $HOME directory\r\n\r\n" }, { "url": "https://api.github.com/repos/alexch/rerun/issues/59", "labels_url": "https://api.github.com/repos/alexch/rerun/issues/59/labels{/name}", "comments_url": "https://api.github.com/repos/alexch/rerun/issues/59/comments", "events_url": "https://api.github.com/repos/alexch/rerun/issues/59/events", "html_url": "https://github.com/alexch/rerun/issues/59", "id": 33151552, "number": 59, "title": "Feature request: send signal to cause restart", "user": { "login": "jmuheim", "id": 1814983, "avatar_url": "https://avatars.githubusercontent.com/u/1814983?v=1", "gravatar_id": "fc582698581884352e745d1d4c64699d", "url": "https://api.github.com/users/jmuheim", "html_url": "https://github.com/jmuheim", "followers_url": "https://api.github.com/users/jmuheim/followers", "following_url": "https://api.github.com/users/jmuheim/following{/other_user}", "gists_url": "https://api.github.com/users/jmuheim/gists{/gist_id}", "starred_url": "https://api.github.com/users/jmuheim/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/jmuheim/subscriptions", "organizations_url": "https://api.github.com/users/jmuheim/orgs", "repos_url": "https://api.github.com/users/jmuheim/repos", "events_url": "https://api.github.com/users/jmuheim/events{/privacy}", "received_events_url": "https://api.github.com/users/jmuheim/received_events", "type": "User", "site_admin": false }, "labels": [ ], "state": "open", "assignee": null, "milestone": null, "comments": 0, "created_at": "2014-05-09T07:37:50Z", "updated_at": "2014-05-09T07:37:50Z", "closed_at": null, "body": "It would be nice to be able to send a signal to the running console which would cause a restart." }, { "url": "https://api.github.com/repos/alexch/rerun/issues/58", "labels_url": "https://api.github.com/repos/alexch/rerun/issues/58/labels{/name}", "comments_url": "https://api.github.com/repos/alexch/rerun/issues/58/comments", "events_url": "https://api.github.com/repos/alexch/rerun/issues/58/events", "html_url": "https://github.com/alexch/rerun/pull/58", "id": 31934813, "number": 58, "title": "add --ignore-dotfiles and disable ignoring by default", "user": { "login": "robbles", "id": 92927, "avatar_url": "https://avatars.githubusercontent.com/u/92927?v=1", "gravatar_id": "33cd4933e841cf3c03ee8a3aed0585f7", "url": "https://api.github.com/users/robbles", "html_url": "https://github.com/robbles", "followers_url": "https://api.github.com/users/robbles/followers", "following_url": "https://api.github.com/users/robbles/following{/other_user}", "gists_url": "https://api.github.com/users/robbles/gists{/gist_id}", "starred_url": "https://api.github.com/users/robbles/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/robbles/subscriptions", "organizations_url": "https://api.github.com/users/robbles/orgs", "repos_url": "https://api.github.com/users/robbles/repos", "events_url": "https://api.github.com/users/robbles/events{/privacy}", "received_events_url": "https://api.github.com/users/robbles/received_events", "type": "User", "site_admin": false }, "labels": [ ], "state": "open", "assignee": null, "milestone": null, "comments": 6, "created_at": "2014-04-21T23:51:58Z", "updated_at": "2014-05-05T15:18:57Z", "closed_at": null, "pull_request": { "url": "https://api.github.com/repos/alexch/rerun/pulls/58", "html_url": "https://github.com/alexch/rerun/pull/58", "diff_url": "https://github.com/alexch/rerun/pull/58.diff", "patch_url": "https://github.com/alexch/rerun/pull/58.patch" }, "body": "I added an option to enable the filtering of dotfiles. It's disabled by default, because otherwise it's impossible with the current setup to detect changes to them (because of the order in which Listen finds & filters files).\r\n\r\nIf you think it should be enabled by default though, I'm open to changing this though." }, { "url": "https://api.github.com/repos/alexch/rerun/issues/57", "labels_url": "https://api.github.com/repos/alexch/rerun/issues/57/labels{/name}", "comments_url": "https://api.github.com/repos/alexch/rerun/issues/57/comments", "events_url": "https://api.github.com/repos/alexch/rerun/issues/57/events", "html_url": "https://github.com/alexch/rerun/issues/57", "id": 29895300, "number": 57, "title": "Feature request: option to run the submitted command only when the first file changes", "user": { "login": "jmuheim", "id": 1814983, "avatar_url": "https://avatars.githubusercontent.com/u/1814983?v=1", "gravatar_id": "fc582698581884352e745d1d4c64699d", "url": "https://api.github.com/users/jmuheim", "html_url": "https://github.com/jmuheim", "followers_url": "https://api.github.com/users/jmuheim/followers", "following_url": "https://api.github.com/users/jmuheim/following{/other_user}", "gists_url": "https://api.github.com/users/jmuheim/gists{/gist_id}", "starred_url": "https://api.github.com/users/jmuheim/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/jmuheim/subscriptions", "organizations_url": "https://api.github.com/users/jmuheim/orgs", "repos_url": "https://api.github.com/users/jmuheim/repos", "events_url": "https://api.github.com/users/jmuheim/events{/privacy}", "received_events_url": "https://api.github.com/users/jmuheim/received_events", "type": "User", "site_admin": false }, "labels": [ ], "state": "open", "assignee": null, "milestone": null, "comments": 0, "created_at": "2014-03-21T12:01:39Z", "updated_at": "2014-05-02T16:57:57Z", "closed_at": null, "body": "...and not when running `rerun`.\r\n\r\n`--run-on-start` or something like that." }, { "url": "https://api.github.com/repos/alexch/rerun/issues/56", "labels_url": "https://api.github.com/repos/alexch/rerun/issues/56/labels{/name}", "comments_url": "https://api.github.com/repos/alexch/rerun/issues/56/comments", "events_url": "https://api.github.com/repos/alexch/rerun/issues/56/events", "html_url": "https://github.com/alexch/rerun/pull/56", "id": 29895193, "number": 56, "title": "Add feature files to default pattern and update README", "user": { "login": "jmuheim", "id": 1814983, "avatar_url": "https://avatars.githubusercontent.com/u/1814983?v=1", "gravatar_id": "fc582698581884352e745d1d4c64699d", "url": "https://api.github.com/users/jmuheim", "html_url": "https://github.com/jmuheim", "followers_url": "https://api.github.com/users/jmuheim/followers", "following_url": "https://api.github.com/users/jmuheim/following{/other_user}", "gists_url": "https://api.github.com/users/jmuheim/gists{/gist_id}", "starred_url": "https://api.github.com/users/jmuheim/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/jmuheim/subscriptions", "organizations_url": "https://api.github.com/users/jmuheim/orgs", "repos_url": "https://api.github.com/users/jmuheim/repos", "events_url": "https://api.github.com/users/jmuheim/events{/privacy}", "received_events_url": "https://api.github.com/users/jmuheim/received_events", "type": "User", "site_admin": false }, "labels": [ ], "state": "open", "assignee": null, "milestone": null, "comments": 0, "created_at": "2014-03-21T11:59:27Z", "updated_at": "2014-03-21T11:59:27Z", "closed_at": null, "pull_request": { "url": "https://api.github.com/repos/alexch/rerun/pulls/56", "html_url": "https://github.com/alexch/rerun/pull/56", "diff_url": "https://github.com/alexch/rerun/pull/56.diff", "patch_url": "https://github.com/alexch/rerun/pull/56.patch" }, "body": "`xxx.feature` files are commonly used for Gherkin based stuff, e.g. Cucumber or Turnip feature tests.\r\n\r\nI also noticed that your README wasn't up2date and fixed it." }, { "url": "https://api.github.com/repos/alexch/rerun/issues/55", "labels_url": "https://api.github.com/repos/alexch/rerun/issues/55/labels{/name}", "comments_url": "https://api.github.com/repos/alexch/rerun/issues/55/comments", "events_url": "https://api.github.com/repos/alexch/rerun/issues/55/events", "html_url": "https://github.com/alexch/rerun/issues/55", "id": 29825419, "number": 55, "title": "Stop rerun when launch failed", "user": { "login": "jmuheim", "id": 1814983, "avatar_url": "https://avatars.githubusercontent.com/u/1814983?v=1", "gravatar_id": "fc582698581884352e745d1d4c64699d", "url": "https://api.github.com/users/jmuheim", "html_url": "https://github.com/jmuheim", "followers_url": "https://api.github.com/users/jmuheim/followers", "following_url": "https://api.github.com/users/jmuheim/following{/other_user}", "gists_url": "https://api.github.com/users/jmuheim/gists{/gist_id}", "starred_url": "https://api.github.com/users/jmuheim/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/jmuheim/subscriptions", "organizations_url": "https://api.github.com/users/jmuheim/orgs", "repos_url": "https://api.github.com/users/jmuheim/repos", "events_url": "https://api.github.com/users/jmuheim/events{/privacy}", "received_events_url": "https://api.github.com/users/jmuheim/received_events", "type": "User", "site_admin": false }, "labels": [ ], "state": "open", "assignee": null, "milestone": null, "comments": 0, "created_at": "2014-03-20T14:57:06Z", "updated_at": "2014-03-20T14:57:06Z", "closed_at": null, "body": "I think that rerun should exit when it can't launch the app:\r\n\r\n```\r\n15:55:22 [rerun] Synaesthesia Launch Failed\r\n15:55:23 [rerun] Watching . for {Gemfile.lock,config/environment.rb,config/environments/development.rb,config/initializers/*.rb,lib/**/*.rb} using Darwin adapter\r\n```\r\n\r\nOr do you expect the next time the launch will succeed?" }, { "url": "https://api.github.com/repos/alexch/rerun/issues/53", "labels_url": "https://api.github.com/repos/alexch/rerun/issues/53/labels{/name}", "comments_url": "https://api.github.com/repos/alexch/rerun/issues/53/comments", "events_url": "https://api.github.com/repos/alexch/rerun/issues/53/events", "html_url": "https://github.com/alexch/rerun/issues/53", "id": 29714802, "number": 53, "title": "FATAL SignalException: SIGTERM", "user": { "login": "jmuheim", "id": 1814983, "avatar_url": "https://avatars.githubusercontent.com/u/1814983?v=1", "gravatar_id": "fc582698581884352e745d1d4c64699d", "url": "https://api.github.com/users/jmuheim", "html_url": "https://github.com/jmuheim", "followers_url": "https://api.github.com/users/jmuheim/followers", "following_url": "https://api.github.com/users/jmuheim/following{/other_user}", "gists_url": "https://api.github.com/users/jmuheim/gists{/gist_id}", "starred_url": "https://api.github.com/users/jmuheim/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/jmuheim/subscriptions", "organizations_url": "https://api.github.com/users/jmuheim/orgs", "repos_url": "https://api.github.com/users/jmuheim/repos", "events_url": "https://api.github.com/users/jmuheim/events{/privacy}", "received_events_url": "https://api.github.com/users/jmuheim/received_events", "type": "User", "site_admin": false }, "labels": [ ], "state": "open", "assignee": null, "milestone": null, "comments": 6, "created_at": "2014-03-19T08:42:16Z", "updated_at": "2014-05-09T07:37:11Z", "closed_at": null, "body": "I try to restart webrick whenever an important file changes. This is the output:\r\n\r\n```\r\n=> Booting WEBrick\r\n=> Rails 4.0.3 application starting in development on http://0.0.0.0:3001\r\n=> Run `rails server -h` for more startup options\r\n=> Ctrl-C to shutdown server\r\n[2014-03-19 09:38:13] INFO WEBrick 1.3.1\r\n[2014-03-19 09:38:13] INFO ruby 2.1.0 (2013-12-25) [x86_64-darwin12.0]\r\n[2014-03-19 09:38:13] INFO WEBrick::HTTPServer#start: pid=9912 port=3001\r\nr09:38:31 [rerun] Restarting\r\n09:38:31 [rerun] Sending signal TERM to 9912\r\n[2014-03-19 09:38:31] FATAL SignalException: SIGTERM\r\n\t/Users/josh/.rvm/rubies/ruby-2.1.0/lib/ruby/2.1.0/webrick/server.rb:170:in `select'\r\n\t/Users/josh/.rvm/rubies/ruby-2.1.0/lib/ruby/2.1.0/webrick/server.rb:170:in `block in start'\r\n\t/Users/josh/.rvm/rubies/ruby-2.1.0/lib/ruby/2.1.0/webrick/server.rb:32:in `start'\r\n\t/Users/josh/.rvm/rubies/ruby-2.1.0/lib/ruby/2.1.0/webrick/server.rb:160:in `start'\r\n\t/Users/josh/.rvm/gems/ruby-2.1.0@base/gems/rack-1.5.2/lib/rack/handler/webrick.rb:14:in `run'\r\n\t/Users/josh/.rvm/gems/ruby-2.1.0@base/gems/rack-1.5.2/lib/rack/server.rb:264:in `start'\r\n\t/Users/josh/.rvm/gems/ruby-2.1.0@base/gems/railties-4.0.3/lib/rails/commands/server.rb:84:in `start'\r\n\t/Users/josh/.rvm/gems/ruby-2.1.0@base/gems/railties-4.0.3/lib/rails/commands.rb:76:in `block in '\r\n\t/Users/josh/.rvm/gems/ruby-2.1.0@base/gems/railties-4.0.3/lib/rails/commands.rb:71:in `tap'\r\n\t/Users/josh/.rvm/gems/ruby-2.1.0@base/gems/railties-4.0.3/lib/rails/commands.rb:71:in `'\r\n\tbin/rails:8:in `require'\r\n\tbin/rails:8:in `
'\r\n[2014-03-19 09:38:31] INFO going to shutdown ...\r\n[2014-03-19 09:38:31] INFO WEBrick::HTTPServer#start done.\r\n```\r\n\r\nI'm concerned about the \"FATAL SignalException: SIGTERM\": is this really correct? Webrick is reloaded correctly, but this looks a bit strange to me." }, { "url": "https://api.github.com/repos/alexch/rerun/issues/52", "labels_url": "https://api.github.com/repos/alexch/rerun/issues/52/labels{/name}", "comments_url": "https://api.github.com/repos/alexch/rerun/issues/52/comments", "events_url": "https://api.github.com/repos/alexch/rerun/issues/52/events", "html_url": "https://github.com/alexch/rerun/issues/52", "id": 29598993, "number": 52, "title": "Allow monitoring of changes to files starting with a dot", "user": { "login": "robbles", "id": 92927, "avatar_url": "https://avatars.githubusercontent.com/u/92927?v=1", "gravatar_id": "33cd4933e841cf3c03ee8a3aed0585f7", "url": "https://api.github.com/users/robbles", "html_url": "https://github.com/robbles", "followers_url": "https://api.github.com/users/robbles/followers", "following_url": "https://api.github.com/users/robbles/following{/other_user}", "gists_url": "https://api.github.com/users/robbles/gists{/gist_id}", "starred_url": "https://api.github.com/users/robbles/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/robbles/subscriptions", "organizations_url": "https://api.github.com/users/robbles/orgs", "repos_url": "https://api.github.com/users/robbles/repos", "events_url": "https://api.github.com/users/robbles/events{/privacy}", "received_events_url": "https://api.github.com/users/robbles/received_events", "type": "User", "site_admin": false }, "labels": [ ], "state": "open", "assignee": null, "milestone": null, "comments": 4, "created_at": "2014-03-17T21:09:21Z", "updated_at": "2014-06-12T21:48:38Z", "closed_at": null, "body": "I'm trying to get rerun to pick up changes to my `.env` file, used with Foreman. Restarting my server when code changes is working just fine, but ideally I'd like to have a workflow where I can change environment vars in `.env` and have the app auto-reload with new configuration.\r\n\r\nI see that this is a deliberate built-in feature of the file globbing implementation. Turning this off could be a switch (e.g. `--no-ignore-dot`) or perhaps an implementation of the exclude option #24 could have leading dots, etc. as the default value, which could then be overridden.\r\n\r\nI'm happy to give a shot at implementing this myself. Just wondering if it's already in progress or if you're opposed to the idea." }, { "url": "https://api.github.com/repos/alexch/rerun/issues/41", "labels_url": "https://api.github.com/repos/alexch/rerun/issues/41/labels{/name}", "comments_url": "https://api.github.com/repos/alexch/rerun/issues/41/comments", "events_url": "https://api.github.com/repos/alexch/rerun/issues/41/events", "html_url": "https://github.com/alexch/rerun/issues/41", "id": 16313594, "number": 41, "title": "\"rerun foreman start\", the first re-run fails with \"Errno::EADDRINUSE\" (Ubuntu 12.10)", "user": { "login": "gridsane", "id": 1535767, "avatar_url": "https://avatars.githubusercontent.com/u/1535767?v=1", "gravatar_id": "0e0b0b176952aea9f2cb7539b3fb6c3f", "url": "https://api.github.com/users/gridsane", "html_url": "https://github.com/gridsane", "followers_url": "https://api.github.com/users/gridsane/followers", "following_url": "https://api.github.com/users/gridsane/following{/other_user}", "gists_url": "https://api.github.com/users/gridsane/gists{/gist_id}", "starred_url": "https://api.github.com/users/gridsane/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/gridsane/subscriptions", "organizations_url": "https://api.github.com/users/gridsane/orgs", "repos_url": "https://api.github.com/users/gridsane/repos", "events_url": "https://api.github.com/users/gridsane/events{/privacy}", "received_events_url": "https://api.github.com/users/gridsane/received_events", "type": "User", "site_admin": false }, "labels": [ ], "state": "open", "assignee": null, "milestone": null, "comments": 4, "created_at": "2013-07-03T11:44:23Z", "updated_at": "2014-03-25T06:54:39Z", "closed_at": null, "body": "```\r\nrerun foreman start\r\n\r\n17:31:47 [rerun] Heroku.dev launched\r\n17:31:47 web.1 | started with pid 22808\r\n17:31:49 web.1 | [2013-07-03 17:31:49] INFO WEBrick 1.3.1\r\n17:31:49 web.1 | [2013-07-03 17:31:49] INFO ruby 1.9.3 (2012-04-20) [x86_64-linux]\r\n17:31:49 web.1 | [2013-07-03 17:31:49] INFO WEBrick::HTTPServer#start: pid=22811 port=5000\r\n17:31:50 [rerun] Watching . for **/*.{rb,js,css,scss,sass,erb,html,haml,ru} using Linux adapter\r\nr17:31:56 [rerun] Restarting\r\n17:31:56 [rerun] Sending signal TERM to 22799\r\nSIGTERM received\r\n17:31:56 system | sending SIGTERM to all processes\r\n17:32:00 [rerun] Sending signal INT to 22799\r\nSIGINT received\r\n17:32:01 system | sending SIGKILL to all processes\r\n17:32:02 [rerun] Sending signal KILL to 22799\r\n\r\n17:32:02 [rerun] Heroku.dev restarted\r\n17:32:02 web.1 | started with pid 22892\r\n17:32:04 web.1 | [2013-07-03 17:32:04] INFO WEBrick 1.3.1\r\n17:32:04 web.1 | [2013-07-03 17:32:04] INFO ruby 1.9.3 (2012-04-20) [x86_64-linux]\r\n17:32:04 web.1 | [2013-07-03 17:32:04] WARN TCPServer Error: Address already in use - bind(2)\r\n17:32:04 web.1 | /usr/lib/ruby/1.9.1/webrick/utils.rb:85:in `initialize': Address already in use - bind(2) (Errno::EADDRINUSE)\r\n17:32:04 web.1 | from /usr/lib/ruby/1.9.1/webrick/utils.rb:85:in `new'\r\n17:32:04 web.1 | from /usr/lib/ruby/1.9.1/webrick/utils.rb:85:in `block in create_listeners'\r\n17:32:04 web.1 | from /usr/lib/ruby/1.9.1/webrick/utils.rb:82:in `each'\r\n17:32:04 web.1 | from /usr/lib/ruby/1.9.1/webrick/utils.rb:82:in `create_listeners'\r\n17:32:04 web.1 | from /usr/lib/ruby/1.9.1/webrick/server.rb:82:in `listen'\r\n17:32:04 web.1 | from /usr/lib/ruby/1.9.1/webrick/server.rb:70:in `initialize'\r\n17:32:04 web.1 | from /usr/lib/ruby/1.9.1/webrick/httpserver.rb:45:in `initialize'\r\n17:32:04 web.1 | from /var/lib/gems/1.9.1/gems/rack-1.5.2/lib/rack/handler/webrick.rb:11:in `new'\r\n17:32:04 web.1 | from /var/lib/gems/1.9.1/gems/rack-1.5.2/lib/rack/handler/webrick.rb:11:in `run'\r\n17:32:04 web.1 | from /var/lib/gems/1.9.1/gems/rack-1.5.2/lib/rack/server.rb:264:in `start'\r\n17:32:04 web.1 | from /var/lib/gems/1.9.1/gems/rack-1.5.2/lib/rack/server.rb:141:in `start'\r\n17:32:04 web.1 | from /var/lib/gems/1.9.1/gems/rack-1.5.2/bin/rackup:4:in `'\r\n17:32:04 web.1 | from /usr/local/bin/rackup:23:in `load'\r\n17:32:04 web.1 | from /usr/local/bin/rackup:23:in `
'\r\n17:32:04 web.1 | exited with code 1\r\n17:32:04 system | sending SIGTERM to all processes\r\n```\r\n\r\n\"foreman\" recieve SIGKILL, so \"rackup\" not killed by \"foreman\" (i can see it in a process list on port 5000), so \"foreman\" can't start second time.\r\n\r\nMaybe time intervals between signals should be in options?" }, { "url": "https://api.github.com/repos/alexch/rerun/issues/40", "labels_url": "https://api.github.com/repos/alexch/rerun/issues/40/labels{/name}", "comments_url": "https://api.github.com/repos/alexch/rerun/issues/40/comments", "events_url": "https://api.github.com/repos/alexch/rerun/issues/40/events", "html_url": "https://github.com/alexch/rerun/pull/40", "id": 15551304, "number": 40, "title": "support OSX notifications as alternative to growl", "user": { "login": "RaVbaker", "id": 56023, "avatar_url": "https://avatars.githubusercontent.com/u/56023?v=1", "gravatar_id": "9764e44e1d69baa6276644e546ea9229", "url": "https://api.github.com/users/RaVbaker", "html_url": "https://github.com/RaVbaker", "followers_url": "https://api.github.com/users/RaVbaker/followers", "following_url": "https://api.github.com/users/RaVbaker/following{/other_user}", "gists_url": "https://api.github.com/users/RaVbaker/gists{/gist_id}", "starred_url": "https://api.github.com/users/RaVbaker/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/RaVbaker/subscriptions", "organizations_url": "https://api.github.com/users/RaVbaker/orgs", "repos_url": "https://api.github.com/users/RaVbaker/repos", "events_url": "https://api.github.com/users/RaVbaker/events{/privacy}", "received_events_url": "https://api.github.com/users/RaVbaker/received_events", "type": "User", "site_admin": false }, "labels": [ ], "state": "open", "assignee": null, "milestone": null, "comments": 7, "created_at": "2013-06-14T10:15:21Z", "updated_at": "2014-06-07T17:46:55Z", "closed_at": null, "pull_request": { "url": "https://api.github.com/repos/alexch/rerun/pulls/40", "html_url": "https://github.com/alexch/rerun/pull/40", "diff_url": "https://github.com/alexch/rerun/pull/40.diff", "patch_url": "https://github.com/alexch/rerun/pull/40.patch" }, "body": "I have coded the OSX Notifications support for rerun. It uses [terminal-notifier](https://github.com/alloy/terminal-notifier) gem. And you can use it with two different arguments: `-on` or `--osx-notifications`. If you will use it will disable the growl notifications.\r\n\r\nRelated to issue: #33\r\n\r\nHow it looks? See here: ![OS X notifications for rerun gem](http://f.cl.ly/items/1q302F041i2I0j1l113U/Screen%20Shot%202013-06-14%20o%2012.11.40.png) " }, { "url": "https://api.github.com/repos/alexch/rerun/issues/39", "labels_url": "https://api.github.com/repos/alexch/rerun/issues/39/labels{/name}", "comments_url": "https://api.github.com/repos/alexch/rerun/issues/39/comments", "events_url": "https://api.github.com/repos/alexch/rerun/issues/39/events", "html_url": "https://github.com/alexch/rerun/issues/39", "id": 14921776, "number": 39, "title": "Monitoring shared directories inside a vagrant VM doesn't work", "user": { "login": "fields", "id": 52378, "avatar_url": "https://avatars.githubusercontent.com/u/52378?v=1", "gravatar_id": "e916fec0d7599a70f91bda465987323d", "url": "https://api.github.com/users/fields", "html_url": "https://github.com/fields", "followers_url": "https://api.github.com/users/fields/followers", "following_url": "https://api.github.com/users/fields/following{/other_user}", "gists_url": "https://api.github.com/users/fields/gists{/gist_id}", "starred_url": "https://api.github.com/users/fields/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/fields/subscriptions", "organizations_url": "https://api.github.com/users/fields/orgs", "repos_url": "https://api.github.com/users/fields/repos", "events_url": "https://api.github.com/users/fields/events{/privacy}", "received_events_url": "https://api.github.com/users/fields/received_events", "type": "User", "site_admin": false }, "labels": [ ], "state": "open", "assignee": null, "milestone": null, "comments": 7, "created_at": "2013-05-30T01:52:32Z", "updated_at": "2014-03-07T23:21:24Z", "closed_at": null, "body": "We're trying to use rerun to automatically restart a sinatra process inside a vagrant VM (ubuntu). The host is a Mac, and the source tree is in a shared directory. rerun starts, but doesn't detect changes on the files in the source tree.\r\n\r\nIs there a way to get this to work? Is this a more appropriate issue for the listen gem?" }, { "url": "https://api.github.com/repos/alexch/rerun/issues/38", "labels_url": "https://api.github.com/repos/alexch/rerun/issues/38/labels{/name}", "comments_url": "https://api.github.com/repos/alexch/rerun/issues/38/comments", "events_url": "https://api.github.com/repos/alexch/rerun/issues/38/events", "html_url": "https://github.com/alexch/rerun/issues/38", "id": 14247850, "number": 38, "title": "Doesn't work when source file is mounted from Mac OSX", "user": { "login": "garbin", "id": 63785, "avatar_url": "https://avatars.githubusercontent.com/u/63785?v=1", "gravatar_id": "608bb9c89a1969d6739d1e458058c17d", "url": "https://api.github.com/users/garbin", "html_url": "https://github.com/garbin", "followers_url": "https://api.github.com/users/garbin/followers", "following_url": "https://api.github.com/users/garbin/following{/other_user}", "gists_url": "https://api.github.com/users/garbin/gists{/gist_id}", "starred_url": "https://api.github.com/users/garbin/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/garbin/subscriptions", "organizations_url": "https://api.github.com/users/garbin/orgs", "repos_url": "https://api.github.com/users/garbin/repos", "events_url": "https://api.github.com/users/garbin/events{/privacy}", "received_events_url": "https://api.github.com/users/garbin/received_events", "type": "User", "site_admin": false }, "labels": [ ], "state": "open", "assignee": null, "milestone": null, "comments": 2, "created_at": "2013-05-13T07:04:40Z", "updated_at": "2014-03-06T23:50:04Z", "closed_at": null, "body": "The source file is in mac osx. I mount the dir to a Linux which is in a vmware virtual machine. In linux, I try to \"rerun 'rackup'\", the server can be started up, but when I change the source file on Mac OS X, the server doesn't auto reload. When I change the source file on linux, It works great. How can I resolve this problem?" }, { "url": "https://api.github.com/repos/alexch/rerun/issues/33", "labels_url": "https://api.github.com/repos/alexch/rerun/issues/33/labels{/name}", "comments_url": "https://api.github.com/repos/alexch/rerun/issues/33/comments", "events_url": "https://api.github.com/repos/alexch/rerun/issues/33/events", "html_url": "https://github.com/alexch/rerun/issues/33", "id": 13535519, "number": 33, "title": "support OSX notifications as alternative to growl", "user": { "login": "rkh", "id": 30442, "avatar_url": "https://avatars.githubusercontent.com/u/30442?v=1", "gravatar_id": "5c2b452f6eea4a6d84c105ebd971d2a4", "url": "https://api.github.com/users/rkh", "html_url": "https://github.com/rkh", "followers_url": "https://api.github.com/users/rkh/followers", "following_url": "https://api.github.com/users/rkh/following{/other_user}", "gists_url": "https://api.github.com/users/rkh/gists{/gist_id}", "starred_url": "https://api.github.com/users/rkh/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/rkh/subscriptions", "organizations_url": "https://api.github.com/users/rkh/orgs", "repos_url": "https://api.github.com/users/rkh/repos", "events_url": "https://api.github.com/users/rkh/events{/privacy}", "received_events_url": "https://api.github.com/users/rkh/received_events", "type": "User", "site_admin": false }, "labels": [ ], "state": "open", "assignee": null, "milestone": null, "comments": 3, "created_at": "2013-04-23T13:57:27Z", "updated_at": "2013-08-28T19:07:00Z", "closed_at": null, "body": "" }, { "url": "https://api.github.com/repos/alexch/rerun/issues/31", "labels_url": "https://api.github.com/repos/alexch/rerun/issues/31/labels{/name}", "comments_url": "https://api.github.com/repos/alexch/rerun/issues/31/comments", "events_url": "https://api.github.com/repos/alexch/rerun/issues/31/events", "html_url": "https://github.com/alexch/rerun/pull/31", "id": 12609258, "number": 31, "title": "Add restart signal support", "user": { "login": "ismell", "id": 562978, "avatar_url": "https://avatars.githubusercontent.com/u/562978?v=1", "gravatar_id": "4f945a304cb19ee2404bfbad964bd85e", "url": "https://api.github.com/users/ismell", "html_url": "https://github.com/ismell", "followers_url": "https://api.github.com/users/ismell/followers", "following_url": "https://api.github.com/users/ismell/following{/other_user}", "gists_url": "https://api.github.com/users/ismell/gists{/gist_id}", "starred_url": "https://api.github.com/users/ismell/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/ismell/subscriptions", "organizations_url": "https://api.github.com/users/ismell/orgs", "repos_url": "https://api.github.com/users/ismell/repos", "events_url": "https://api.github.com/users/ismell/events{/privacy}", "received_events_url": "https://api.github.com/users/ismell/received_events", "type": "User", "site_admin": false }, "labels": [ ], "state": "open", "assignee": null, "milestone": null, "comments": 1, "created_at": "2013-03-29T15:58:47Z", "updated_at": "2013-10-18T18:37:05Z", "closed_at": null, "pull_request": { "url": "https://api.github.com/repos/alexch/rerun/pulls/31", "html_url": "https://github.com/alexch/rerun/pull/31", "diff_url": "https://github.com/alexch/rerun/pull/31.diff", "patch_url": "https://github.com/alexch/rerun/pull/31.patch" }, "body": "This can be used when running with unicorn.\r\n\r\nrerun -r HUP -- unicorn -c unicorn.rb\r\n\r\nNOTE: Make sure you run unicorn with a config file\r\n otherwise it will respawn the master and you will\r\n end up in a very bad place." }, { "url": "https://api.github.com/repos/alexch/rerun/issues/24", "labels_url": "https://api.github.com/repos/alexch/rerun/issues/24/labels{/name}", "comments_url": "https://api.github.com/repos/alexch/rerun/issues/24/comments", "events_url": "https://api.github.com/repos/alexch/rerun/issues/24/events", "html_url": "https://github.com/alexch/rerun/issues/24", "id": 9274411, "number": 24, "title": "Support for a --exclude option", "user": { "login": "teddziuba", "id": 84232, "avatar_url": "https://avatars.githubusercontent.com/u/84232?v=1", "gravatar_id": "17c9d9798ac2b8f811ddc64cc7ca8c0f", "url": "https://api.github.com/users/teddziuba", "html_url": "https://github.com/teddziuba", "followers_url": "https://api.github.com/users/teddziuba/followers", "following_url": "https://api.github.com/users/teddziuba/following{/other_user}", "gists_url": "https://api.github.com/users/teddziuba/gists{/gist_id}", "starred_url": "https://api.github.com/users/teddziuba/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/teddziuba/subscriptions", "organizations_url": "https://api.github.com/users/teddziuba/orgs", "repos_url": "https://api.github.com/users/teddziuba/repos", "events_url": "https://api.github.com/users/teddziuba/events{/privacy}", "received_events_url": "https://api.github.com/users/teddziuba/received_events", "type": "User", "site_admin": false }, "labels": [ ], "state": "open", "assignee": null, "milestone": null, "comments": 3, "created_at": "2012-12-14T02:28:55Z", "updated_at": "2014-04-16T22:10:35Z", "closed_at": null, "body": "I'm using Rerun for for Python development with Heroku. (Long story short, the HTTP server I use in production doesn't support automatic-reloading, so I have rerun kicking foreman when there are code changes).\r\n\r\nI use Emacs for development, with flymake mode to do on-the-fly syntax checking. It does this by copying the current buffer into a `[filename]_flymake.py` file and then running `pylint` on that file. This file creation kicks off rerun, so it's constantly bouncing my development HTTP server as I'm editing code.\r\n\r\nI'd like to add my vote for a `--exclude` option that can take a glob pattern. I'd send you a pull myself, but I don't know enough Ruby.\r\n\r\nCheers" }, { "url": "https://api.github.com/repos/alexch/rerun/issues/23", "labels_url": "https://api.github.com/repos/alexch/rerun/issues/23/labels{/name}", "comments_url": "https://api.github.com/repos/alexch/rerun/issues/23/comments", "events_url": "https://api.github.com/repos/alexch/rerun/issues/23/events", "html_url": "https://github.com/alexch/rerun/issues/23", "id": 8426275, "number": 23, "title": "Input keypresses are duplicated after 200-800ms on OS X 10.8.2 ", "user": { "login": "nathanaeljones", "id": 107935, "avatar_url": "https://avatars.githubusercontent.com/u/107935?v=1", "gravatar_id": "e246b32ac5e470afb71f8221a9759da2", "url": "https://api.github.com/users/nathanaeljones", "html_url": "https://github.com/nathanaeljones", "followers_url": "https://api.github.com/users/nathanaeljones/followers", "following_url": "https://api.github.com/users/nathanaeljones/following{/other_user}", "gists_url": "https://api.github.com/users/nathanaeljones/gists{/gist_id}", "starred_url": "https://api.github.com/users/nathanaeljones/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/nathanaeljones/subscriptions", "organizations_url": "https://api.github.com/users/nathanaeljones/orgs", "repos_url": "https://api.github.com/users/nathanaeljones/repos", "events_url": "https://api.github.com/users/nathanaeljones/events{/privacy}", "received_events_url": "https://api.github.com/users/nathanaeljones/received_events", "type": "User", "site_admin": false }, "labels": [ ], "state": "open", "assignee": null, "milestone": null, "comments": 2, "created_at": "2012-11-16T17:30:44Z", "updated_at": "2013-01-31T15:46:32Z", "closed_at": null, "body": "Typing @me will product @@meme or @m@mee or something similar.\n\nMakes debugging with 'debugger' impossible.\n\nusing rerun (0.7.1)" }, { "url": "https://api.github.com/repos/alexch/rerun/issues/21", "labels_url": "https://api.github.com/repos/alexch/rerun/issues/21/labels{/name}", "comments_url": "https://api.github.com/repos/alexch/rerun/issues/21/comments", "events_url": "https://api.github.com/repos/alexch/rerun/issues/21/events", "html_url": "https://github.com/alexch/rerun/issues/21", "id": 7027235, "number": 21, "title": "use ChildProcess so it works on Windows", "user": { "login": "alexch", "id": 8524, "avatar_url": "https://avatars.githubusercontent.com/u/8524?v=1", "gravatar_id": "5a0d7f0cb2fac7858d234de7f7f01491", "url": "https://api.github.com/users/alexch", "html_url": "https://github.com/alexch", "followers_url": "https://api.github.com/users/alexch/followers", "following_url": "https://api.github.com/users/alexch/following{/other_user}", "gists_url": "https://api.github.com/users/alexch/gists{/gist_id}", "starred_url": "https://api.github.com/users/alexch/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/alexch/subscriptions", "organizations_url": "https://api.github.com/users/alexch/orgs", "repos_url": "https://api.github.com/users/alexch/repos", "events_url": "https://api.github.com/users/alexch/events{/privacy}", "received_events_url": "https://api.github.com/users/alexch/received_events", "type": "User", "site_admin": false }, "labels": [ ], "state": "open", "assignee": null, "milestone": null, "comments": 1, "created_at": "2012-09-20T22:36:33Z", "updated_at": "2014-01-21T03:23:14Z", "closed_at": null, "body": "a la https://github.com/guard/guard-spork/commit/282c3413200580e36c79c5166a91863c37e9efe1" }, { "url": "https://api.github.com/repos/alexch/rerun/issues/19", "labels_url": "https://api.github.com/repos/alexch/rerun/issues/19/labels{/name}", "comments_url": "https://api.github.com/repos/alexch/rerun/issues/19/comments", "events_url": "https://api.github.com/repos/alexch/rerun/issues/19/events", "html_url": "https://github.com/alexch/rerun/issues/19", "id": 5750481, "number": 19, "title": "control-C during restart leaves something running", "user": { "login": "alexch", "id": 8524, "avatar_url": "https://avatars.githubusercontent.com/u/8524?v=1", "gravatar_id": "5a0d7f0cb2fac7858d234de7f7f01491", "url": "https://api.github.com/users/alexch", "html_url": "https://github.com/alexch", "followers_url": "https://api.github.com/users/alexch/followers", "following_url": "https://api.github.com/users/alexch/following{/other_user}", "gists_url": "https://api.github.com/users/alexch/gists{/gist_id}", "starred_url": "https://api.github.com/users/alexch/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/alexch/subscriptions", "organizations_url": "https://api.github.com/users/alexch/orgs", "repos_url": "https://api.github.com/users/alexch/repos", "events_url": "https://api.github.com/users/alexch/events{/privacy}", "received_events_url": "https://api.github.com/users/alexch/received_events", "type": "User", "site_admin": false }, "labels": [ ], "state": "open", "assignee": null, "milestone": null, "comments": 2, "created_at": "2012-07-21T02:31:28Z", "updated_at": "2013-06-18T19:31:43Z", "closed_at": null, "body": "the signal handler should not only kill a running process; it should also kill a process that we're currently in the middle of starting (if the timing is just wrong it'll leave one running in the background)" }, { "url": "https://api.github.com/repos/alexch/rerun/issues/18", "labels_url": "https://api.github.com/repos/alexch/rerun/issues/18/labels{/name}", "comments_url": "https://api.github.com/repos/alexch/rerun/issues/18/comments", "events_url": "https://api.github.com/repos/alexch/rerun/issues/18/events", "html_url": "https://github.com/alexch/rerun/issues/18", "id": 5610909, "number": 18, "title": "Vote for the \"cool-down\" feature", "user": { "login": "mjones-rpx", "id": 851349, "avatar_url": "https://avatars.githubusercontent.com/u/851349?v=1", "gravatar_id": "295429f9c258add966b808a428bc68ba", "url": "https://api.github.com/users/mjones-rpx", "html_url": "https://github.com/mjones-rpx", "followers_url": "https://api.github.com/users/mjones-rpx/followers", "following_url": "https://api.github.com/users/mjones-rpx/following{/other_user}", "gists_url": "https://api.github.com/users/mjones-rpx/gists{/gist_id}", "starred_url": "https://api.github.com/users/mjones-rpx/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/mjones-rpx/subscriptions", "organizations_url": "https://api.github.com/users/mjones-rpx/orgs", "repos_url": "https://api.github.com/users/mjones-rpx/repos", "events_url": "https://api.github.com/users/mjones-rpx/events{/privacy}", "received_events_url": "https://api.github.com/users/mjones-rpx/received_events", "type": "User", "site_admin": false }, "labels": [ ], "state": "open", "assignee": null, "milestone": null, "comments": 1, "created_at": "2012-07-13T18:32:07Z", "updated_at": "2014-03-06T23:55:58Z", "closed_at": null, "body": "Just a note to register a strong vote for the cool-down feature. This is working really nicely to help with restarting a Rails 3 Grape API app I'm working on. But I use RubyMine, which autosaves all the time, and this causes rerun to kick off constantly. It would even be cool if you kept it simple and we could start rerun with a flag telling it to not restart more than once every X seconds. Thanks for the great program." }, { "url": "https://api.github.com/repos/alexch/rerun/issues/15", "labels_url": "https://api.github.com/repos/alexch/rerun/issues/15/labels{/name}", "comments_url": "https://api.github.com/repos/alexch/rerun/issues/15/comments", "events_url": "https://api.github.com/repos/alexch/rerun/issues/15/events", "html_url": "https://github.com/alexch/rerun/issues/15", "id": 2282579, "number": 15, "title": "tell me when the server is listening", "user": { "login": "alexch", "id": 8524, "avatar_url": "https://avatars.githubusercontent.com/u/8524?v=1", "gravatar_id": "5a0d7f0cb2fac7858d234de7f7f01491", "url": "https://api.github.com/users/alexch", "html_url": "https://github.com/alexch", "followers_url": "https://api.github.com/users/alexch/followers", "following_url": "https://api.github.com/users/alexch/following{/other_user}", "gists_url": "https://api.github.com/users/alexch/gists{/gist_id}", "starred_url": "https://api.github.com/users/alexch/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/alexch/subscriptions", "organizations_url": "https://api.github.com/users/alexch/orgs", "repos_url": "https://api.github.com/users/alexch/repos", "events_url": "https://api.github.com/users/alexch/events{/privacy}", "received_events_url": "https://api.github.com/users/alexch/received_events", "type": "User", "site_admin": false }, "labels": [ ], "state": "open", "assignee": null, "milestone": null, "comments": 3, "created_at": "2011-11-18T17:41:13Z", "updated_at": "2013-06-18T20:04:41Z", "closed_at": null, "body": "if possible, detect when the server has not only launched but is listening to the port and ready to accept requests\r\n\r\nthis may require some config.ru snooping or CL params to figure out what port to check\r\n" }, { "url": "https://api.github.com/repos/alexch/rerun/issues/12", "labels_url": "https://api.github.com/repos/alexch/rerun/issues/12/labels{/name}", "comments_url": "https://api.github.com/repos/alexch/rerun/issues/12/comments", "events_url": "https://api.github.com/repos/alexch/rerun/issues/12/events", "html_url": "https://github.com/alexch/rerun/issues/12", "id": 2282415, "number": 12, "title": "should detect a \"config.ru\" file and automatically rackup", "user": { "login": "alexch", "id": 8524, "avatar_url": "https://avatars.githubusercontent.com/u/8524?v=1", "gravatar_id": "5a0d7f0cb2fac7858d234de7f7f01491", "url": "https://api.github.com/users/alexch", "html_url": "https://github.com/alexch", "followers_url": "https://api.github.com/users/alexch/followers", "following_url": "https://api.github.com/users/alexch/following{/other_user}", "gists_url": "https://api.github.com/users/alexch/gists{/gist_id}", "starred_url": "https://api.github.com/users/alexch/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/alexch/subscriptions", "organizations_url": "https://api.github.com/users/alexch/orgs", "repos_url": "https://api.github.com/users/alexch/repos", "events_url": "https://api.github.com/users/alexch/events{/privacy}", "received_events_url": "https://api.github.com/users/alexch/received_events", "type": "User", "site_admin": false }, "labels": [ ], "state": "open", "assignee": null, "milestone": null, "comments": 0, "created_at": "2011-11-18T17:24:38Z", "updated_at": "2011-11-18T17:24:38Z", "closed_at": null, "body": "...if no other parameters are specified, of course\r\n\r\n...should decide whether \"rake\" or \"rackup\" take precedence, so this feature request may be impossible\r\n" } ] rerun-0.11.0/lib/000077500000000000000000000000001260522351700134755ustar00rootroot00000000000000rerun-0.11.0/lib/rerun.rb000066400000000000000000000004441260522351700151570ustar00rootroot00000000000000here = File.expand_path(File.dirname(__FILE__)) $: << here unless $:.include?(here) require "listen" # pull in the Listen gem require "rerun/options" require "rerun/system" require "rerun/notification" require "rerun/runner" require "rerun/watcher" require "rerun/glob" module Rerun end rerun-0.11.0/lib/rerun/000077500000000000000000000000001260522351700146305ustar00rootroot00000000000000rerun-0.11.0/lib/rerun/glob.rb000066400000000000000000000033011260522351700160750ustar00rootroot00000000000000# based on http://cpan.uwinnipeg.ca/htdocs/Text-Glob/Text/Glob.pm.html#glob_to_regex_string- # todo: release as separate gem # module Rerun class Glob NO_LEADING_DOT = '(?=[^\.])' # todo START_OF_FILENAME = '(\A|\/)' # beginning of string or a slash END_OF_STRING = '\z' def initialize glob_string @glob_string = glob_string end def to_regexp_string chars = @glob_string.split('') chars = smoosh(chars) curlies = 0 escaping = false string = chars.map do |char| if escaping escaping = false char else case char when '**' "([^/]+/)*" when '*' ".*" when "?" "." when "." "\\." when "{" curlies += 1 "(" when "}" if curlies > 0 curlies -= 1 ")" else char end when "," if curlies > 0 "|" else char end when "\\" escaping = true "\\" else char end end end.join START_OF_FILENAME + string + END_OF_STRING end def to_regexp Regexp.new(to_regexp_string) end def smoosh chars out = [] until chars.empty? char = chars.shift if char == "*" and chars.first == "*" chars.shift chars.shift if chars.first == "/" out.push("**") else out.push(char) end end out end end end rerun-0.11.0/lib/rerun/notification.rb000066400000000000000000000027251260522351700176510ustar00rootroot00000000000000# todo: unit tests module Rerun class Notification include System attr_reader :title, :body, :options def initialize(title, body, options = Options::DEFAULTS.dup) @title = title @body = body @options = options end def command return unless mac? # todo: strategy or subclass s = nil if options[:notify] == true or options[:notify] == "growl" if (cmd = command_named("growlnotify")) # todo: check version of growlnotify and warn if it's too old icon_str = ("--image \"#{icon}\"" if icon) s = "#{cmd} -n \"#{app_name}\" -m \"#{body}\" \"#{app_name} #{title}\" #{icon_str}" end end if s.nil? and options[:notify] == true or options[:notify] == "osx" if (cmd = command_named("terminal-notifier")) icon_str = ("-appIcon \"#{icon}\"" if icon) s = "#{cmd} -title \"#{app_name}\" -message \"#{body}\" \"#{app_name} #{title}\" #{icon_str}" end end s end def command_named(name) path = `which #{name}`.chomp path.empty? ? nil : path end def send(background = true) return unless command `#{command}#{" &" if background}` end def app_name options[:name] end def icon "#{icon_dir}/rails_red_sml.png" if rails? end def icon_dir here = File.expand_path(File.dirname(__FILE__)) File.expand_path("#{here}/../../icons") end end end rerun-0.11.0/lib/rerun/options.rb000066400000000000000000000076201260522351700166550ustar00rootroot00000000000000require 'optparse' require 'pathname' require 'rerun/watcher' libdir = "#{File.expand_path(File.dirname(File.dirname(__FILE__)))}" $spec = Gem::Specification.load(File.join(libdir, "..", "rerun.gemspec")) module Rerun class Options DEFAULT_PATTERN = "**/*.{rb,js,coffee,css,scss,sass,erb,html,haml,ru,yml,slim,md,feature}" DEFAULT_DIRS = ["."] DEFAULTS = { :pattern => DEFAULT_PATTERN, :signal => "TERM", :notify => true, :name => Pathname.getwd.basename.to_s.capitalize, :ignore => [], :dir => DEFAULT_DIRS } def self.parse args = ARGV default_options = DEFAULTS.dup options = { ignore: [] } opts = OptionParser.new("", 24, ' ') do |opts| opts.banner = "Usage: rerun [options] [--] cmd" opts.separator "" opts.separator "Launches an app, and restarts it when the filesystem changes." opts.separator "See http://github.com/alexch/rerun for more info." opts.separator "Version: #{$spec.version}" opts.separator "" opts.separator "Options:" opts.on("-d dir", "--dir dir", "directory to watch, default = \"#{DEFAULT_DIRS}\". Specify multiple paths with ',' or separate '-d dir' option pairs.") do |dir| elements = dir.split(",") options[:dir] = (options[:dir] || []) + elements end # todo: rename to "--watch" opts.on("-p pattern", "--pattern pattern", "file glob to watch, default = \"#{DEFAULTS[:pattern]}\"") do |pattern| options[:pattern] = pattern end opts.on("-i pattern", "--ignore pattern", "file glob to ignore (can be set many times). To ignore a directory, you must append '/*' e.g. --ignore 'coverage/*'") do |pattern| options[:ignore] += [pattern] end opts.on("-s signal", "--signal signal", "terminate process using this signal, default = \"#{DEFAULTS[:signal]}\"") do |signal| options[:signal] = signal end opts.on("-r", "--restart", "expect process to restart itself (uses the HUP signal unless overridden using --signal)") do |signal| options[:restart] = true default_options[:signal] = "HUP" end opts.on("-c", "--clear", "clear screen before each run") do options[:clear] = true end 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| options[:exit] = true end opts.on("-b", "--background", "disable on-the-fly commands, allowing the process to be backgrounded") do options[:background] = true end opts.on("-n name", "--name name", "name of app used in logs and notifications, default = \"#{DEFAULTS[:name]}\"") do |name| options[:name] = name end opts.on("--no-growl", "don't use growl [OBSOLETE]") do options[:growl] = false $stderr.puts "--no-growl is obsolete; use --no-notify instead" return end opts.on("--[no-]notify [notifier]", "send messages through growl (requires growlnotify) or osx (requires terminal-notifier gem)") do |notifier| notifier = true if notifier.nil? options[:notify] = notifier end opts.on_tail("-h", "--help", "--usage", "show this message") do puts opts return end opts.on_tail("--version", "show version") do puts $spec.version return end opts.on_tail "" opts.on_tail "On top of --pattern and --ignore, we ignore any changes to files and dirs starting with a dot." end if args.empty? puts opts nil else opts.parse! args default_options[:cmd] = args.join(" ") options = default_options.merge(options) options end end end end rerun-0.11.0/lib/rerun/runner.rb000066400000000000000000000205731260522351700164750ustar00rootroot00000000000000require 'timeout' require 'io/wait' module Rerun class Runner def self.keep_running(cmd, options) runner = new(cmd, options) runner.start runner.join # apparently runner doesn't keep running anymore (as of Listen 2) so we have to sleep forever :-( sleep 10000 while true # :-( end include System def initialize(run_command, options = {}) @run_command, @options = run_command, options @run_command = "ruby #{@run_command}" if @run_command.split(' ').first =~ /\.rb$/ end def start_keypress_thread return if @options[:background] @keypress_thread = Thread.new do while true if c = key_pressed case c.downcase when 'c' say "Clearing screen" clear_screen when 'r' say "Restarting" restart when 'p' toggle_pause if watcher_running? when 'x', 'q' die break # the break will stop this thread, in case the 'die' doesn't else puts "\n#{c.inspect} pressed inside rerun" puts [["c", "clear screen"], ["r", "restart"], ["p", "toggle pause"], ["x or q", "stop and exit"] ].map{|key, description| " #{key} -- #{description}"}.join("\n") puts end end sleep 1 # todo: use select instead of polling somehow? end end @keypress_thread.run end def stop_keypress_thread @keypress_thread.kill if @keypress_thread @keypress_thread = nil end def restart @restarting = true if @options[:restart] restart_with_signal(@options[:signal]) else stop start end @restarting = false end def watcher_running? @watcher && @watcher.running? end def toggle_pause unless @pausing say "Pausing. Press 'p' again to resume." @watcher.pause @pausing = true else say "Resuming." @watcher.unpause @pausing = false end end def unpause @watcher.unpause end def dir @options[:dir] end def dirs @options[:dir] || "." end def pattern @options[:pattern] end def ignore @options[:ignore] || [] end def clear? @options[:clear] end def exit? @options[:exit] end def app_name @options[:name] end def restart_with_signal(restart_signal) if @pid && (@pid != 0) notify "restarting", "We will be with you shortly." signal(restart_signal) end end def start if windows? raise "Sorry, Rerun does not work on Windows." end if @already_running taglines = [ "Here we go again!", "Keep on trucking.", "Once more unto the breach, dear friends, once more!", "The road goes ever on and on, down from the door where it began.", ] notify "restarted", taglines[rand(taglines.size)] else taglines = [ "To infinity... and beyond!", "Charge!", ] notify "launched", taglines[rand(taglines.size)] @already_running = true end clear_screen if clear? start_keypress_thread unless @keypress_thread @pid = Kernel.fork do begin exec(@run_command) rescue => e puts "#{e.class}: #{e.message}" exit end end status_thread = Process.detach(@pid) # so if the child exits, it dies Signal.trap("INT") do # INT = control-C -- allows user to stop the top-level rerun process die end Signal.trap("TERM") do # TERM is the polite way of terminating a process die end begin sleep 2 rescue Interrupt => e # in case someone hits control-C immediately ("oops!") die end if exit? status = status_thread.value if status.success? notify "succeeded", "" else notify "failed", "Exit status #{status.exitstatus}" end else if !running? notify "Launch Failed", "See console for error output" @already_running = false end end unless @watcher watcher = Watcher.new(:directory => dirs, :pattern => pattern, :ignore => ignore) do |changes| message = change_message(changes) say "Change detected: #{message}" restart unless @restarting end watcher.start @watcher = watcher say "Watching #{dir.join(', ')} for #{pattern}" + (ignore.empty? ? "" : " (ignoring #{ignore.join(',')})") end end def change_message(changes) message = [:modified, :added, :removed].map do |change| count = changes[change] ? changes[change].size : 0 if count > 0 "#{count} #{change}" end end.compact.join(", ") changed_files = changes.values.flatten if changed_files.count > 0 message += ": " message += changes.values.flatten[0..3].map { |path| path.split('/').last }.join(', ') if changed_files.count > 3 message += ", ..." end end message end def die #stop_keypress_thread # don't do this since we're probably *in* the keypress thread stop # stop the child process if it exists exit 0 # todo: status code param end def join @watcher.join end def running? signal(0) end def signal(signal) say "Sending signal #{signal} to #{@pid}" unless signal == 0 Process.kill(signal, @pid) true rescue false end # todo: test escalation def stop default_signal = @options[:signal] || "TERM" if @pid && (@pid != 0) notify "stopping", "All good things must come to an end." unless @restarting begin timeout(5) do # todo: escalation timeout setting # start with a polite SIGTERM signal(default_signal) && Process.wait(@pid) end rescue Timeout::Error begin timeout(5) do # escalate to SIGINT aka control-C since some foolish process may be ignoring SIGTERM signal("INT") && Process.wait(@pid) end rescue Timeout::Error # escalate to SIGKILL aka "kill -9" which cannot be ignored signal("KILL") && Process.wait(@pid) end end end rescue => e false end def git_head_changed? old_git_head = @git_head read_git_head @git_head and old_git_head and @git_head != old_git_head end def read_git_head git_head_file = File.join(dir, '.git', 'HEAD') @git_head = File.exists?(git_head_file) && File.read(git_head_file) end def notify(title, body, background = true) Notification.new(title, body, @options).send(background) if @options[:notify] puts say "#{app_name} #{title}" end def say msg puts "#{Time.now.strftime("%T")} [rerun] #{msg}" end # non-blocking stdin reader. # returns a 1-char string if a key was pressed; otherwise nil # def key_pressed begin # this "raw input" nonsense is because unix likes waiting for linefeeds before sending stdin # 'raw' means turn raw input on # restore proper output newline handling -- see stty.rb and "man stty" and /usr/include/sys/termios.h # looks like "raw" flips off the OPOST bit 0x00000001 /* enable following output processing */ # which disables #define ONLCR 0x00000002 /* map NL to CR-NL (ala CRMOD) */ # so this sets it back on again since all we care about is raw input, not raw output system("stty raw opost") c = nil if $stdin.ready? c = $stdin.getc end c.chr if c ensure system "stty -raw" # turn raw input off end # note: according to 'man tty' the proper way restore the settings is # tty_state=`stty -g` # ensure # system 'stty "#{tty_state}' # end # but this way seems fine and less confusing end def clear_screen # see http://ascii-table.com/ansi-escape-sequences-vt-100.php $stdout.print "\033[H\033[2J" end end end rerun-0.11.0/lib/rerun/system.rb000066400000000000000000000005141260522351700165010ustar00rootroot00000000000000module Rerun module System def mac? RUBY_PLATFORM =~ /darwin/i end def windows? RUBY_PLATFORM =~ /mswin/i end def linux? RUBY_PLATFORM =~ /linux/i end def rails? rails_sig_file = File.expand_path(".")+"/config/boot.rb" File.exists? rails_sig_file end end end rerun-0.11.0/lib/rerun/watcher.rb000066400000000000000000000061611260522351700166160ustar00rootroot00000000000000require 'listen' Thread.abort_on_exception = true # This class will watch a directory and alert you of # new files, modified files, deleted files. # # Now uses the Listen gem, but spawns its own thread on top. # We should probably be accessing the Listen thread directly. # # Author: Alex Chaffee # module Rerun class Watcher InvalidDirectoryError = Class.new(RuntimeError) #def self.default_ignore # Listen::Silencer.new(Listen::Listener.new).send :_default_ignore_patterns #end attr_reader :directory, :pattern, :priority # Create a file system watcher. Start it by calling #start. # # @param options[:directory] the directory to watch (default ".") # @param options[:pattern] the glob pattern to search under the watched directory (default "**/*") # @param options[:priority] the priority of the watcher thread (default 0) # def initialize(options = {}, &client_callback) @client_callback = client_callback options = { :directory => ".", :pattern => "**/*", :priority => 0, }.merge(options) @pattern = options[:pattern] @directories = options[:directory] @directories = sanitize_dirs(@directories) @priority = options[:priority] @ignore = [options[:ignore]].flatten.compact @thread = nil end def sanitize_dirs(dirs) dirs = [*dirs] dirs.map do |d| d.chomp!("/") unless FileTest.exists?(d) && FileTest.readable?(d) && FileTest.directory?(d) raise InvalidDirectoryError, "Directory '#{d}' either doesnt exist or isn't readable" end File.expand_path(d) end end def start if @thread then raise RuntimeError, "already started" end @thread = Thread.new do @listener = Listen.to(*@directories, only: watching, ignore: ignoring, wait_for_delay: 1) do |modified, added, removed| if((modified.size + added.size + removed.size) > 0) @client_callback.call(:modified => modified, :added => added, :removed => removed) end end @listener.start end @thread.priority = @priority sleep 0.1 until @listener at_exit { stop } # try really hard to clean up after ourselves end def watching Rerun::Glob.new(@pattern).to_regexp end def ignoring # todo: --no-ignore-dotfiles dotfiles = /^\.[^.]/ # at beginning of string, a real dot followed by any other character [dotfiles] + @ignore.map { |x| Rerun::Glob.new(x).to_regexp } end # kill the file watcher thread def stop @thread.wakeup rescue ThreadError begin @listener.stop rescue Exception => e puts "#{e.class}: #{e.message} stopping listener" end @thread.kill rescue ThreadError end # wait for the file watcher to finish def join @thread.join if @thread rescue Interrupt => e # don't care end def pause @listener.pause if @listener end def unpause @listener.start if @listener end def running? @listener && @listener.processing? end end end rerun-0.11.0/pulls.json000066400000000000000000002371761260522351700150010ustar00rootroot00000000000000[ { "url": "https://api.github.com/repos/alexch/rerun/pulls/61", "id": 16296103, "html_url": "https://github.com/alexch/rerun/pull/61", "diff_url": "https://github.com/alexch/rerun/pull/61.diff", "patch_url": "https://github.com/alexch/rerun/pull/61.patch", "issue_url": "https://api.github.com/repos/alexch/rerun/issues/61", "number": 61, "state": "open", "title": "load .rerun file from $HOME and project directory in case it exists", "user": { "login": "dagi3d", "id": 11283, "avatar_url": "https://avatars.githubusercontent.com/u/11283?v=1", "gravatar_id": "90ea347c45cdfbc1c5767dd6304d9c10", "url": "https://api.github.com/users/dagi3d", "html_url": "https://github.com/dagi3d", "followers_url": "https://api.github.com/users/dagi3d/followers", "following_url": "https://api.github.com/users/dagi3d/following{/other_user}", "gists_url": "https://api.github.com/users/dagi3d/gists{/gist_id}", "starred_url": "https://api.github.com/users/dagi3d/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/dagi3d/subscriptions", "organizations_url": "https://api.github.com/users/dagi3d/orgs", "repos_url": "https://api.github.com/users/dagi3d/repos", "events_url": "https://api.github.com/users/dagi3d/events{/privacy}", "received_events_url": "https://api.github.com/users/dagi3d/received_events", "type": "User", "site_admin": false }, "body": "Now it loads the .rerun file from the project directory and $HOME in case it exists\r\nCommand line arguments have precedence over the params declared in the project\r\nParams declared in the project directory have precedence over the params in the $HOME directory\r\n\r\n", "created_at": "2014-05-23T21:40:31Z", "updated_at": "2014-06-12T21:45:05Z", "closed_at": null, "merged_at": null, "merge_commit_sha": "3f3c0816b3542de2798aea3cc16fa63064a500ea", "assignee": null, "milestone": null, "commits_url": "https://api.github.com/repos/alexch/rerun/pulls/61/commits", "review_comments_url": "https://api.github.com/repos/alexch/rerun/pulls/61/comments", "review_comment_url": "https://api.github.com/repos/alexch/rerun/pulls/comments/{number}", "comments_url": "https://api.github.com/repos/alexch/rerun/issues/61/comments", "statuses_url": "https://api.github.com/repos/alexch/rerun/statuses/dd4498d4a5236ceeb102fab2612bd5f18e7617bd", "head": { "label": "dagi3d:master", "ref": "master", "sha": "dd4498d4a5236ceeb102fab2612bd5f18e7617bd", "user": { "login": "dagi3d", "id": 11283, "avatar_url": "https://avatars.githubusercontent.com/u/11283?v=1", "gravatar_id": "90ea347c45cdfbc1c5767dd6304d9c10", "url": "https://api.github.com/users/dagi3d", "html_url": "https://github.com/dagi3d", "followers_url": "https://api.github.com/users/dagi3d/followers", "following_url": "https://api.github.com/users/dagi3d/following{/other_user}", "gists_url": "https://api.github.com/users/dagi3d/gists{/gist_id}", "starred_url": "https://api.github.com/users/dagi3d/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/dagi3d/subscriptions", "organizations_url": "https://api.github.com/users/dagi3d/orgs", "repos_url": "https://api.github.com/users/dagi3d/repos", "events_url": "https://api.github.com/users/dagi3d/events{/privacy}", "received_events_url": "https://api.github.com/users/dagi3d/received_events", "type": "User", "site_admin": false }, "repo": { "id": 20039153, "name": "rerun", "full_name": "dagi3d/rerun", "owner": { "login": "dagi3d", "id": 11283, "avatar_url": "https://avatars.githubusercontent.com/u/11283?v=1", "gravatar_id": "90ea347c45cdfbc1c5767dd6304d9c10", "url": "https://api.github.com/users/dagi3d", "html_url": "https://github.com/dagi3d", "followers_url": "https://api.github.com/users/dagi3d/followers", "following_url": "https://api.github.com/users/dagi3d/following{/other_user}", "gists_url": "https://api.github.com/users/dagi3d/gists{/gist_id}", "starred_url": "https://api.github.com/users/dagi3d/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/dagi3d/subscriptions", "organizations_url": "https://api.github.com/users/dagi3d/orgs", "repos_url": "https://api.github.com/users/dagi3d/repos", "events_url": "https://api.github.com/users/dagi3d/events{/privacy}", "received_events_url": "https://api.github.com/users/dagi3d/received_events", "type": "User", "site_admin": false }, "private": false, "html_url": "https://github.com/dagi3d/rerun", "description": "Restarts an app when the filesystem changes. Uses growl and FSEventStream if on OS X.", "fork": true, "url": "https://api.github.com/repos/dagi3d/rerun", "forks_url": "https://api.github.com/repos/dagi3d/rerun/forks", "keys_url": "https://api.github.com/repos/dagi3d/rerun/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/dagi3d/rerun/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/dagi3d/rerun/teams", "hooks_url": "https://api.github.com/repos/dagi3d/rerun/hooks", "issue_events_url": "https://api.github.com/repos/dagi3d/rerun/issues/events{/number}", "events_url": "https://api.github.com/repos/dagi3d/rerun/events", "assignees_url": "https://api.github.com/repos/dagi3d/rerun/assignees{/user}", "branches_url": "https://api.github.com/repos/dagi3d/rerun/branches{/branch}", "tags_url": "https://api.github.com/repos/dagi3d/rerun/tags", "blobs_url": "https://api.github.com/repos/dagi3d/rerun/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/dagi3d/rerun/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/dagi3d/rerun/git/refs{/sha}", "trees_url": "https://api.github.com/repos/dagi3d/rerun/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/dagi3d/rerun/statuses/{sha}", "languages_url": "https://api.github.com/repos/dagi3d/rerun/languages", "stargazers_url": "https://api.github.com/repos/dagi3d/rerun/stargazers", "contributors_url": "https://api.github.com/repos/dagi3d/rerun/contributors", "subscribers_url": "https://api.github.com/repos/dagi3d/rerun/subscribers", "subscription_url": "https://api.github.com/repos/dagi3d/rerun/subscription", "commits_url": "https://api.github.com/repos/dagi3d/rerun/commits{/sha}", "git_commits_url": "https://api.github.com/repos/dagi3d/rerun/git/commits{/sha}", "comments_url": "https://api.github.com/repos/dagi3d/rerun/comments{/number}", "issue_comment_url": "https://api.github.com/repos/dagi3d/rerun/issues/comments/{number}", "contents_url": "https://api.github.com/repos/dagi3d/rerun/contents/{+path}", "compare_url": "https://api.github.com/repos/dagi3d/rerun/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/dagi3d/rerun/merges", "archive_url": "https://api.github.com/repos/dagi3d/rerun/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/dagi3d/rerun/downloads", "issues_url": "https://api.github.com/repos/dagi3d/rerun/issues{/number}", "pulls_url": "https://api.github.com/repos/dagi3d/rerun/pulls{/number}", "milestones_url": "https://api.github.com/repos/dagi3d/rerun/milestones{/number}", "notifications_url": "https://api.github.com/repos/dagi3d/rerun/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/dagi3d/rerun/labels{/name}", "releases_url": "https://api.github.com/repos/dagi3d/rerun/releases{/id}", "created_at": "2014-05-21T22:10:20Z", "updated_at": "2014-05-23T21:40:31Z", "pushed_at": "2014-05-23T21:35:42Z", "git_url": "git://github.com/dagi3d/rerun.git", "ssh_url": "git@github.com:dagi3d/rerun.git", "clone_url": "https://github.com/dagi3d/rerun.git", "svn_url": "https://github.com/dagi3d/rerun", "homepage": "", "size": 328, "stargazers_count": 0, "watchers_count": 0, "language": "Ruby", "has_issues": false, "has_downloads": true, "has_wiki": true, "forks_count": 0, "mirror_url": null, "open_issues_count": 0, "forks": 0, "open_issues": 0, "watchers": 0, "default_branch": "master" } }, "base": { "label": "alexch:master", "ref": "master", "sha": "43bfadea9006da31ff965985ecbedea56fe05847", "user": { "login": "alexch", "id": 8524, "avatar_url": "https://avatars.githubusercontent.com/u/8524?v=1", "gravatar_id": "5a0d7f0cb2fac7858d234de7f7f01491", "url": "https://api.github.com/users/alexch", "html_url": "https://github.com/alexch", "followers_url": "https://api.github.com/users/alexch/followers", "following_url": "https://api.github.com/users/alexch/following{/other_user}", "gists_url": "https://api.github.com/users/alexch/gists{/gist_id}", "starred_url": "https://api.github.com/users/alexch/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/alexch/subscriptions", "organizations_url": "https://api.github.com/users/alexch/orgs", "repos_url": "https://api.github.com/users/alexch/repos", "events_url": "https://api.github.com/users/alexch/events{/privacy}", "received_events_url": "https://api.github.com/users/alexch/received_events", "type": "User", "site_admin": false }, "repo": { "id": 221696, "name": "rerun", "full_name": "alexch/rerun", "owner": { "login": "alexch", "id": 8524, "avatar_url": "https://avatars.githubusercontent.com/u/8524?v=1", "gravatar_id": "5a0d7f0cb2fac7858d234de7f7f01491", "url": "https://api.github.com/users/alexch", "html_url": "https://github.com/alexch", "followers_url": "https://api.github.com/users/alexch/followers", "following_url": "https://api.github.com/users/alexch/following{/other_user}", "gists_url": "https://api.github.com/users/alexch/gists{/gist_id}", "starred_url": "https://api.github.com/users/alexch/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/alexch/subscriptions", "organizations_url": "https://api.github.com/users/alexch/orgs", "repos_url": "https://api.github.com/users/alexch/repos", "events_url": "https://api.github.com/users/alexch/events{/privacy}", "received_events_url": "https://api.github.com/users/alexch/received_events", "type": "User", "site_admin": false }, "private": false, "html_url": "https://github.com/alexch/rerun", "description": "Restarts an app when the filesystem changes. Uses growl and FSEventStream if on OS X.", "fork": false, "url": "https://api.github.com/repos/alexch/rerun", "forks_url": "https://api.github.com/repos/alexch/rerun/forks", "keys_url": "https://api.github.com/repos/alexch/rerun/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/alexch/rerun/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/alexch/rerun/teams", "hooks_url": "https://api.github.com/repos/alexch/rerun/hooks", "issue_events_url": "https://api.github.com/repos/alexch/rerun/issues/events{/number}", "events_url": "https://api.github.com/repos/alexch/rerun/events", "assignees_url": "https://api.github.com/repos/alexch/rerun/assignees{/user}", "branches_url": "https://api.github.com/repos/alexch/rerun/branches{/branch}", "tags_url": "https://api.github.com/repos/alexch/rerun/tags", "blobs_url": "https://api.github.com/repos/alexch/rerun/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/alexch/rerun/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/alexch/rerun/git/refs{/sha}", "trees_url": "https://api.github.com/repos/alexch/rerun/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/alexch/rerun/statuses/{sha}", "languages_url": "https://api.github.com/repos/alexch/rerun/languages", "stargazers_url": "https://api.github.com/repos/alexch/rerun/stargazers", "contributors_url": "https://api.github.com/repos/alexch/rerun/contributors", "subscribers_url": "https://api.github.com/repos/alexch/rerun/subscribers", "subscription_url": "https://api.github.com/repos/alexch/rerun/subscription", "commits_url": "https://api.github.com/repos/alexch/rerun/commits{/sha}", "git_commits_url": "https://api.github.com/repos/alexch/rerun/git/commits{/sha}", "comments_url": "https://api.github.com/repos/alexch/rerun/comments{/number}", "issue_comment_url": "https://api.github.com/repos/alexch/rerun/issues/comments/{number}", "contents_url": "https://api.github.com/repos/alexch/rerun/contents/{+path}", "compare_url": "https://api.github.com/repos/alexch/rerun/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/alexch/rerun/merges", "archive_url": "https://api.github.com/repos/alexch/rerun/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/alexch/rerun/downloads", "issues_url": "https://api.github.com/repos/alexch/rerun/issues{/number}", "pulls_url": "https://api.github.com/repos/alexch/rerun/pulls{/number}", "milestones_url": "https://api.github.com/repos/alexch/rerun/milestones{/number}", "notifications_url": "https://api.github.com/repos/alexch/rerun/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/alexch/rerun/labels{/name}", "releases_url": "https://api.github.com/repos/alexch/rerun/releases{/id}", "created_at": "2009-06-08T15:59:27Z", "updated_at": "2014-07-28T07:08:07Z", "pushed_at": "2014-05-05T15:09:08Z", "git_url": "git://github.com/alexch/rerun.git", "ssh_url": "git@github.com:alexch/rerun.git", "clone_url": "https://github.com/alexch/rerun.git", "svn_url": "https://github.com/alexch/rerun", "homepage": "", "size": 744, "stargazers_count": 382, "watchers_count": 382, "language": "Ruby", "has_issues": true, "has_downloads": true, "has_wiki": true, "forks_count": 29, "mirror_url": null, "open_issues_count": 22, "forks": 29, "open_issues": 22, "watchers": 382, "default_branch": "master" } }, "_links": { "self": { "href": "https://api.github.com/repos/alexch/rerun/pulls/61" }, "html": { "href": "https://github.com/alexch/rerun/pull/61" }, "issue": { "href": "https://api.github.com/repos/alexch/rerun/issues/61" }, "comments": { "href": "https://api.github.com/repos/alexch/rerun/issues/61/comments" }, "review_comments": { "href": "https://api.github.com/repos/alexch/rerun/pulls/61/comments" }, "review_comment": { "href": "https://api.github.com/repos/alexch/rerun/pulls/comments/{number}" }, "commits": { "href": "https://api.github.com/repos/alexch/rerun/pulls/61/commits" }, "statuses": { "href": "https://api.github.com/repos/alexch/rerun/statuses/dd4498d4a5236ceeb102fab2612bd5f18e7617bd" } } }, { "url": "https://api.github.com/repos/alexch/rerun/pulls/58", "id": 14990763, "html_url": "https://github.com/alexch/rerun/pull/58", "diff_url": "https://github.com/alexch/rerun/pull/58.diff", "patch_url": "https://github.com/alexch/rerun/pull/58.patch", "issue_url": "https://api.github.com/repos/alexch/rerun/issues/58", "number": 58, "state": "open", "title": "add --ignore-dotfiles and disable ignoring by default", "user": { "login": "robbles", "id": 92927, "avatar_url": "https://avatars.githubusercontent.com/u/92927?v=1", "gravatar_id": "33cd4933e841cf3c03ee8a3aed0585f7", "url": "https://api.github.com/users/robbles", "html_url": "https://github.com/robbles", "followers_url": "https://api.github.com/users/robbles/followers", "following_url": "https://api.github.com/users/robbles/following{/other_user}", "gists_url": "https://api.github.com/users/robbles/gists{/gist_id}", "starred_url": "https://api.github.com/users/robbles/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/robbles/subscriptions", "organizations_url": "https://api.github.com/users/robbles/orgs", "repos_url": "https://api.github.com/users/robbles/repos", "events_url": "https://api.github.com/users/robbles/events{/privacy}", "received_events_url": "https://api.github.com/users/robbles/received_events", "type": "User", "site_admin": false }, "body": "I added an option to enable the filtering of dotfiles. It's disabled by default, because otherwise it's impossible with the current setup to detect changes to them (because of the order in which Listen finds & filters files).\r\n\r\nIf you think it should be enabled by default though, I'm open to changing this though.", "created_at": "2014-04-21T23:51:58Z", "updated_at": "2014-06-12T21:43:05Z", "closed_at": null, "merged_at": null, "merge_commit_sha": "bf34d1f5520d5b2abe576b5eea8d60ad74710990", "assignee": null, "milestone": null, "commits_url": "https://api.github.com/repos/alexch/rerun/pulls/58/commits", "review_comments_url": "https://api.github.com/repos/alexch/rerun/pulls/58/comments", "review_comment_url": "https://api.github.com/repos/alexch/rerun/pulls/comments/{number}", "comments_url": "https://api.github.com/repos/alexch/rerun/issues/58/comments", "statuses_url": "https://api.github.com/repos/alexch/rerun/statuses/d5ec3d6060f3d3ed77508646a19e532a8e331bdd", "head": { "label": "robbles:master", "ref": "master", "sha": "d5ec3d6060f3d3ed77508646a19e532a8e331bdd", "user": { "login": "robbles", "id": 92927, "avatar_url": "https://avatars.githubusercontent.com/u/92927?v=1", "gravatar_id": "33cd4933e841cf3c03ee8a3aed0585f7", "url": "https://api.github.com/users/robbles", "html_url": "https://github.com/robbles", "followers_url": "https://api.github.com/users/robbles/followers", "following_url": "https://api.github.com/users/robbles/following{/other_user}", "gists_url": "https://api.github.com/users/robbles/gists{/gist_id}", "starred_url": "https://api.github.com/users/robbles/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/robbles/subscriptions", "organizations_url": "https://api.github.com/users/robbles/orgs", "repos_url": "https://api.github.com/users/robbles/repos", "events_url": "https://api.github.com/users/robbles/events{/privacy}", "received_events_url": "https://api.github.com/users/robbles/received_events", "type": "User", "site_admin": false }, "repo": { "id": 18780328, "name": "rerun", "full_name": "robbles/rerun", "owner": { "login": "robbles", "id": 92927, "avatar_url": "https://avatars.githubusercontent.com/u/92927?v=1", "gravatar_id": "33cd4933e841cf3c03ee8a3aed0585f7", "url": "https://api.github.com/users/robbles", "html_url": "https://github.com/robbles", "followers_url": "https://api.github.com/users/robbles/followers", "following_url": "https://api.github.com/users/robbles/following{/other_user}", "gists_url": "https://api.github.com/users/robbles/gists{/gist_id}", "starred_url": "https://api.github.com/users/robbles/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/robbles/subscriptions", "organizations_url": "https://api.github.com/users/robbles/orgs", "repos_url": "https://api.github.com/users/robbles/repos", "events_url": "https://api.github.com/users/robbles/events{/privacy}", "received_events_url": "https://api.github.com/users/robbles/received_events", "type": "User", "site_admin": false }, "private": false, "html_url": "https://github.com/robbles/rerun", "description": "Restarts an app when the filesystem changes. Uses growl and FSEventStream if on OS X.", "fork": true, "url": "https://api.github.com/repos/robbles/rerun", "forks_url": "https://api.github.com/repos/robbles/rerun/forks", "keys_url": "https://api.github.com/repos/robbles/rerun/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/robbles/rerun/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/robbles/rerun/teams", "hooks_url": "https://api.github.com/repos/robbles/rerun/hooks", "issue_events_url": "https://api.github.com/repos/robbles/rerun/issues/events{/number}", "events_url": "https://api.github.com/repos/robbles/rerun/events", "assignees_url": "https://api.github.com/repos/robbles/rerun/assignees{/user}", "branches_url": "https://api.github.com/repos/robbles/rerun/branches{/branch}", "tags_url": "https://api.github.com/repos/robbles/rerun/tags", "blobs_url": "https://api.github.com/repos/robbles/rerun/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/robbles/rerun/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/robbles/rerun/git/refs{/sha}", "trees_url": "https://api.github.com/repos/robbles/rerun/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/robbles/rerun/statuses/{sha}", "languages_url": "https://api.github.com/repos/robbles/rerun/languages", "stargazers_url": "https://api.github.com/repos/robbles/rerun/stargazers", "contributors_url": "https://api.github.com/repos/robbles/rerun/contributors", "subscribers_url": "https://api.github.com/repos/robbles/rerun/subscribers", "subscription_url": "https://api.github.com/repos/robbles/rerun/subscription", "commits_url": "https://api.github.com/repos/robbles/rerun/commits{/sha}", "git_commits_url": "https://api.github.com/repos/robbles/rerun/git/commits{/sha}", "comments_url": "https://api.github.com/repos/robbles/rerun/comments{/number}", "issue_comment_url": "https://api.github.com/repos/robbles/rerun/issues/comments/{number}", "contents_url": "https://api.github.com/repos/robbles/rerun/contents/{+path}", "compare_url": "https://api.github.com/repos/robbles/rerun/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/robbles/rerun/merges", "archive_url": "https://api.github.com/repos/robbles/rerun/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/robbles/rerun/downloads", "issues_url": "https://api.github.com/repos/robbles/rerun/issues{/number}", "pulls_url": "https://api.github.com/repos/robbles/rerun/pulls{/number}", "milestones_url": "https://api.github.com/repos/robbles/rerun/milestones{/number}", "notifications_url": "https://api.github.com/repos/robbles/rerun/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/robbles/rerun/labels{/name}", "releases_url": "https://api.github.com/repos/robbles/rerun/releases{/id}", "created_at": "2014-04-14T23:22:08Z", "updated_at": "2014-04-21T23:51:58Z", "pushed_at": "2014-04-21T23:43:38Z", "git_url": "git://github.com/robbles/rerun.git", "ssh_url": "git@github.com:robbles/rerun.git", "clone_url": "https://github.com/robbles/rerun.git", "svn_url": "https://github.com/robbles/rerun", "homepage": "", "size": 300, "stargazers_count": 0, "watchers_count": 0, "language": "Ruby", "has_issues": false, "has_downloads": true, "has_wiki": true, "forks_count": 0, "mirror_url": null, "open_issues_count": 0, "forks": 0, "open_issues": 0, "watchers": 0, "default_branch": "master" } }, "base": { "label": "alexch:master", "ref": "master", "sha": "a7fd980db79b56e9e06bafe928e003562b7a48af", "user": { "login": "alexch", "id": 8524, "avatar_url": "https://avatars.githubusercontent.com/u/8524?v=1", "gravatar_id": "5a0d7f0cb2fac7858d234de7f7f01491", "url": "https://api.github.com/users/alexch", "html_url": "https://github.com/alexch", "followers_url": "https://api.github.com/users/alexch/followers", "following_url": "https://api.github.com/users/alexch/following{/other_user}", "gists_url": "https://api.github.com/users/alexch/gists{/gist_id}", "starred_url": "https://api.github.com/users/alexch/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/alexch/subscriptions", "organizations_url": "https://api.github.com/users/alexch/orgs", "repos_url": "https://api.github.com/users/alexch/repos", "events_url": "https://api.github.com/users/alexch/events{/privacy}", "received_events_url": "https://api.github.com/users/alexch/received_events", "type": "User", "site_admin": false }, "repo": { "id": 221696, "name": "rerun", "full_name": "alexch/rerun", "owner": { "login": "alexch", "id": 8524, "avatar_url": "https://avatars.githubusercontent.com/u/8524?v=1", "gravatar_id": "5a0d7f0cb2fac7858d234de7f7f01491", "url": "https://api.github.com/users/alexch", "html_url": "https://github.com/alexch", "followers_url": "https://api.github.com/users/alexch/followers", "following_url": "https://api.github.com/users/alexch/following{/other_user}", "gists_url": "https://api.github.com/users/alexch/gists{/gist_id}", "starred_url": "https://api.github.com/users/alexch/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/alexch/subscriptions", "organizations_url": "https://api.github.com/users/alexch/orgs", "repos_url": "https://api.github.com/users/alexch/repos", "events_url": "https://api.github.com/users/alexch/events{/privacy}", "received_events_url": "https://api.github.com/users/alexch/received_events", "type": "User", "site_admin": false }, "private": false, "html_url": "https://github.com/alexch/rerun", "description": "Restarts an app when the filesystem changes. Uses growl and FSEventStream if on OS X.", "fork": false, "url": "https://api.github.com/repos/alexch/rerun", "forks_url": "https://api.github.com/repos/alexch/rerun/forks", "keys_url": "https://api.github.com/repos/alexch/rerun/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/alexch/rerun/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/alexch/rerun/teams", "hooks_url": "https://api.github.com/repos/alexch/rerun/hooks", "issue_events_url": "https://api.github.com/repos/alexch/rerun/issues/events{/number}", "events_url": "https://api.github.com/repos/alexch/rerun/events", "assignees_url": "https://api.github.com/repos/alexch/rerun/assignees{/user}", "branches_url": "https://api.github.com/repos/alexch/rerun/branches{/branch}", "tags_url": "https://api.github.com/repos/alexch/rerun/tags", "blobs_url": "https://api.github.com/repos/alexch/rerun/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/alexch/rerun/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/alexch/rerun/git/refs{/sha}", "trees_url": "https://api.github.com/repos/alexch/rerun/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/alexch/rerun/statuses/{sha}", "languages_url": "https://api.github.com/repos/alexch/rerun/languages", "stargazers_url": "https://api.github.com/repos/alexch/rerun/stargazers", "contributors_url": "https://api.github.com/repos/alexch/rerun/contributors", "subscribers_url": "https://api.github.com/repos/alexch/rerun/subscribers", "subscription_url": "https://api.github.com/repos/alexch/rerun/subscription", "commits_url": "https://api.github.com/repos/alexch/rerun/commits{/sha}", "git_commits_url": "https://api.github.com/repos/alexch/rerun/git/commits{/sha}", "comments_url": "https://api.github.com/repos/alexch/rerun/comments{/number}", "issue_comment_url": "https://api.github.com/repos/alexch/rerun/issues/comments/{number}", "contents_url": "https://api.github.com/repos/alexch/rerun/contents/{+path}", "compare_url": "https://api.github.com/repos/alexch/rerun/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/alexch/rerun/merges", "archive_url": "https://api.github.com/repos/alexch/rerun/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/alexch/rerun/downloads", "issues_url": "https://api.github.com/repos/alexch/rerun/issues{/number}", "pulls_url": "https://api.github.com/repos/alexch/rerun/pulls{/number}", "milestones_url": "https://api.github.com/repos/alexch/rerun/milestones{/number}", "notifications_url": "https://api.github.com/repos/alexch/rerun/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/alexch/rerun/labels{/name}", "releases_url": "https://api.github.com/repos/alexch/rerun/releases{/id}", "created_at": "2009-06-08T15:59:27Z", "updated_at": "2014-07-28T07:08:07Z", "pushed_at": "2014-05-05T15:09:08Z", "git_url": "git://github.com/alexch/rerun.git", "ssh_url": "git@github.com:alexch/rerun.git", "clone_url": "https://github.com/alexch/rerun.git", "svn_url": "https://github.com/alexch/rerun", "homepage": "", "size": 744, "stargazers_count": 382, "watchers_count": 382, "language": "Ruby", "has_issues": true, "has_downloads": true, "has_wiki": true, "forks_count": 29, "mirror_url": null, "open_issues_count": 22, "forks": 29, "open_issues": 22, "watchers": 382, "default_branch": "master" } }, "_links": { "self": { "href": "https://api.github.com/repos/alexch/rerun/pulls/58" }, "html": { "href": "https://github.com/alexch/rerun/pull/58" }, "issue": { "href": "https://api.github.com/repos/alexch/rerun/issues/58" }, "comments": { "href": "https://api.github.com/repos/alexch/rerun/issues/58/comments" }, "review_comments": { "href": "https://api.github.com/repos/alexch/rerun/pulls/58/comments" }, "review_comment": { "href": "https://api.github.com/repos/alexch/rerun/pulls/comments/{number}" }, "commits": { "href": "https://api.github.com/repos/alexch/rerun/pulls/58/commits" }, "statuses": { "href": "https://api.github.com/repos/alexch/rerun/statuses/d5ec3d6060f3d3ed77508646a19e532a8e331bdd" } } }, { "url": "https://api.github.com/repos/alexch/rerun/pulls/56", "id": 13832440, "html_url": "https://github.com/alexch/rerun/pull/56", "diff_url": "https://github.com/alexch/rerun/pull/56.diff", "patch_url": "https://github.com/alexch/rerun/pull/56.patch", "issue_url": "https://api.github.com/repos/alexch/rerun/issues/56", "number": 56, "state": "open", "title": "Add feature files to default pattern and update README", "user": { "login": "jmuheim", "id": 1814983, "avatar_url": "https://avatars.githubusercontent.com/u/1814983?v=1", "gravatar_id": "fc582698581884352e745d1d4c64699d", "url": "https://api.github.com/users/jmuheim", "html_url": "https://github.com/jmuheim", "followers_url": "https://api.github.com/users/jmuheim/followers", "following_url": "https://api.github.com/users/jmuheim/following{/other_user}", "gists_url": "https://api.github.com/users/jmuheim/gists{/gist_id}", "starred_url": "https://api.github.com/users/jmuheim/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/jmuheim/subscriptions", "organizations_url": "https://api.github.com/users/jmuheim/orgs", "repos_url": "https://api.github.com/users/jmuheim/repos", "events_url": "https://api.github.com/users/jmuheim/events{/privacy}", "received_events_url": "https://api.github.com/users/jmuheim/received_events", "type": "User", "site_admin": false }, "body": "`xxx.feature` files are commonly used for Gherkin based stuff, e.g. Cucumber or Turnip feature tests.\r\n\r\nI also noticed that your README wasn't up2date and fixed it.", "created_at": "2014-03-21T11:59:27Z", "updated_at": "2014-06-19T07:01:48Z", "closed_at": null, "merged_at": null, "merge_commit_sha": "c123ff17f966c306f4afff81609279d9fcace31f", "assignee": null, "milestone": null, "commits_url": "https://api.github.com/repos/alexch/rerun/pulls/56/commits", "review_comments_url": "https://api.github.com/repos/alexch/rerun/pulls/56/comments", "review_comment_url": "https://api.github.com/repos/alexch/rerun/pulls/comments/{number}", "comments_url": "https://api.github.com/repos/alexch/rerun/issues/56/comments", "statuses_url": "https://api.github.com/repos/alexch/rerun/statuses/1092c30ea86331bddb01b6afe28cada3d6f8f7ab", "head": { "label": "jmuheim:master", "ref": "master", "sha": "1092c30ea86331bddb01b6afe28cada3d6f8f7ab", "user": { "login": "jmuheim", "id": 1814983, "avatar_url": "https://avatars.githubusercontent.com/u/1814983?v=1", "gravatar_id": "fc582698581884352e745d1d4c64699d", "url": "https://api.github.com/users/jmuheim", "html_url": "https://github.com/jmuheim", "followers_url": "https://api.github.com/users/jmuheim/followers", "following_url": "https://api.github.com/users/jmuheim/following{/other_user}", "gists_url": "https://api.github.com/users/jmuheim/gists{/gist_id}", "starred_url": "https://api.github.com/users/jmuheim/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/jmuheim/subscriptions", "organizations_url": "https://api.github.com/users/jmuheim/orgs", "repos_url": "https://api.github.com/users/jmuheim/repos", "events_url": "https://api.github.com/users/jmuheim/events{/privacy}", "received_events_url": "https://api.github.com/users/jmuheim/received_events", "type": "User", "site_admin": false }, "repo": { "id": 17978433, "name": "rerun", "full_name": "jmuheim/rerun", "owner": { "login": "jmuheim", "id": 1814983, "avatar_url": "https://avatars.githubusercontent.com/u/1814983?v=1", "gravatar_id": "fc582698581884352e745d1d4c64699d", "url": "https://api.github.com/users/jmuheim", "html_url": "https://github.com/jmuheim", "followers_url": "https://api.github.com/users/jmuheim/followers", "following_url": "https://api.github.com/users/jmuheim/following{/other_user}", "gists_url": "https://api.github.com/users/jmuheim/gists{/gist_id}", "starred_url": "https://api.github.com/users/jmuheim/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/jmuheim/subscriptions", "organizations_url": "https://api.github.com/users/jmuheim/orgs", "repos_url": "https://api.github.com/users/jmuheim/repos", "events_url": "https://api.github.com/users/jmuheim/events{/privacy}", "received_events_url": "https://api.github.com/users/jmuheim/received_events", "type": "User", "site_admin": false }, "private": false, "html_url": "https://github.com/jmuheim/rerun", "description": "Restarts an app when the filesystem changes. Uses growl and FSEventStream if on OS X.", "fork": true, "url": "https://api.github.com/repos/jmuheim/rerun", "forks_url": "https://api.github.com/repos/jmuheim/rerun/forks", "keys_url": "https://api.github.com/repos/jmuheim/rerun/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/jmuheim/rerun/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/jmuheim/rerun/teams", "hooks_url": "https://api.github.com/repos/jmuheim/rerun/hooks", "issue_events_url": "https://api.github.com/repos/jmuheim/rerun/issues/events{/number}", "events_url": "https://api.github.com/repos/jmuheim/rerun/events", "assignees_url": "https://api.github.com/repos/jmuheim/rerun/assignees{/user}", "branches_url": "https://api.github.com/repos/jmuheim/rerun/branches{/branch}", "tags_url": "https://api.github.com/repos/jmuheim/rerun/tags", "blobs_url": "https://api.github.com/repos/jmuheim/rerun/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/jmuheim/rerun/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/jmuheim/rerun/git/refs{/sha}", "trees_url": "https://api.github.com/repos/jmuheim/rerun/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/jmuheim/rerun/statuses/{sha}", "languages_url": "https://api.github.com/repos/jmuheim/rerun/languages", "stargazers_url": "https://api.github.com/repos/jmuheim/rerun/stargazers", "contributors_url": "https://api.github.com/repos/jmuheim/rerun/contributors", "subscribers_url": "https://api.github.com/repos/jmuheim/rerun/subscribers", "subscription_url": "https://api.github.com/repos/jmuheim/rerun/subscription", "commits_url": "https://api.github.com/repos/jmuheim/rerun/commits{/sha}", "git_commits_url": "https://api.github.com/repos/jmuheim/rerun/git/commits{/sha}", "comments_url": "https://api.github.com/repos/jmuheim/rerun/comments{/number}", "issue_comment_url": "https://api.github.com/repos/jmuheim/rerun/issues/comments/{number}", "contents_url": "https://api.github.com/repos/jmuheim/rerun/contents/{+path}", "compare_url": "https://api.github.com/repos/jmuheim/rerun/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/jmuheim/rerun/merges", "archive_url": "https://api.github.com/repos/jmuheim/rerun/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/jmuheim/rerun/downloads", "issues_url": "https://api.github.com/repos/jmuheim/rerun/issues{/number}", "pulls_url": "https://api.github.com/repos/jmuheim/rerun/pulls{/number}", "milestones_url": "https://api.github.com/repos/jmuheim/rerun/milestones{/number}", "notifications_url": "https://api.github.com/repos/jmuheim/rerun/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/jmuheim/rerun/labels{/name}", "releases_url": "https://api.github.com/repos/jmuheim/rerun/releases{/id}", "created_at": "2014-03-21T11:54:15Z", "updated_at": "2014-03-21T11:59:27Z", "pushed_at": "2014-03-21T11:58:31Z", "git_url": "git://github.com/jmuheim/rerun.git", "ssh_url": "git@github.com:jmuheim/rerun.git", "clone_url": "https://github.com/jmuheim/rerun.git", "svn_url": "https://github.com/jmuheim/rerun", "homepage": "", "size": 299, "stargazers_count": 0, "watchers_count": 0, "language": "Ruby", "has_issues": false, "has_downloads": true, "has_wiki": true, "forks_count": 0, "mirror_url": null, "open_issues_count": 0, "forks": 0, "open_issues": 0, "watchers": 0, "default_branch": "master" } }, "base": { "label": "alexch:master", "ref": "master", "sha": "a7fd980db79b56e9e06bafe928e003562b7a48af", "user": { "login": "alexch", "id": 8524, "avatar_url": "https://avatars.githubusercontent.com/u/8524?v=1", "gravatar_id": "5a0d7f0cb2fac7858d234de7f7f01491", "url": "https://api.github.com/users/alexch", "html_url": "https://github.com/alexch", "followers_url": "https://api.github.com/users/alexch/followers", "following_url": "https://api.github.com/users/alexch/following{/other_user}", "gists_url": "https://api.github.com/users/alexch/gists{/gist_id}", "starred_url": "https://api.github.com/users/alexch/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/alexch/subscriptions", "organizations_url": "https://api.github.com/users/alexch/orgs", "repos_url": "https://api.github.com/users/alexch/repos", "events_url": "https://api.github.com/users/alexch/events{/privacy}", "received_events_url": "https://api.github.com/users/alexch/received_events", "type": "User", "site_admin": false }, "repo": { "id": 221696, "name": "rerun", "full_name": "alexch/rerun", "owner": { "login": "alexch", "id": 8524, "avatar_url": "https://avatars.githubusercontent.com/u/8524?v=1", "gravatar_id": "5a0d7f0cb2fac7858d234de7f7f01491", "url": "https://api.github.com/users/alexch", "html_url": "https://github.com/alexch", "followers_url": "https://api.github.com/users/alexch/followers", "following_url": "https://api.github.com/users/alexch/following{/other_user}", "gists_url": "https://api.github.com/users/alexch/gists{/gist_id}", "starred_url": "https://api.github.com/users/alexch/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/alexch/subscriptions", "organizations_url": "https://api.github.com/users/alexch/orgs", "repos_url": "https://api.github.com/users/alexch/repos", "events_url": "https://api.github.com/users/alexch/events{/privacy}", "received_events_url": "https://api.github.com/users/alexch/received_events", "type": "User", "site_admin": false }, "private": false, "html_url": "https://github.com/alexch/rerun", "description": "Restarts an app when the filesystem changes. Uses growl and FSEventStream if on OS X.", "fork": false, "url": "https://api.github.com/repos/alexch/rerun", "forks_url": "https://api.github.com/repos/alexch/rerun/forks", "keys_url": "https://api.github.com/repos/alexch/rerun/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/alexch/rerun/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/alexch/rerun/teams", "hooks_url": "https://api.github.com/repos/alexch/rerun/hooks", "issue_events_url": "https://api.github.com/repos/alexch/rerun/issues/events{/number}", "events_url": "https://api.github.com/repos/alexch/rerun/events", "assignees_url": "https://api.github.com/repos/alexch/rerun/assignees{/user}", "branches_url": "https://api.github.com/repos/alexch/rerun/branches{/branch}", "tags_url": "https://api.github.com/repos/alexch/rerun/tags", "blobs_url": "https://api.github.com/repos/alexch/rerun/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/alexch/rerun/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/alexch/rerun/git/refs{/sha}", "trees_url": "https://api.github.com/repos/alexch/rerun/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/alexch/rerun/statuses/{sha}", "languages_url": "https://api.github.com/repos/alexch/rerun/languages", "stargazers_url": "https://api.github.com/repos/alexch/rerun/stargazers", "contributors_url": "https://api.github.com/repos/alexch/rerun/contributors", "subscribers_url": "https://api.github.com/repos/alexch/rerun/subscribers", "subscription_url": "https://api.github.com/repos/alexch/rerun/subscription", "commits_url": "https://api.github.com/repos/alexch/rerun/commits{/sha}", "git_commits_url": "https://api.github.com/repos/alexch/rerun/git/commits{/sha}", "comments_url": "https://api.github.com/repos/alexch/rerun/comments{/number}", "issue_comment_url": "https://api.github.com/repos/alexch/rerun/issues/comments/{number}", "contents_url": "https://api.github.com/repos/alexch/rerun/contents/{+path}", "compare_url": "https://api.github.com/repos/alexch/rerun/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/alexch/rerun/merges", "archive_url": "https://api.github.com/repos/alexch/rerun/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/alexch/rerun/downloads", "issues_url": "https://api.github.com/repos/alexch/rerun/issues{/number}", "pulls_url": "https://api.github.com/repos/alexch/rerun/pulls{/number}", "milestones_url": "https://api.github.com/repos/alexch/rerun/milestones{/number}", "notifications_url": "https://api.github.com/repos/alexch/rerun/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/alexch/rerun/labels{/name}", "releases_url": "https://api.github.com/repos/alexch/rerun/releases{/id}", "created_at": "2009-06-08T15:59:27Z", "updated_at": "2014-07-28T07:08:07Z", "pushed_at": "2014-05-05T15:09:08Z", "git_url": "git://github.com/alexch/rerun.git", "ssh_url": "git@github.com:alexch/rerun.git", "clone_url": "https://github.com/alexch/rerun.git", "svn_url": "https://github.com/alexch/rerun", "homepage": "", "size": 744, "stargazers_count": 382, "watchers_count": 382, "language": "Ruby", "has_issues": true, "has_downloads": true, "has_wiki": true, "forks_count": 29, "mirror_url": null, "open_issues_count": 22, "forks": 29, "open_issues": 22, "watchers": 382, "default_branch": "master" } }, "_links": { "self": { "href": "https://api.github.com/repos/alexch/rerun/pulls/56" }, "html": { "href": "https://github.com/alexch/rerun/pull/56" }, "issue": { "href": "https://api.github.com/repos/alexch/rerun/issues/56" }, "comments": { "href": "https://api.github.com/repos/alexch/rerun/issues/56/comments" }, "review_comments": { "href": "https://api.github.com/repos/alexch/rerun/pulls/56/comments" }, "review_comment": { "href": "https://api.github.com/repos/alexch/rerun/pulls/comments/{number}" }, "commits": { "href": "https://api.github.com/repos/alexch/rerun/pulls/56/commits" }, "statuses": { "href": "https://api.github.com/repos/alexch/rerun/statuses/1092c30ea86331bddb01b6afe28cada3d6f8f7ab" } } }, { "url": "https://api.github.com/repos/alexch/rerun/pulls/40", "id": 6322469, "html_url": "https://github.com/alexch/rerun/pull/40", "diff_url": "https://github.com/alexch/rerun/pull/40.diff", "patch_url": "https://github.com/alexch/rerun/pull/40.patch", "issue_url": "https://api.github.com/repos/alexch/rerun/issues/40", "number": 40, "state": "open", "title": "support OSX notifications as alternative to growl", "user": { "login": "RaVbaker", "id": 56023, "avatar_url": "https://avatars.githubusercontent.com/u/56023?v=1", "gravatar_id": "9764e44e1d69baa6276644e546ea9229", "url": "https://api.github.com/users/RaVbaker", "html_url": "https://github.com/RaVbaker", "followers_url": "https://api.github.com/users/RaVbaker/followers", "following_url": "https://api.github.com/users/RaVbaker/following{/other_user}", "gists_url": "https://api.github.com/users/RaVbaker/gists{/gist_id}", "starred_url": "https://api.github.com/users/RaVbaker/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/RaVbaker/subscriptions", "organizations_url": "https://api.github.com/users/RaVbaker/orgs", "repos_url": "https://api.github.com/users/RaVbaker/repos", "events_url": "https://api.github.com/users/RaVbaker/events{/privacy}", "received_events_url": "https://api.github.com/users/RaVbaker/received_events", "type": "User", "site_admin": false }, "body": "I have coded the OSX Notifications support for rerun. It uses [terminal-notifier](https://github.com/alloy/terminal-notifier) gem. And you can use it with two different arguments: `-on` or `--osx-notifications`. If you will use it will disable the growl notifications.\r\n\r\nRelated to issue: #33\r\n\r\nHow it looks? See here: ![OS X notifications for rerun gem](http://f.cl.ly/items/1q302F041i2I0j1l113U/Screen%20Shot%202013-06-14%20o%2012.11.40.png) ", "created_at": "2013-06-14T10:15:21Z", "updated_at": "2014-06-15T08:58:28Z", "closed_at": null, "merged_at": null, "merge_commit_sha": "645d46a644656b6b57b36ae81e2c9ef64f447e13", "assignee": null, "milestone": null, "commits_url": "https://api.github.com/repos/alexch/rerun/pulls/40/commits", "review_comments_url": "https://api.github.com/repos/alexch/rerun/pulls/40/comments", "review_comment_url": "https://api.github.com/repos/alexch/rerun/pulls/comments/{number}", "comments_url": "https://api.github.com/repos/alexch/rerun/issues/40/comments", "statuses_url": "https://api.github.com/repos/alexch/rerun/statuses/21ce9b2cf6c2d5570891ea41ed6ad74b58560ff7", "head": { "label": "RaVbaker:master", "ref": "master", "sha": "21ce9b2cf6c2d5570891ea41ed6ad74b58560ff7", "user": { "login": "RaVbaker", "id": 56023, "avatar_url": "https://avatars.githubusercontent.com/u/56023?v=1", "gravatar_id": "9764e44e1d69baa6276644e546ea9229", "url": "https://api.github.com/users/RaVbaker", "html_url": "https://github.com/RaVbaker", "followers_url": "https://api.github.com/users/RaVbaker/followers", "following_url": "https://api.github.com/users/RaVbaker/following{/other_user}", "gists_url": "https://api.github.com/users/RaVbaker/gists{/gist_id}", "starred_url": "https://api.github.com/users/RaVbaker/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/RaVbaker/subscriptions", "organizations_url": "https://api.github.com/users/RaVbaker/orgs", "repos_url": "https://api.github.com/users/RaVbaker/repos", "events_url": "https://api.github.com/users/RaVbaker/events{/privacy}", "received_events_url": "https://api.github.com/users/RaVbaker/received_events", "type": "User", "site_admin": false }, "repo": { "id": 10685919, "name": "rerun", "full_name": "RaVbaker/rerun", "owner": { "login": "RaVbaker", "id": 56023, "avatar_url": "https://avatars.githubusercontent.com/u/56023?v=1", "gravatar_id": "9764e44e1d69baa6276644e546ea9229", "url": "https://api.github.com/users/RaVbaker", "html_url": "https://github.com/RaVbaker", "followers_url": "https://api.github.com/users/RaVbaker/followers", "following_url": "https://api.github.com/users/RaVbaker/following{/other_user}", "gists_url": "https://api.github.com/users/RaVbaker/gists{/gist_id}", "starred_url": "https://api.github.com/users/RaVbaker/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/RaVbaker/subscriptions", "organizations_url": "https://api.github.com/users/RaVbaker/orgs", "repos_url": "https://api.github.com/users/RaVbaker/repos", "events_url": "https://api.github.com/users/RaVbaker/events{/privacy}", "received_events_url": "https://api.github.com/users/RaVbaker/received_events", "type": "User", "site_admin": false }, "private": false, "html_url": "https://github.com/RaVbaker/rerun", "description": "Restarts an app when the filesystem changes. Uses growl and FSEventStream if on OS X.", "fork": true, "url": "https://api.github.com/repos/RaVbaker/rerun", "forks_url": "https://api.github.com/repos/RaVbaker/rerun/forks", "keys_url": "https://api.github.com/repos/RaVbaker/rerun/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/RaVbaker/rerun/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/RaVbaker/rerun/teams", "hooks_url": "https://api.github.com/repos/RaVbaker/rerun/hooks", "issue_events_url": "https://api.github.com/repos/RaVbaker/rerun/issues/events{/number}", "events_url": "https://api.github.com/repos/RaVbaker/rerun/events", "assignees_url": "https://api.github.com/repos/RaVbaker/rerun/assignees{/user}", "branches_url": "https://api.github.com/repos/RaVbaker/rerun/branches{/branch}", "tags_url": "https://api.github.com/repos/RaVbaker/rerun/tags", "blobs_url": "https://api.github.com/repos/RaVbaker/rerun/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/RaVbaker/rerun/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/RaVbaker/rerun/git/refs{/sha}", "trees_url": "https://api.github.com/repos/RaVbaker/rerun/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/RaVbaker/rerun/statuses/{sha}", "languages_url": "https://api.github.com/repos/RaVbaker/rerun/languages", "stargazers_url": "https://api.github.com/repos/RaVbaker/rerun/stargazers", "contributors_url": "https://api.github.com/repos/RaVbaker/rerun/contributors", "subscribers_url": "https://api.github.com/repos/RaVbaker/rerun/subscribers", "subscription_url": "https://api.github.com/repos/RaVbaker/rerun/subscription", "commits_url": "https://api.github.com/repos/RaVbaker/rerun/commits{/sha}", "git_commits_url": "https://api.github.com/repos/RaVbaker/rerun/git/commits{/sha}", "comments_url": "https://api.github.com/repos/RaVbaker/rerun/comments{/number}", "issue_comment_url": "https://api.github.com/repos/RaVbaker/rerun/issues/comments/{number}", "contents_url": "https://api.github.com/repos/RaVbaker/rerun/contents/{+path}", "compare_url": "https://api.github.com/repos/RaVbaker/rerun/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/RaVbaker/rerun/merges", "archive_url": "https://api.github.com/repos/RaVbaker/rerun/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/RaVbaker/rerun/downloads", "issues_url": "https://api.github.com/repos/RaVbaker/rerun/issues{/number}", "pulls_url": "https://api.github.com/repos/RaVbaker/rerun/pulls{/number}", "milestones_url": "https://api.github.com/repos/RaVbaker/rerun/milestones{/number}", "notifications_url": "https://api.github.com/repos/RaVbaker/rerun/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/RaVbaker/rerun/labels{/name}", "releases_url": "https://api.github.com/repos/RaVbaker/rerun/releases{/id}", "created_at": "2013-06-14T09:26:55Z", "updated_at": "2013-08-28T19:02:05Z", "pushed_at": "2013-06-14T10:08:45Z", "git_url": "git://github.com/RaVbaker/rerun.git", "ssh_url": "git@github.com:RaVbaker/rerun.git", "clone_url": "https://github.com/RaVbaker/rerun.git", "svn_url": "https://github.com/RaVbaker/rerun", "homepage": "", "size": 267, "stargazers_count": 0, "watchers_count": 0, "language": "Ruby", "has_issues": false, "has_downloads": true, "has_wiki": true, "forks_count": 0, "mirror_url": null, "open_issues_count": 0, "forks": 0, "open_issues": 0, "watchers": 0, "default_branch": "master" } }, "base": { "label": "alexch:master", "ref": "master", "sha": "8db720f0f407a7e3f156b508f551bf9ef70e10c6", "user": { "login": "alexch", "id": 8524, "avatar_url": "https://avatars.githubusercontent.com/u/8524?v=1", "gravatar_id": "5a0d7f0cb2fac7858d234de7f7f01491", "url": "https://api.github.com/users/alexch", "html_url": "https://github.com/alexch", "followers_url": "https://api.github.com/users/alexch/followers", "following_url": "https://api.github.com/users/alexch/following{/other_user}", "gists_url": "https://api.github.com/users/alexch/gists{/gist_id}", "starred_url": "https://api.github.com/users/alexch/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/alexch/subscriptions", "organizations_url": "https://api.github.com/users/alexch/orgs", "repos_url": "https://api.github.com/users/alexch/repos", "events_url": "https://api.github.com/users/alexch/events{/privacy}", "received_events_url": "https://api.github.com/users/alexch/received_events", "type": "User", "site_admin": false }, "repo": { "id": 221696, "name": "rerun", "full_name": "alexch/rerun", "owner": { "login": "alexch", "id": 8524, "avatar_url": "https://avatars.githubusercontent.com/u/8524?v=1", "gravatar_id": "5a0d7f0cb2fac7858d234de7f7f01491", "url": "https://api.github.com/users/alexch", "html_url": "https://github.com/alexch", "followers_url": "https://api.github.com/users/alexch/followers", "following_url": "https://api.github.com/users/alexch/following{/other_user}", "gists_url": "https://api.github.com/users/alexch/gists{/gist_id}", "starred_url": "https://api.github.com/users/alexch/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/alexch/subscriptions", "organizations_url": "https://api.github.com/users/alexch/orgs", "repos_url": "https://api.github.com/users/alexch/repos", "events_url": "https://api.github.com/users/alexch/events{/privacy}", "received_events_url": "https://api.github.com/users/alexch/received_events", "type": "User", "site_admin": false }, "private": false, "html_url": "https://github.com/alexch/rerun", "description": "Restarts an app when the filesystem changes. Uses growl and FSEventStream if on OS X.", "fork": false, "url": "https://api.github.com/repos/alexch/rerun", "forks_url": "https://api.github.com/repos/alexch/rerun/forks", "keys_url": "https://api.github.com/repos/alexch/rerun/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/alexch/rerun/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/alexch/rerun/teams", "hooks_url": "https://api.github.com/repos/alexch/rerun/hooks", "issue_events_url": "https://api.github.com/repos/alexch/rerun/issues/events{/number}", "events_url": "https://api.github.com/repos/alexch/rerun/events", "assignees_url": "https://api.github.com/repos/alexch/rerun/assignees{/user}", "branches_url": "https://api.github.com/repos/alexch/rerun/branches{/branch}", "tags_url": "https://api.github.com/repos/alexch/rerun/tags", "blobs_url": "https://api.github.com/repos/alexch/rerun/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/alexch/rerun/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/alexch/rerun/git/refs{/sha}", "trees_url": "https://api.github.com/repos/alexch/rerun/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/alexch/rerun/statuses/{sha}", "languages_url": "https://api.github.com/repos/alexch/rerun/languages", "stargazers_url": "https://api.github.com/repos/alexch/rerun/stargazers", "contributors_url": "https://api.github.com/repos/alexch/rerun/contributors", "subscribers_url": "https://api.github.com/repos/alexch/rerun/subscribers", "subscription_url": "https://api.github.com/repos/alexch/rerun/subscription", "commits_url": "https://api.github.com/repos/alexch/rerun/commits{/sha}", "git_commits_url": "https://api.github.com/repos/alexch/rerun/git/commits{/sha}", "comments_url": "https://api.github.com/repos/alexch/rerun/comments{/number}", "issue_comment_url": "https://api.github.com/repos/alexch/rerun/issues/comments/{number}", "contents_url": "https://api.github.com/repos/alexch/rerun/contents/{+path}", "compare_url": "https://api.github.com/repos/alexch/rerun/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/alexch/rerun/merges", "archive_url": "https://api.github.com/repos/alexch/rerun/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/alexch/rerun/downloads", "issues_url": "https://api.github.com/repos/alexch/rerun/issues{/number}", "pulls_url": "https://api.github.com/repos/alexch/rerun/pulls{/number}", "milestones_url": "https://api.github.com/repos/alexch/rerun/milestones{/number}", "notifications_url": "https://api.github.com/repos/alexch/rerun/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/alexch/rerun/labels{/name}", "releases_url": "https://api.github.com/repos/alexch/rerun/releases{/id}", "created_at": "2009-06-08T15:59:27Z", "updated_at": "2014-07-28T07:08:07Z", "pushed_at": "2014-05-05T15:09:08Z", "git_url": "git://github.com/alexch/rerun.git", "ssh_url": "git@github.com:alexch/rerun.git", "clone_url": "https://github.com/alexch/rerun.git", "svn_url": "https://github.com/alexch/rerun", "homepage": "", "size": 744, "stargazers_count": 382, "watchers_count": 382, "language": "Ruby", "has_issues": true, "has_downloads": true, "has_wiki": true, "forks_count": 29, "mirror_url": null, "open_issues_count": 22, "forks": 29, "open_issues": 22, "watchers": 382, "default_branch": "master" } }, "_links": { "self": { "href": "https://api.github.com/repos/alexch/rerun/pulls/40" }, "html": { "href": "https://github.com/alexch/rerun/pull/40" }, "issue": { "href": "https://api.github.com/repos/alexch/rerun/issues/40" }, "comments": { "href": "https://api.github.com/repos/alexch/rerun/issues/40/comments" }, "review_comments": { "href": "https://api.github.com/repos/alexch/rerun/pulls/40/comments" }, "review_comment": { "href": "https://api.github.com/repos/alexch/rerun/pulls/comments/{number}" }, "commits": { "href": "https://api.github.com/repos/alexch/rerun/pulls/40/commits" }, "statuses": { "href": "https://api.github.com/repos/alexch/rerun/statuses/21ce9b2cf6c2d5570891ea41ed6ad74b58560ff7" } } }, { "url": "https://api.github.com/repos/alexch/rerun/pulls/31", "id": 4887127, "html_url": "https://github.com/alexch/rerun/pull/31", "diff_url": "https://github.com/alexch/rerun/pull/31.diff", "patch_url": "https://github.com/alexch/rerun/pull/31.patch", "issue_url": "https://api.github.com/repos/alexch/rerun/issues/31", "number": 31, "state": "open", "title": "Add restart signal support", "user": { "login": "ismell", "id": 562978, "avatar_url": "https://avatars.githubusercontent.com/u/562978?v=1", "gravatar_id": "4f945a304cb19ee2404bfbad964bd85e", "url": "https://api.github.com/users/ismell", "html_url": "https://github.com/ismell", "followers_url": "https://api.github.com/users/ismell/followers", "following_url": "https://api.github.com/users/ismell/following{/other_user}", "gists_url": "https://api.github.com/users/ismell/gists{/gist_id}", "starred_url": "https://api.github.com/users/ismell/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/ismell/subscriptions", "organizations_url": "https://api.github.com/users/ismell/orgs", "repos_url": "https://api.github.com/users/ismell/repos", "events_url": "https://api.github.com/users/ismell/events{/privacy}", "received_events_url": "https://api.github.com/users/ismell/received_events", "type": "User", "site_admin": false }, "body": "This can be used when running with unicorn.\r\n\r\nrerun -r HUP -- unicorn -c unicorn.rb\r\n\r\nNOTE: Make sure you run unicorn with a config file\r\n otherwise it will respawn the master and you will\r\n end up in a very bad place.", "created_at": "2013-03-29T15:58:47Z", "updated_at": "2014-06-12T20:20:17Z", "closed_at": null, "merged_at": null, "merge_commit_sha": "67371ef78471e2f84ac703e765d063caf0065601", "assignee": null, "milestone": null, "commits_url": "https://api.github.com/repos/alexch/rerun/pulls/31/commits", "review_comments_url": "https://api.github.com/repos/alexch/rerun/pulls/31/comments", "review_comment_url": "https://api.github.com/repos/alexch/rerun/pulls/comments/{number}", "comments_url": "https://api.github.com/repos/alexch/rerun/issues/31/comments", "statuses_url": "https://api.github.com/repos/alexch/rerun/statuses/174bc3ce2ad1ad786b98197d762f7e41fa114398", "head": { "label": "ismell:master", "ref": "master", "sha": "174bc3ce2ad1ad786b98197d762f7e41fa114398", "user": { "login": "ismell", "id": 562978, "avatar_url": "https://avatars.githubusercontent.com/u/562978?v=1", "gravatar_id": "4f945a304cb19ee2404bfbad964bd85e", "url": "https://api.github.com/users/ismell", "html_url": "https://github.com/ismell", "followers_url": "https://api.github.com/users/ismell/followers", "following_url": "https://api.github.com/users/ismell/following{/other_user}", "gists_url": "https://api.github.com/users/ismell/gists{/gist_id}", "starred_url": "https://api.github.com/users/ismell/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/ismell/subscriptions", "organizations_url": "https://api.github.com/users/ismell/orgs", "repos_url": "https://api.github.com/users/ismell/repos", "events_url": "https://api.github.com/users/ismell/events{/privacy}", "received_events_url": "https://api.github.com/users/ismell/received_events", "type": "User", "site_admin": false }, "repo": { "id": 9100150, "name": "rerun", "full_name": "ismell/rerun", "owner": { "login": "ismell", "id": 562978, "avatar_url": "https://avatars.githubusercontent.com/u/562978?v=1", "gravatar_id": "4f945a304cb19ee2404bfbad964bd85e", "url": "https://api.github.com/users/ismell", "html_url": "https://github.com/ismell", "followers_url": "https://api.github.com/users/ismell/followers", "following_url": "https://api.github.com/users/ismell/following{/other_user}", "gists_url": "https://api.github.com/users/ismell/gists{/gist_id}", "starred_url": "https://api.github.com/users/ismell/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/ismell/subscriptions", "organizations_url": "https://api.github.com/users/ismell/orgs", "repos_url": "https://api.github.com/users/ismell/repos", "events_url": "https://api.github.com/users/ismell/events{/privacy}", "received_events_url": "https://api.github.com/users/ismell/received_events", "type": "User", "site_admin": false }, "private": false, "html_url": "https://github.com/ismell/rerun", "description": "Restarts an app when the filesystem changes. Uses growl and FSEventStream if on OS X.", "fork": true, "url": "https://api.github.com/repos/ismell/rerun", "forks_url": "https://api.github.com/repos/ismell/rerun/forks", "keys_url": "https://api.github.com/repos/ismell/rerun/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/ismell/rerun/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/ismell/rerun/teams", "hooks_url": "https://api.github.com/repos/ismell/rerun/hooks", "issue_events_url": "https://api.github.com/repos/ismell/rerun/issues/events{/number}", "events_url": "https://api.github.com/repos/ismell/rerun/events", "assignees_url": "https://api.github.com/repos/ismell/rerun/assignees{/user}", "branches_url": "https://api.github.com/repos/ismell/rerun/branches{/branch}", "tags_url": "https://api.github.com/repos/ismell/rerun/tags", "blobs_url": "https://api.github.com/repos/ismell/rerun/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/ismell/rerun/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/ismell/rerun/git/refs{/sha}", "trees_url": "https://api.github.com/repos/ismell/rerun/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/ismell/rerun/statuses/{sha}", "languages_url": "https://api.github.com/repos/ismell/rerun/languages", "stargazers_url": "https://api.github.com/repos/ismell/rerun/stargazers", "contributors_url": "https://api.github.com/repos/ismell/rerun/contributors", "subscribers_url": "https://api.github.com/repos/ismell/rerun/subscribers", "subscription_url": "https://api.github.com/repos/ismell/rerun/subscription", "commits_url": "https://api.github.com/repos/ismell/rerun/commits{/sha}", "git_commits_url": "https://api.github.com/repos/ismell/rerun/git/commits{/sha}", "comments_url": "https://api.github.com/repos/ismell/rerun/comments{/number}", "issue_comment_url": "https://api.github.com/repos/ismell/rerun/issues/comments/{number}", "contents_url": "https://api.github.com/repos/ismell/rerun/contents/{+path}", "compare_url": "https://api.github.com/repos/ismell/rerun/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/ismell/rerun/merges", "archive_url": "https://api.github.com/repos/ismell/rerun/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/ismell/rerun/downloads", "issues_url": "https://api.github.com/repos/ismell/rerun/issues{/number}", "pulls_url": "https://api.github.com/repos/ismell/rerun/pulls{/number}", "milestones_url": "https://api.github.com/repos/ismell/rerun/milestones{/number}", "notifications_url": "https://api.github.com/repos/ismell/rerun/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/ismell/rerun/labels{/name}", "releases_url": "https://api.github.com/repos/ismell/rerun/releases{/id}", "created_at": "2013-03-29T14:44:17Z", "updated_at": "2013-10-18T18:37:05Z", "pushed_at": "2013-04-22T17:47:13Z", "git_url": "git://github.com/ismell/rerun.git", "ssh_url": "git@github.com:ismell/rerun.git", "clone_url": "https://github.com/ismell/rerun.git", "svn_url": "https://github.com/ismell/rerun", "homepage": "", "size": 271, "stargazers_count": 0, "watchers_count": 0, "language": "Ruby", "has_issues": false, "has_downloads": true, "has_wiki": true, "forks_count": 0, "mirror_url": null, "open_issues_count": 0, "forks": 0, "open_issues": 0, "watchers": 0, "default_branch": "master" } }, "base": { "label": "alexch:master", "ref": "master", "sha": "31d6a11b5269006d2bbb868af0271e3538ac6dd6", "user": { "login": "alexch", "id": 8524, "avatar_url": "https://avatars.githubusercontent.com/u/8524?v=1", "gravatar_id": "5a0d7f0cb2fac7858d234de7f7f01491", "url": "https://api.github.com/users/alexch", "html_url": "https://github.com/alexch", "followers_url": "https://api.github.com/users/alexch/followers", "following_url": "https://api.github.com/users/alexch/following{/other_user}", "gists_url": "https://api.github.com/users/alexch/gists{/gist_id}", "starred_url": "https://api.github.com/users/alexch/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/alexch/subscriptions", "organizations_url": "https://api.github.com/users/alexch/orgs", "repos_url": "https://api.github.com/users/alexch/repos", "events_url": "https://api.github.com/users/alexch/events{/privacy}", "received_events_url": "https://api.github.com/users/alexch/received_events", "type": "User", "site_admin": false }, "repo": { "id": 221696, "name": "rerun", "full_name": "alexch/rerun", "owner": { "login": "alexch", "id": 8524, "avatar_url": "https://avatars.githubusercontent.com/u/8524?v=1", "gravatar_id": "5a0d7f0cb2fac7858d234de7f7f01491", "url": "https://api.github.com/users/alexch", "html_url": "https://github.com/alexch", "followers_url": "https://api.github.com/users/alexch/followers", "following_url": "https://api.github.com/users/alexch/following{/other_user}", "gists_url": "https://api.github.com/users/alexch/gists{/gist_id}", "starred_url": "https://api.github.com/users/alexch/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/alexch/subscriptions", "organizations_url": "https://api.github.com/users/alexch/orgs", "repos_url": "https://api.github.com/users/alexch/repos", "events_url": "https://api.github.com/users/alexch/events{/privacy}", "received_events_url": "https://api.github.com/users/alexch/received_events", "type": "User", "site_admin": false }, "private": false, "html_url": "https://github.com/alexch/rerun", "description": "Restarts an app when the filesystem changes. Uses growl and FSEventStream if on OS X.", "fork": false, "url": "https://api.github.com/repos/alexch/rerun", "forks_url": "https://api.github.com/repos/alexch/rerun/forks", "keys_url": "https://api.github.com/repos/alexch/rerun/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/alexch/rerun/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/alexch/rerun/teams", "hooks_url": "https://api.github.com/repos/alexch/rerun/hooks", "issue_events_url": "https://api.github.com/repos/alexch/rerun/issues/events{/number}", "events_url": "https://api.github.com/repos/alexch/rerun/events", "assignees_url": "https://api.github.com/repos/alexch/rerun/assignees{/user}", "branches_url": "https://api.github.com/repos/alexch/rerun/branches{/branch}", "tags_url": "https://api.github.com/repos/alexch/rerun/tags", "blobs_url": "https://api.github.com/repos/alexch/rerun/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/alexch/rerun/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/alexch/rerun/git/refs{/sha}", "trees_url": "https://api.github.com/repos/alexch/rerun/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/alexch/rerun/statuses/{sha}", "languages_url": "https://api.github.com/repos/alexch/rerun/languages", "stargazers_url": "https://api.github.com/repos/alexch/rerun/stargazers", "contributors_url": "https://api.github.com/repos/alexch/rerun/contributors", "subscribers_url": "https://api.github.com/repos/alexch/rerun/subscribers", "subscription_url": "https://api.github.com/repos/alexch/rerun/subscription", "commits_url": "https://api.github.com/repos/alexch/rerun/commits{/sha}", "git_commits_url": "https://api.github.com/repos/alexch/rerun/git/commits{/sha}", "comments_url": "https://api.github.com/repos/alexch/rerun/comments{/number}", "issue_comment_url": "https://api.github.com/repos/alexch/rerun/issues/comments/{number}", "contents_url": "https://api.github.com/repos/alexch/rerun/contents/{+path}", "compare_url": "https://api.github.com/repos/alexch/rerun/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/alexch/rerun/merges", "archive_url": "https://api.github.com/repos/alexch/rerun/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/alexch/rerun/downloads", "issues_url": "https://api.github.com/repos/alexch/rerun/issues{/number}", "pulls_url": "https://api.github.com/repos/alexch/rerun/pulls{/number}", "milestones_url": "https://api.github.com/repos/alexch/rerun/milestones{/number}", "notifications_url": "https://api.github.com/repos/alexch/rerun/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/alexch/rerun/labels{/name}", "releases_url": "https://api.github.com/repos/alexch/rerun/releases{/id}", "created_at": "2009-06-08T15:59:27Z", "updated_at": "2014-07-28T07:08:07Z", "pushed_at": "2014-05-05T15:09:08Z", "git_url": "git://github.com/alexch/rerun.git", "ssh_url": "git@github.com:alexch/rerun.git", "clone_url": "https://github.com/alexch/rerun.git", "svn_url": "https://github.com/alexch/rerun", "homepage": "", "size": 744, "stargazers_count": 382, "watchers_count": 382, "language": "Ruby", "has_issues": true, "has_downloads": true, "has_wiki": true, "forks_count": 29, "mirror_url": null, "open_issues_count": 22, "forks": 29, "open_issues": 22, "watchers": 382, "default_branch": "master" } }, "_links": { "self": { "href": "https://api.github.com/repos/alexch/rerun/pulls/31" }, "html": { "href": "https://github.com/alexch/rerun/pull/31" }, "issue": { "href": "https://api.github.com/repos/alexch/rerun/issues/31" }, "comments": { "href": "https://api.github.com/repos/alexch/rerun/issues/31/comments" }, "review_comments": { "href": "https://api.github.com/repos/alexch/rerun/pulls/31/comments" }, "review_comment": { "href": "https://api.github.com/repos/alexch/rerun/pulls/comments/{number}" }, "commits": { "href": "https://api.github.com/repos/alexch/rerun/pulls/31/commits" }, "statuses": { "href": "https://api.github.com/repos/alexch/rerun/statuses/174bc3ce2ad1ad786b98197d762f7e41fa114398" } } } ] rerun-0.11.0/rerun.gemspec000066400000000000000000000020531260522351700154270ustar00rootroot00000000000000$spec = Gem::Specification.new do |s| s.specification_version = 2 if s.respond_to? :specification_version= s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.name = 'rerun' s.version = '0.11.0' s.description = "Restarts your app when a file changes. A no-frills, command-line alternative to Guard, Shotgun, Autotest, etc." s.summary = "Launches an app, and restarts it whenever the filesystem changes. A no-frills, command-line alternative to Guard, Shotgun, Autotest, etc." s.authors = ["Alex Chaffee"] s.email = "alex@stinky.com" s.files = %w[ README.md LICENSE Rakefile rerun.gemspec bin/rerun icons/rails_grn_sml.png icons/rails_red_sml.png] + Dir['lib/**/*.rb'] s.executables = ['rerun'] s.test_files = s.files.select {|path| path =~ /^spec\/.*_spec.rb/} s.extra_rdoc_files = %w[README.md] s.add_runtime_dependency 'listen', '~> 3.0' s.homepage = "http://github.com/alexch/rerun/" s.require_paths = %w[lib] s.license = 'MIT' end rerun-0.11.0/spec/000077500000000000000000000000001260522351700136615ustar00rootroot00000000000000rerun-0.11.0/spec/functional_spec.rb000066400000000000000000000041731260522351700173670ustar00rootroot00000000000000here = File.expand_path(File.dirname(__FILE__)) require "#{here}/spec_helper.rb" require "#{here}/inc_process.rb" describe "the rerun command" do before do STDOUT.sync = true @inc = IncProcess.new # one file that exists in dir1 @existing_file = File.join(@inc.dir1, "foo.rb") touch @existing_file # one file that doesn't yet exist in dir1 @soon_to_exist_file = File.join(@inc.dir1, "bar.rb") # one file that exists in dir2 @other_existing_file = File.join(@inc.dir2, "baz.rb") @inc.launch end after do @inc.kill end def read @inc.read end def touch(file = @existing_file) puts "#{Time.now.strftime("%T")} touching #{file}" File.open(file, "w") do |f| f.puts Time.now end end def type char # todo: send a character to stdin of the rerun process end describe IncProcess do it "increments a test file at least once per second" do sleep 1 x = @inc.current_count sleep 1 y = @inc.current_count y.should be > x end end it "restarts its target when an app file is modified" do first_launched_at = read[:launched_at] touch @existing_file sleep 4 second_launched_at = read[:launched_at] second_launched_at.should be > first_launched_at end it "restarts its target when an app file is created" do first_launched_at = read[:launched_at] touch @soon_to_exist_file sleep 4 second_launched_at = read[:launched_at] second_launched_at.should be > first_launched_at end it "restarts its target when an app file is created in the second dir" do first_launched_at = read[:launched_at] touch @other_existing_file sleep 4 second_launched_at = read[:launched_at] second_launched_at.should be > first_launched_at end #it "sends its child process a SIGINT to restart" it "dies when sent a control-C (SIGINT)" do pid = @inc.inc_parent_pid # puts "test sending INT to #{pid}" Process.kill("INT", pid) timeout(6) { # puts "test waiting for #{pid}" Process.wait(@inc.rerun_pid) rescue Errno::ESRCH } end #it "accepts a key press" end rerun-0.11.0/spec/glob_spec.rb000066400000000000000000000054101260522351700161430ustar00rootroot00000000000000here = File.expand_path(File.dirname(__FILE__)) require "#{here}/spec_helper.rb" require "rerun/glob" module Rerun describe Glob do describe "#to_regexp" do it "makes a regexp" do Glob.new("foo*").to_regexp.should == /#{Glob::START_OF_FILENAME}foo.*#{Glob::END_OF_STRING}/ end end describe "#to_regexp_string" do { "x" => "x", "*" => ".*", "foo*" => "foo.*", "*foo" => ".*foo", "*foo*" => ".*foo.*", "?" => ".", "." => "\\.", "{foo,bar,baz}" => "(foo|bar|baz)", "{.txt,.md}" => '(\.txt|\.md)', # pass through slash-escapes verbatim "\\x" => "\\x", "\\." => "\\.", "\\*" => "\\*", "\\\\" => "\\\\", "**/*.txt" => "([^/]+/)*.*\\.txt", }.each_pair do |glob_string, regexp_string| specify glob_string do Glob.new(glob_string).to_regexp_string.should == Glob::START_OF_FILENAME + regexp_string + Glob::END_OF_STRING end end end describe "specifically" do { "*.txt" => { :hits=> [ "foo.txt", "foo/bar.txt", "/foo/bar.txt", "bar.baz.txt", "/foo/bar.baz.txt", ], :misses => [ "foo.txt.html", "tmp/foo.txt.html", "/tmp/foo.txt.html", #"tmp/.foo.txt", ] }, "tmp/foo.*" => { :hits => [ "tmp/foo.txt", ], :misses => [ "stmp/foo.txt", "tmp/foofoo.txt", ] } }.each_pair do |glob, paths| paths[:hits].each do |path| specify "#{glob} matches #{path}" do Glob.new(glob).to_regexp.should =~ path end end paths[:misses].each do |path| specify "#{glob} doesn't match #{path}" do Glob.new(glob).to_regexp.should_not =~ path end end end end describe "#smoosh" do def check_smoosh string, array glob = Glob.new("") glob.smoosh(string.split('')).should == array end it "ignores non-stars" do check_smoosh "", [] check_smoosh "abc", ["a", "b", "c"] end it "passes solitary stars" do check_smoosh "*", ["*"] check_smoosh "a*b", ["a", "*", "b"] end it "smooshes two stars in a row into a single '**' string" do check_smoosh "**", ["**"] check_smoosh "a**b", ["a", "**", "b"] check_smoosh "**b", ["**", "b"] check_smoosh "a**", ["a", "**"] end it "treats **/ like **" do check_smoosh "**/", ["**"] check_smoosh "a**/b", ["a", "**", "b"] end end end end rerun-0.11.0/spec/inc_process.rb000066400000000000000000000040331260522351700165150ustar00rootroot00000000000000here = File.expand_path(File.dirname(__FILE__)) require 'tmpdir' class IncProcess attr_reader :dir, :inc_output_file attr_reader :dir1, :dir2 attr_reader :rerun_pid, :inc_parent_pid def initialize @dir = Dir.tmpdir + "/#{Time.now.to_i}" FileUtils.mkdir_p(@dir) @inc_output_file = "#{@dir}/inc.txt" @dir1 = File.join(@dir, "dir1") FileUtils.mkdir_p(@dir1) @dir2 = File.join(@dir, "dir2") FileUtils.mkdir_p(@dir2) end # don't call this until you're sure it's running def kill begin pids = ([@inc_pid, @inc_parent_pid, @rerun_pid] - [Process.pid]).uniq timeout(5) do pids.each do |pid| # puts "sending INT to #{pid}" Process.kill("INT", pid) rescue Errno::ESRCH end pids.each do |pid| # puts "waiting for #{pid}" Process.wait(pid) rescue Errno::ECHILD end end rescue Timeout::Error pids.each do |pid| # puts "sending KILL to #{pid}" Process.kill("KILL", pid) rescue Errno::ESRCH end end end def rerun_cmd root = File.dirname(__FILE__) + "/.." "#{root}/bin/rerun -d '#{@dir1},#{@dir2}' ruby #{root}/inc.rb #{@inc_output_file}" end def launch @rerun_pid = spawn(rerun_cmd) timeout(10) { sleep 0.5 until File.exist?(@inc_output_file) } sleep 3 # let rerun's watcher get going read end def read File.open(@inc_output_file, "r") do |f| result = { launched_at: f.gets.to_i, count: f.gets.to_i, inc_pid: f.gets.to_i, inc_parent_pid: f.gets.to_i, } @inc_pid = result[:inc_pid] @inc_parent_pid = result[:inc_parent_pid] puts "reading #{@inc_output_file}: #{result.inspect}" result end end def current_count read[:count] end def touch(file = @existing_file) puts "#{Time.now.strftime("%T")} touching #{file}" File.open(file, "w") do |f| f.puts Time.now end end def type char # todo: send a character to stdin of the rerun process end end rerun-0.11.0/spec/options_spec.rb000066400000000000000000000070341260522351700167170ustar00rootroot00000000000000here = File.expand_path(File.dirname(__FILE__)) require "#{here}/spec_helper.rb" require "rerun/options" module Rerun describe Options do it "has good defaults" do defaults = Options.parse ["foo"] assert { defaults[:cmd] = "foo" } assert { defaults[:dir] == ["."] } assert { defaults[:pattern] == Options::DEFAULT_PATTERN } assert { defaults[:signal] == "TERM" } assert { defaults[:notify] == true } assert { defaults[:name] == 'Rerun' } assert { defaults[:clear].nil? } assert { defaults[:exit].nil? } assert { defaults[:background].nil? } end ["--help", "-h", "--usage", "--version", "-v"].each do |arg| describe "when passed #{arg}" do it "returns nil" do capturing do Options.parse([arg]).should be_nil end end end end it "splits directories" do options = Options.parse ["--dir", "a,b", "foo"] assert { options[:dir] == ["a", "b"] } end it "adds directories specified individually with --dir" do options = Options.parse ["--dir", "a", "--dir", "b"] assert { options[:dir] == ["a", "b"] } end it "adds directories specified individually with -d" do options = Options.parse ["-d", "a", "-d", "b"] assert { options[:dir] == ["a", "b"] } end it "adds directories specified individually using mixed -d and --dir" do options = Options.parse ["-d", "a", "--dir", "b"] assert { options[:dir] == ["a", "b"] } end it "adds individual directories and splits comma-separated ones" do options = Options.parse ["--dir", "a", "--dir", "b", "--dir", "foo,other"] assert { options[:dir] == ["a", "b", "foo", "other"] } end it "accepts --name for a custom application name" do options = Options.parse ["--name", "scheduler"] assert { options[:name] == "scheduler" } end it "accepts --ignore" do options = Options.parse ["--ignore", "log/*"] assert { options[:ignore] == ["log/*"] } end it "accepts --ignore multiple times" do options = Options.parse ["--ignore", "log/*", "--ignore", "*.tmp"] assert { options[:ignore] == ["log/*", "*.tmp"] } end it "accepts --restart which allows the process to restart itself, defaulting to HUP" do options = Options.parse ["--restart"] assert { options[:restart] } assert { options[:signal] == "HUP" } end it "allows user to override HUP signal when --restart is specified" do options = Options.parse %w[--restart --signal INT] assert { options[:restart] } assert { options[:signal] == "INT" } end # notifications it "rejects --no-growl" do options = nil err = capturing(:stderr) do options = Options.parse %w[--no-growl echo foo] end assert { options == nil } assert { err.include? "use --no-notify" } end it "defaults to --notify true (meaning 'use what works')" do options = Options.parse %w[echo foo] assert { options[:notify] == true } end it "accepts bare --notify" do options = Options.parse %w[--notify -- echo foo] assert { options[:notify] == true } end %w[growl osx].each do |notifier| it "accepts --notify #{notifier}" do options = Options.parse ["--notify", notifier, "echo foo"] assert { options[:notify] == notifier } end end it "accepts --no-notify" do options = Options.parse %w[--no-notify echo foo] assert { options[:notify] == false } end end end rerun-0.11.0/spec/runner_spec.rb000066400000000000000000000045671260522351700165450ustar00rootroot00000000000000here = File.expand_path(File.dirname(__FILE__)) require "#{here}/spec_helper.rb" require 'rerun' module Rerun describe Runner do class Runner attr_reader :run_command end describe "initialization and configuration" do it "accepts a command" do runner = Runner.new("foo") runner.run_command.should == "foo" end it "If the command is a .rb file, then run it with ruby" do runner = Runner.new("foo.rb") runner.run_command.should == "ruby foo.rb" end it "If the command starts with a .rb file, then run it with ruby" do runner = Runner.new("foo.rb --param bar baz.txt") runner.run_command.should == "ruby foo.rb --param bar baz.txt" end it "clears the screen" do runner = Runner.new("foo.rb", {:clear => true}) runner.clear?.should be_truthy end end describe "running" do it "sends its child process a SIGINT when restarting" it "dies when sent a control-C (SIGINT)" it "accepts a key press" it "restarts with HUP" it "restarts with a different signal" end describe 'change_message' do subject { Runner.new("").change_message(changes) } [:modified, :added, :removed].each do |change_type| context "one #{change_type}" do let(:changes) { {change_type => ["foo.rb"]} } it 'says how many of each type of change' do expect(subject == "1 modified: foo.rb") end end end context "two changes" do let(:changes) { {modified: ["foo.rb", "bar.rb"]} } it 'uses a comma' do expect(subject == "2 modified: foo.rb, bar.rb") end end context "three changes" do let(:changes) { {modified: ["foo.rb", "bar.rb", "baz.rb"]} } it 'elides after the third' do expect(subject == "3 modified: foo.rb, bar.rb, baz.rb") end end context "more than three changes" do let(:changes) { {modified: ["foo.rb", "bar.rb", "baz.rb", "baf.rb"]} } it 'elides after the third' do expect(subject == "4 modified: foo.rb, bar.rb, baz.rb, ...") end end context "with a path" do let(:changes) { {modified: ["baz/bar/foo.rb"]} } it 'strips the path' do expect(subject == "1 modified: foo.rb") end end end end end rerun-0.11.0/spec/spec_helper.rb000066400000000000000000000004731260522351700165030ustar00rootroot00000000000000require "rubygems" require "rspec" #require "rspec/autorun" require "wrong/adapters/rspec" include Wrong::D here = File.expand_path(File.dirname(__FILE__)) $: << File.expand_path("#{here}/../lib") require "rerun" RSpec.configure do |config| config.expect_with(:rspec) { |c| c.syntax = %i[expect should] } end rerun-0.11.0/spec/watcher_spec.rb000066400000000000000000000063721260522351700166650ustar00rootroot00000000000000here = File.expand_path(File.dirname(__FILE__)) require "#{here}/spec_helper.rb" require 'tmpdir' require 'rerun/watcher' module Rerun describe Watcher do COOL_OFF_TIME = 2 def start_watcher options = {} options = {:directory => @dir, :pattern => "*.txt"}.merge(options) @log = nil @watcher = Watcher.new(options) do |hash| @log = hash end @watcher.start sleep(COOL_OFF_TIME) # let it spin up end def stop_watcher begin @watcher.stop rescue ThreadError => e end end before do @dir = Dir.tmpdir + "/#{Time.now.to_i}-#{(rand*100000).to_i}" # fix goofy MacOS /tmp path ambiguity @dir.sub!(/^\/var/, "/private/var") FileUtils.mkdir_p(@dir) start_watcher end let(:rest) { 2 } after do stop_watcher end def create test_file, sleep = true File.open(test_file, "w") do |f| f.puts("test") end sleep(rest) if sleep end def modify test_file File.open(test_file, "a") do |f| f.puts("more more more") end sleep(rest) end def remove test_file File.delete(test_file) sleep(rest) end it "watches file changes" do test_file = "#{@dir}/test.txt" create test_file @log[:added].should == [test_file] modify test_file @log[:modified].should == [test_file] remove test_file @log[:removed].should == [test_file] end it "ignores changes to non-matching files" do non_matching_file = "#{@dir}/test.exe" create non_matching_file @log.should be_nil modify non_matching_file @log.should be_nil remove non_matching_file @log.should be_nil end it "ignores changes to dot-files" do dot_file = "#{@dir}/.ignoreme.txt" create dot_file @log.should be_nil modify dot_file @log.should be_nil remove dot_file @log.should be_nil end # TODO: unify with Listen::Silencer::DEFAULT_IGNORED_DIRECTORIES ignored_directories = %w[ .git .svn .hg .rbx .bundle bundle vendor/bundle log tmp vendor/ruby ] it "ignores directories named #{ignored_directories}" do ignored_directories.each do |ignored_dir| FileUtils.mkdir_p "#{@dir}/#{ignored_dir}" create [@dir, ignored_dir, "foo.txt"].join('/'), false end sleep(rest) @log.should be_nil end it "ignores files named `.DS_Store`." do create "#{@dir}/.DS_Store" @log.should be_nil end it "ignores files ending with `.tmp`." do create "#{@dir}/foo.tmp" @log.should be_nil end it "optionally ignores globs" do stop_watcher start_watcher ignore: "foo*" create "#{@dir}/foo.txt" @log.should be_nil end it "disables watcher when paused" do @watcher.pause create "#{@dir}/pause_test.txt" @log.should be_nil end it "pauses and resumes watcher" do @watcher.pause create "#{@dir}/pause_test.txt" @log.should be_nil sleep 0.25 # work around very rare timing issue on Travis @watcher.unpause test_file = "#{@dir}/pause_test2.txt" create test_file @log[:added].should == [test_file] end end end rerun-0.11.0/stty.rb000066400000000000000000000013361260522351700142620ustar00rootroot00000000000000# see /usr/include/sys/termios.h # see man stty require "wrong" include Wrong def tty stty = `stty -g` stty.split(':') end def tty_setting name tty.grep(/^#{name}/).first.split('=').last end def oflag tty_setting("oflag") end normal = tty `stty raw` raw = tty `stty -raw` minus_raw = tty assert { minus_raw == normal } `stty raw opost` raw_opost = tty d { raw - normal } d { normal - raw } d { normal - raw_opost } puts "== normal" # d { tty } d{oflag} def check setting `stty #{setting}` puts "testing #{setting}:\nline\nline" print "\r\n" end check "raw" check "-raw" check "raw opost" check "-raw" check "raw gfmt1:oflag=3" # check "oflag=3" # check "lflag=200005cb" # check "iflag=2b02" `stty -raw` rerun-0.11.0/todo.md000066400000000000000000000007671260522351700142300ustar00rootroot00000000000000* use GNTP * https://github.com/snaka/ruby_gntp * https://github.com/ericgj/groem * http://growl.info/documentation/developer/gntp.php * test stty stuff on other Unixes * use childprocess * specify escalation timeout (time between sending SIGTERM and SIGINT) * also try to kill whatever process is listening to a given port (in case it's ignoring or doesn't get the signal from its parent) (see http://stackoverflow.com/questions/8105322/foreman-does-not-kill-processes for lsof example)