sinefunc-rstakeout 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/README.md ADDED
@@ -0,0 +1,27 @@
1
+ Rstakeout
2
+ =========
3
+
4
+ Ruby script to execute an arbitrary command whenever a file changes.
5
+
6
+ Forked from github.com/edvardm/rstakeout, which was forked from topfunkyv
7
+
8
+ Installation
9
+ ------------
10
+
11
+ gem install sinefunc-rstakeout
12
+ # Mac users: install `growlnotify` from the Growl DWG to get notifications
13
+
14
+ Common usage
15
+ ------------
16
+
17
+ # Execute a test everytime any file changes
18
+ rstakeout 'rake test' **/*
19
+
20
+ # Regenerate some LessCSS files whenever needed
21
+ rstakeout 'lessc %s' **/*.less
22
+
23
+ Copyright
24
+ ---------
25
+
26
+ License: MIT
27
+
data/Rakefile ADDED
@@ -0,0 +1,53 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "sinefunc-rstakeout"
8
+ gem.summary = "Watches a directory for any changes"
9
+ gem.description = "This gem watches a given directory for any changes and executes a given command when something is changed."
10
+ gem.email = "rico@sinefunc.com"
11
+ gem.homepage = "http://github.com/sinefunc/rstakeout"
12
+ gem.authors = ["edvardw", "topfunky"]
13
+ #gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
14
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
+ end
16
+ Jeweler::GemcutterTasks.new
17
+ rescue LoadError
18
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
19
+ end
20
+
21
+ require 'rake/testtask'
22
+ Rake::TestTask.new(:test) do |test|
23
+ test.libs << 'lib' << 'test'
24
+ test.pattern = 'test/**/test_*.rb'
25
+ test.verbose = true
26
+ end
27
+
28
+ begin
29
+ require 'rcov/rcovtask'
30
+ Rcov::RcovTask.new do |test|
31
+ test.libs << 'test'
32
+ test.pattern = 'test/**/test_*.rb'
33
+ test.verbose = true
34
+ end
35
+ rescue LoadError
36
+ task :rcov do
37
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
38
+ end
39
+ end
40
+
41
+ task :test => :check_dependencies
42
+
43
+ task :default => :test
44
+
45
+ require 'rake/rdoctask'
46
+ Rake::RDocTask.new do |rdoc|
47
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
48
+
49
+ rdoc.rdoc_dir = 'rdoc'
50
+ rdoc.title = "rstakeout #{version}"
51
+ rdoc.rdoc_files.include('README*')
52
+ rdoc.rdoc_files.include('lib/**/*.rb')
53
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
data/bin/rstakeout ADDED
@@ -0,0 +1,231 @@
1
+ #!/usr/bin/env ruby -w
2
+ ##
3
+ # Originally by Mike Clark.
4
+ #
5
+ # From http://www.pragmaticautomation.com/cgi-bin/pragauto.cgi/Monitor/StakingOutFileChanges.rdoc
6
+ #
7
+ # Runs a user-defined command when files are modified.
8
+ #
9
+ # Like autotest, but more customizable. This is useful when you want to do
10
+ # something other than run tests. For example, generate a PDF book, run
11
+ # a single test, or run a legacy Test::Unit suite in an app that also
12
+ # has an rSpec suite.
13
+ #
14
+ # Can use Ruby's Dir[] to get file glob. Quote your args to take advantage of this.
15
+ #
16
+ # rstakeout 'rake test:recent' **/*.rb
17
+ # => Only watches Ruby files one directory down (no quotes)
18
+ #
19
+ # rstakeout 'rake test:recent' '**/*.rb'
20
+ # => Watches all Ruby files in all directories and subdirectories
21
+ #
22
+ # Modified (with permission) by Geoffrey Grosenbach to call growlnotify for
23
+ # rspec and Test::Unit output.
24
+ #
25
+ # See the PeepCode screencast on rSpec or other blog articles for instructions on
26
+ # setting up growlnotify.
27
+ #
28
+ # * Added Snarl support in win32, initial implementation by Francis Fish
29
+ # * Added synchronous mode
30
+ # * Allow adjusting of sleep time
31
+ # * Fixes to work in Linux env too
32
+ # Edvard Majakari <edvard@majakari.net>
33
+
34
+ prefix = File.expand_path(File.join(File.dirname(__FILE__), '..'))
35
+ Dir["#{prefix}/vendor/*/lib"].each { |dir| $:.unshift dir }
36
+
37
+ require 'optparse'
38
+ require 'ostruct'
39
+ require 'rubygems'
40
+
41
+ def require_gem(gemname)
42
+ begin
43
+ require gemname
44
+ rescue LoadError
45
+ puts "Please install gem %s" % gemname
46
+ exit 1
47
+ end
48
+ end
49
+
50
+ FAIL_ICON_PATH = File.join(prefix, %w{data images fail.png})
51
+ OK_ICON_PATH = File.join(prefix, %w{data images ok.png})
52
+ CHANGED_ICON_PATH = File.join(prefix, %w{data images changed.png})
53
+
54
+ module GrowlNotifier
55
+ class << self
56
+ def growl_available?
57
+ @@available = system "which growlnotify > /dev/null"
58
+ end
59
+
60
+ def notify(title, msg, img, pri=0, sticky="")
61
+ system "growlnotify -n 'rstakeout notification' --image #{img} -p #{pri} -m #{msg.inspect} '#{title}' #{sticky}" if growl_available?
62
+ end
63
+
64
+ private :notify
65
+
66
+ def notify_fail(output)
67
+ notify "Failed", "#{output}", FAIL_ICON_PATH, 2
68
+ end
69
+
70
+ def notify_pass(output)
71
+ notify "Passed!", "#{output}", OK_ICON_PATH
72
+ end
73
+
74
+ def notify_changed(file)
75
+ notify "File changed", file, CHANGED_ICON_PATH
76
+ end
77
+ end
78
+ end
79
+
80
+ # TODO: instead of begin/rescue, do
81
+ # module SnarlNotifier < end
82
+ # module SnarlNotifier::AutoSnarl < end
83
+ # ?
84
+ begin
85
+ module SnarlNotifier
86
+ # Idea by Francis Fish, http://francis.blog-city.com/
87
+ begin
88
+ require 'autotest'
89
+ rescue Exception
90
+ nil
91
+ end
92
+ include AutoSnarl
93
+ module ::AutoSnarl
94
+ def self.snarl(title, msg, ico=nil, timeout=5)
95
+ Snarl.show_message(title, msg, icon[ico], timeout)
96
+ end
97
+ end
98
+
99
+ def self.notify_fail(output)
100
+ AutoSnarl::snarl "FAIL", "#{output}", :red, 30
101
+ end
102
+
103
+ def self.notify_pass(output)
104
+ AutoSnarl::snarl "Pass", "#{output}", :green, 10
105
+ end
106
+ end
107
+ rescue Exception
108
+ nil
109
+ end
110
+
111
+ module EmptyNotifier
112
+ def self.notify_pass(output)
113
+ end
114
+ def self.notify_fail(output)
115
+ end
116
+ def self.notify_changed(file)
117
+ end
118
+ end
119
+
120
+ Notifier = case RUBY_PLATFORM
121
+ when /darwin/
122
+ warn "You can install `growlnotify` for Growl notifications" unless GrowlNotifier.growl_available?
123
+ GrowlNotifier
124
+ when /win32/
125
+ require_gem 'autosnarl'
126
+ SnarlNotifier
127
+ else
128
+ EmptyNotifier
129
+ end
130
+
131
+ module ParseSpecResult
132
+ def self.notify_test_unit_results(results)
133
+ output = results.slice(/(\d+)\s+tests?,\s*(\d+)\s+assertions?,\s*(\d+)\s+failures?(,\s*(\d+)\s+errors)?/)
134
+ if output
135
+ $~[3].to_i + $~[5].to_i > 0 ? Notifier.notify_fail(output) : Notifier.notify_pass(output)
136
+ end
137
+ end
138
+
139
+ def self.notify_rspec_results(results)
140
+ output = results.slice(/(\d+)\s+examples?,\s*(\d+)\s+failures?(,\s*(\d+)\s+not implemented)?/)
141
+ if output
142
+ $~[2].to_i > 0 ? Notifier.notify_fail(output) : Notifier.notify_pass(output)
143
+ end
144
+ end
145
+ end
146
+
147
+ def build_mtimes_hash(globs)
148
+ files = {}
149
+ globs.each { |g|
150
+ Dir[g].each { |file| files[file] = File.mtime(file) }
151
+ }
152
+ files
153
+ end
154
+
155
+ trap('INT') do
156
+ puts "\nQuitting..."
157
+ exit
158
+ end
159
+
160
+ options = OpenStruct.new(:sleep_time => 1, :reload_glob => false, :synchronous => false)
161
+
162
+ OptionParser.new do |opts|
163
+ opts.banner = "Usage: rstakeout [options] <command> <filespec>+"
164
+ opts.on("-t", "--sleep-time T", Integer, "time to sleep after each loop iteration") do |t|
165
+ options.sleep_time = t
166
+ end
167
+ opts.on("-v", "--verbose") do |v|
168
+ options.verbose = v
169
+ end
170
+ opts.on("--sync", "force synchronous mode (disallow simultaneous runs)") do |s|
171
+ options.synchronous = s
172
+ end
173
+ end.parse!
174
+
175
+ MYTEMP = ENV['TEMP'] || '/tmp'
176
+
177
+ puts ARGV.inspect
178
+ command = ARGV.shift
179
+ files = build_mtimes_hash(ARGV)
180
+ LOCKFILE = File.join(MYTEMP, 'rstakeout.lock')
181
+ if options.synchronous
182
+ lock_obj = File.new(LOCKFILE, 'w')
183
+ end
184
+
185
+ if options.verbose
186
+ p options
187
+ puts "=> Watching #{files.keys.join(', ')}\n\nFiles: #{files.keys.length}"
188
+ else
189
+ puts "=> Watching #{files.keys.length} files... press Ctrl+C to stop."
190
+ end
191
+
192
+ def with_exclusive_lock_if_synchronous(run_synced, lockfile, &block)
193
+ lockfile.flock(File::LOCK_EX) if run_synced
194
+ block.call
195
+ lockfile.flock(File::LOCK_UN) if run_synced
196
+ end
197
+
198
+ loop do
199
+ changed_file, last_changed = files.find { |file, mtime|
200
+ begin
201
+ File.mtime(file) > mtime
202
+ rescue Errno::ENOENT => e # file may have been moved, deleted etc. while running rstakeout
203
+ warn e
204
+ end
205
+ }
206
+
207
+ if changed_file
208
+ with_exclusive_lock_if_synchronous(options.synchronous, lock_obj) do
209
+ files[changed_file] = File.mtime(changed_file)
210
+
211
+ system "clear"
212
+ puts "=> `#{changed_file}` changed, running '#{command}'"
213
+ puts ""
214
+
215
+ change_command = command.gsub('%s', changed_file.gsub('"', '\"'))
216
+ results = `#{change_command} 2>&1`
217
+ puts results
218
+
219
+ if results.include? 'tests'
220
+ ParseSpecResult.notify_test_unit_results(results)
221
+ #else
222
+ # ParseSpecResult.notify_rspec_results(results)
223
+ elsif $?.to_i > 0
224
+ Notifier.notify_fail "Error code #{$?.to_i}. See the log for details."
225
+ else
226
+ Notifier.notify_pass results
227
+ end
228
+ end
229
+ end
230
+ sleep options.sleep_time
231
+ end
Binary file
Binary file
metadata ADDED
@@ -0,0 +1,70 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sinefunc-rstakeout
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - edvardw
13
+ - topfunky
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-05-03 00:00:00 +08:00
19
+ default_executable: rstakeout
20
+ dependencies: []
21
+
22
+ description: This gem watches a given directory for any changes and executes a given command when something is changed.
23
+ email: rico@sinefunc.com
24
+ executables:
25
+ - rstakeout
26
+ extensions: []
27
+
28
+ extra_rdoc_files:
29
+ - README.md
30
+ files:
31
+ - .document
32
+ - .gitignore
33
+ - README.md
34
+ - Rakefile
35
+ - VERSION
36
+ - bin/rstakeout
37
+ - data/images/fail.png
38
+ - data/images/ok.png
39
+ has_rdoc: true
40
+ homepage: http://github.com/sinefunc/rstakeout
41
+ licenses: []
42
+
43
+ post_install_message:
44
+ rdoc_options:
45
+ - --charset=UTF-8
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ segments:
53
+ - 0
54
+ version: "0"
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ segments:
60
+ - 0
61
+ version: "0"
62
+ requirements: []
63
+
64
+ rubyforge_project:
65
+ rubygems_version: 1.3.6
66
+ signing_key:
67
+ specification_version: 3
68
+ summary: Watches a directory for any changes
69
+ test_files: []
70
+