wake 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,6 @@
1
+ doc/
2
+ pkg/
3
+ bk/
4
+ .wiki
5
+ .yardoc
6
+ /*.gem
data/LICENSE ADDED
@@ -0,0 +1,44 @@
1
+ Wake license:
2
+
3
+ Copyright (c) 2010 Steven Parkes
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ Watch license:
25
+
26
+ Copyright © 2009 Martin Aumont (mynyml)
27
+
28
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
29
+ this software and associated documentation files (the "Software"), to deal in
30
+ the Software without restriction, including without limitation the rights to
31
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
32
+ of the Software, and to permit persons to whom the Software is furnished to do
33
+ so, subject to the following conditions:
34
+
35
+ The above copyright notice and this permission notice shall be included in all
36
+ copies or substantial portions of the Software.
37
+
38
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
41
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
42
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
43
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
44
+ SOFTWARE.
@@ -0,0 +1,30 @@
1
+ .gitignore
2
+ History.txt
3
+ LICENSE
4
+ Manifest
5
+ README.rdoc
6
+ Rakefile
7
+ TODO.txt
8
+ bin/wake
9
+ docs.wk
10
+ gem.wk
11
+ lib/wake.rb
12
+ lib/wake/controller.rb
13
+ lib/wake/event_handlers/base.rb
14
+ lib/wake/event_handlers/portable.rb
15
+ lib/wake/event_handlers/unix.rb
16
+ lib/wake/event_handlers/rev.rb
17
+ lib/wake/event_handlers/em.rb
18
+ lib/wake/script.rb
19
+ manifest.wk
20
+ specs.wk
21
+ test/README
22
+ test/event_handlers/test_base.rb
23
+ test/event_handlers/test_portable.rb
24
+ test/event_handlers/test_rev.rb
25
+ test/event_handlers/test_em.rb
26
+ test/test_controller.rb
27
+ test/test_helper.rb
28
+ test/test_script.rb
29
+ test/test_wake.rb
30
+ wake.gemspec
@@ -0,0 +1,105 @@
1
+ === Summary
2
+
3
+ The vision for wake is as a sort of rake/make like program, combined
4
+ with the real-time filesystem "watching" aspect of autotest/autospec/watchr.
5
+
6
+ Wake started out (and still is) mostly a fork of the watchr gem at
7
+ http://github.com/mynyml/watchr.
8
+
9
+ The are a number of differences now and they're expected to grow.
10
+
11
+ It's been ported to EventMachine for file-events and has some
12
+ extensions for how watches can be written.
13
+
14
+ To install, you can clone the repo (http://github.com/smparkes/wake)
15
+ or install the gem, <tt>wake</tt>. Note that for now, you'll need my
16
+ copy of EventMachine (http://github.com/smparkes/eventmachine or the
17
+ <tt>smparkes-eventmachine</tt> gem) for directory watches to work
18
+ well. (These changes are in the process of getting pulled upstream.)
19
+
20
+ == EventMachine
21
+
22
+ Not much to say. It supports EM as well as Rev, though the Rev stuff
23
+ will probably be dropped unles there's a compelling reason to keep
24
+ it. The default is still Rev. To use EventMachine, after installing
25
+ the EM gem, I just add
26
+
27
+ begin; require 'wake/event_handlers/em'; rescue LoadError; end
28
+
29
+ to my <tt>Wakefile</tt>. It'll use the first required backend, or
30
+ Rev if none are found (and Rev is installed). There may be better ways to
31
+ do this.
32
+
33
+ === Event processing extensions
34
+
35
+ I made several changes to the way events are created/processed, mostly
36
+ to make my <tt>Wakefile</tt> work:
37
+
38
+ #!/usr/bin/env wake
39
+
40
+ begin; require 'wake/event_handlers/em'; rescue LoadError; end
41
+
42
+ watch( %r(.*), :modified, lambda { |md| File.directory? md[0] } ) do |md|
43
+ raise Wake::Refresh
44
+ end
45
+
46
+ watch( %r((public/.*)\.haml$), [ :created, :modified ] ) do |md|
47
+ cmd = "rm -f #{md[1]}.html && haml -f html5 #{md[0]} #{md[1]}.html && chmod 444 #{md[1]}.html"
48
+ puts cmd
49
+ system cmd
50
+ if $?.signaled? && $?.termsig == 2
51
+ Process.kill 2, 0
52
+ end
53
+ end
54
+
55
+ watch( %r((spec/.*[Ss]pec)\.(html|js)$), [ :load, :created, :modified ] ) do |md|
56
+ cmd = "jazrb #{md[0]}"
57
+ puts cmd
58
+ system cmd
59
+ if $?.signaled? && $?.termsig == 2
60
+ Process.kill 2, 0
61
+ end
62
+ end
63
+
64
+ The purpose of the first watch is to cause wake to refresh when
65
+ directories change. This allows new files to be picked up. The watch
66
+ pattern matches all files in the current directory tree (though not
67
+ <tt>.</tt> itself; probably should), and watches for
68
+ <tt>:modified</tt> events. It adds an extra lambda that is processed
69
+ while looking at file paths: only directories will get watches put on
70
+ them. (Otherwise <tt>%r(.*)</tt> would put watches on every
71
+ file/directory in the tree, which seems kinda bad.)
72
+
73
+ The second watch looks for Haml files in my public directory and
74
+ automatically converts them to HTML. These are static files, not
75
+ served by an app server like Rails: even with static files, I hate
76
+ writing raw HTML. The extension here is so that instead of a single event
77
+ type, I can pass an array. In addition to the <tt>:modified</tt>,
78
+ event, this will get called when wake notes that a new file of this
79
+ type has appeared. (Note this works starting from wake's first pass;
80
+ files created while wake wasn't running don't count).
81
+
82
+ Then final watch looks for JavaScript and HTML spec files and runs
83
+ them under jazrb (see http://github.com/smparkes/jazrb if
84
+ interested). This case is similar to the previous but also adds the
85
+ <tt>:load</tt> event. This event gets fired the first time a file is
86
+ seen after wake starts. This allows wake to run all the specs when
87
+ first started, similar to what autotest does.
88
+
89
+ === Recent Changes
90
+
91
+ 1. POC for batch events that occur within a time window
92
+
93
+ 1. Pass event type to callbacks
94
+
95
+ 1. Has some POC dependency detection. Needs to be formalized into an API and have a better backend.
96
+
97
+ === Things to do
98
+
99
+ 1. Move directory watch into wake itself
100
+
101
+ 1. Handle user interrupt processing more systematically
102
+
103
+ 1. Don't swallow config file error messages, particularly on reload. Is this still happening?
104
+
105
+ 1. Integrate with rake/make.
@@ -0,0 +1,51 @@
1
+ require 'rake/rdoctask'
2
+ begin
3
+ require 'yard'
4
+ rescue LoadError, RuntimeError
5
+ end
6
+
7
+ desc "Generate rdoc documentation."
8
+ Rake::RDocTask.new(:rdoc => 'rdoc', :clobber_rdoc => 'rdoc:clean', :rerdoc => 'rdoc:force') { |rdoc|
9
+ rdoc.rdoc_dir = 'doc/rdoc'
10
+ rdoc.title = "Wake"
11
+ rdoc.options << '--line-numbers' << '--inline-source'
12
+ rdoc.options << '--charset' << 'utf-8'
13
+ rdoc.main = 'README.rdoc'
14
+ rdoc.rdoc_files.include('README.rdoc')
15
+ rdoc.rdoc_files.include('TODO.txt')
16
+ rdoc.rdoc_files.include('LICENSE')
17
+ rdoc.rdoc_files.include('lib/**/*.rb')
18
+ }
19
+
20
+ if defined? YARD
21
+ YARD::Rake::YardocTask.new do |t|
22
+ t.files = %w( lib/**/*.rb )
23
+ t.options = %w( -o doc/yard --readme README.rdoc --files LICENSE,TODO.txt )
24
+ end
25
+ end
26
+
27
+ namespace(:test) do
28
+
29
+ desc "Run all tests"
30
+ task(:all) do
31
+ tests = Dir['test/**/test_*.rb'] - ['test/test_helper.rb']
32
+ cmd = "ruby -rubygems -Ilib -e'%w( #{tests.join(' ')} ).each {|file| require file }'"
33
+ puts cmd if ENV['VERBOSE']
34
+ system cmd
35
+ end
36
+
37
+ desc "Run all tests on multiple ruby versions (requires rvm with 1.8.6 and 1.8.7)"
38
+ task(:portability) do
39
+ versions = %w( 1.8.6 1.8.7 )
40
+ versions.each do |version|
41
+ system <<-BASH
42
+ bash -c 'source ~/.rvm/scripts/rvm;
43
+ rvm use #{version};
44
+ echo "--------- `ruby -v` ----------\n";
45
+ rake -s test:all'
46
+ BASH
47
+ end
48
+ end
49
+ end
50
+
51
+ task :default => "test:all"
@@ -0,0 +1,88 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $VERBOSE = true
4
+
5
+ require 'pathname'
6
+ require 'optparse'
7
+
8
+ require 'wake'
9
+
10
+ module Wake
11
+ # Namespaced to avoid defining global methods
12
+ module Bin #:nodoc:
13
+ extend self
14
+
15
+ def usage
16
+ "Usage: wake [opts] [path/to/script]"
17
+ end
18
+
19
+ def version
20
+ "wake version: %s" % Wake::VERSION
21
+ end
22
+
23
+ # Find a partial path name in load path
24
+ #
25
+ # ===== Params
26
+ # path<Pathname>:: partial pathname
27
+ #
28
+ # ===== Returns
29
+ # <Pathname>::
30
+ # absolute path of first occurence of partial path in load path, or nil if not found
31
+ #
32
+ def find_in_load_path(path)
33
+ dir = potentially_with_gem( path.basename('.wk') ) do
34
+ $LOAD_PATH.detect {|p| Pathname(p).join(path).exist? }
35
+ end
36
+ dir ? path.expand_path(dir) : nil
37
+ end
38
+
39
+ private
40
+
41
+ # If the block returns nil, requires gem <tt>name</tt> and tries running the
42
+ # block again. If all fails, returns nil
43
+ #
44
+ # ===== Params
45
+ # name<Pathname,String>:: name of gem to require
46
+ #
47
+ # ===== Returns
48
+ # block's value or nil if gem <tt>name</tt> doesn't exist
49
+ #
50
+ def potentially_with_gem(name)
51
+ yield || (require(name) && yield)
52
+ rescue LoadError
53
+ nil
54
+ end
55
+ end
56
+ end
57
+
58
+ opts = OptionParser.new do |opts|
59
+ opts.banner = Wake::Bin.usage
60
+
61
+ opts.on('-d', '--debug', "Print extra debug info while program runs") {
62
+ Wake.options.debug = true
63
+ begin
64
+ require 'ruby-debug'
65
+ rescue LoadError, RuntimeError
66
+ end
67
+ }
68
+
69
+ opts.on('-1', '--once', "Run load patterns and then exit") {
70
+ Wake.options.once = true
71
+ }
72
+
73
+ opts.on('-f', '--wakefile FILE', "use wakefile FILE") { |file|
74
+ Wake.options.wakefile = file
75
+ }
76
+
77
+ opts.on_tail('-h', '--help', "Print inline help") { puts opts; exit }
78
+ opts.on_tail('-v', '--version', "Print version" ) { puts Wake::Bin.version; exit }
79
+
80
+ opts.parse! ARGV
81
+ end
82
+
83
+ path = Wake.options.wakefile || "Wakefile"
84
+ relative_path = Pathname( path ) rescue abort(Wake::Bin.usage)
85
+ absolute_path = Wake::Bin.find_in_load_path(relative_path) or abort("no script found; file #{relative_path.to_s.inspect} is not in path.")
86
+
87
+ Wake::Controller.new(Wake::Script.new(absolute_path)).run
88
+
data/docs.wk ADDED
@@ -0,0 +1,26 @@
1
+ # Run me with:
2
+ #
3
+ # $ wake -f docs.wk
4
+
5
+ def run_rdoc
6
+ system('rake --silent rdoc')
7
+ end
8
+
9
+ def run_yard
10
+ print "\nUpdating yardocs... "
11
+ system('rake --silent yardoc')
12
+ print "done.\n"
13
+ end
14
+
15
+ def document
16
+ run_rdoc
17
+ run_yard
18
+ end
19
+
20
+ watch( 'lib/.*\.rb' ) { document }
21
+ watch( 'README.rdoc' ) { document }
22
+ watch( 'TODO.txt' ) { document }
23
+ watch( 'LICENSE' ) { document }
24
+
25
+
26
+ # vim:ft=ruby
data/gem.wk ADDED
@@ -0,0 +1,32 @@
1
+ # Run me with:
2
+ #
3
+ # $ wake gem.wk
4
+
5
+ # --------------------------------------------------
6
+ # Convenience Methods
7
+ # --------------------------------------------------
8
+ def build(gemspec)
9
+ system "gem build %s" % gemspec
10
+ FileUtils.mv Dir['wake-*.gem'], 'pkg/'
11
+ puts
12
+ end
13
+
14
+ # --------------------------------------------------
15
+ # Wake Rules
16
+ # --------------------------------------------------
17
+ watch( '^wake.gemspec$' ) { |m| build m[0] }
18
+
19
+ # --------------------------------------------------
20
+ # Signal Handling
21
+ # --------------------------------------------------
22
+ # Ctrl-\
23
+ Signal.trap('QUIT') do
24
+ puts " --- Building Gem ---\n\n"
25
+ build 'wake.gemspec'
26
+ end
27
+
28
+ # Ctrl-C
29
+ Signal.trap('INT') { abort("\n") }
30
+
31
+
32
+ # vim:ft=ruby
@@ -0,0 +1,109 @@
1
+ require 'pathname'
2
+ require 'rbconfig'
3
+
4
+ # Agile development tool that monitors a directory recursively, and triggers a
5
+ # user defined action whenever an observed file is modified. Its most typical
6
+ # use is continuous testing.
7
+ #
8
+ # Usage:
9
+ #
10
+ # # on command line, from project's root dir
11
+ # $ wake path/to/script
12
+ # # default script if none is given is Wakefile.
13
+ #
14
+ # See README for more details
15
+ #
16
+ module Wake
17
+ VERSION = '0.1.0'
18
+
19
+ autoload :Script, 'wake/script'
20
+ autoload :Controller, 'wake/controller'
21
+
22
+ module EventHandler
23
+ autoload :Base, 'wake/event_handlers/base'
24
+ autoload :Unix, 'wake/event_handlers/unix'
25
+ autoload :Portable, 'wake/event_handlers/portable'
26
+ end
27
+
28
+ class << self
29
+ # backwards compatibility
30
+ def version #:nodoc:
31
+ Wake::VERSION
32
+ end
33
+
34
+ # Options proxy.
35
+ #
36
+ # Currently supported options:
37
+ # * debug<Boolean> Debugging state. More verbose.
38
+ #
39
+ # ===== Examples
40
+ #
41
+ # Wake.options.debug #=> false
42
+ # Wake.options.debug = true
43
+ #
44
+ # ===== Returns
45
+ # options<Struct>:: options proxy.
46
+ #
47
+ #--
48
+ # On first use, initialize the options struct and default option values.
49
+ def options
50
+ @options ||= Struct.new(:debug,:once, :wakefile).new
51
+ @options.debug ||= false
52
+ @options.once.nil? and @options.once = false
53
+ @options
54
+ end
55
+
56
+ def options= arg
57
+ @options = arg
58
+ end
59
+
60
+ # Outputs formatted debug statement to stdout, only if ::options.debug is true
61
+ #
62
+ # ===== Examples
63
+ #
64
+ # Wake.options.debug = true
65
+ # Wake.debug('im in ur codes, notifayinin u')
66
+ #
67
+ # outputs: "[wake debug] im in ur codes, notifayinin u"
68
+ #
69
+ def debug(str)
70
+ puts "[wake debug] #{str}" if options.debug
71
+ end
72
+
73
+ # Detect current OS and return appropriate handler.
74
+ #
75
+ # ===== Examples
76
+ #
77
+ # Config::CONFIG['host_os'] #=> 'linux-gnu'
78
+ # Wake.handler #=> Wake::EventHandler::Unix
79
+ #
80
+ # Config::CONFIG['host_os'] #=> 'cygwin'
81
+ # Wake.handler #=> Wake::EventHandler::Portable
82
+ #
83
+ # ENV['HANDLER'] #=> 'unix'
84
+ # Wake.handler #=> Wake::EventHandler::Unix
85
+ #
86
+ # ENV['HANDLER'] #=> 'portable'
87
+ # Wake.handler #=> Wake::EventHandler::Portable
88
+ #
89
+ # ===== Returns
90
+ # handler<Class>:: handler class for current architecture
91
+ #
92
+ def handler
93
+ @handler ||=
94
+ case ENV['HANDLER'] || Config::CONFIG['host_os']
95
+ when /mswin|windows|cygwin/i
96
+ Wake::EventHandler::Portable
97
+ when /sunos|solaris|darwin|mach|osx|bsd|linux/i, 'unix'
98
+ Wake::EventHandler::Unix.default
99
+ else
100
+ Wake::EventHandler::Portable
101
+ end
102
+ end
103
+
104
+ def handler= arg
105
+ @handler = arg
106
+ end
107
+
108
+ end
109
+ end