sinefunc-rstakeout 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.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
+