observr 1.0

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.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ OGYwNDY2YjY5OWRmYjBiYjFhMDM2ZmYxYTYyZWFiYTVmODY2MWQ1Yg==
5
+ data.tar.gz: !binary |-
6
+ ZTUzMzdkYzM0NDBjZTAwOTA3ZTkzYmYwNGEwMDU5MjM3NWQ5ODViYw==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ ZjViMjA2YmVjMGE5OWRiZjY1ZWMzOTYxNzc0NWYyZmQxZTgxNTNmYjFmYThj
10
+ YWMyOTRjYzJlYzM5ODc1M2NlZjE5ODM3YjE2M2Y3NTIyMjRkMGJjNThkYTkw
11
+ NDY2OTZiMTIzYTI4NjRiNGJmMWM5ZTdlMmViNTg5ZDBiMjhhYmE=
12
+ data.tar.gz: !binary |-
13
+ NmExZGIzMjRmMjk5MDdjOWUwOTk0ODZlYzhkMjFmZjZiOTY0NWIxOGY4NGNj
14
+ YzgzMzE4MmNlYTM4NzY2NGIzMmNmNzIxNmE1MmM2NTIxZTA0OTcxZGRiZjU0
15
+ NjRiYTIzZWQwNGQzYjhlZGMxMWRmM2Y5ZGNhN2IyYzc0NGY3ZjU=
@@ -0,0 +1,6 @@
1
+ doc/
2
+ pkg/
3
+ bk/
4
+ .wiki
5
+ .yardoc
6
+ *.gem
@@ -0,0 +1,32 @@
1
+
2
+ === v0.5.7
3
+
4
+ * Added manifest.watchr script
5
+ * Unix handler supports :deleted event type
6
+ * Unix handler supports :accessed (atime), :modified (mtime) and :changed
7
+ (ctime) event types (thanks gzuki[http://github.com/gzuki] for initial work)
8
+
9
+
10
+ === v0.5.6
11
+
12
+ * Rev gem optional in development (thanks TwP[http://github.com/TwP])
13
+ * Allow gems to bundle .watchr scripts (thanks foca[http://github.com/foca])
14
+
15
+ gemname/lib/gemname.watchr
16
+
17
+ is now automatically picked up with
18
+
19
+ $ watchr gemname.watchr
20
+
21
+ * Look for script in path
22
+ * debug msg when rev not found on *nix
23
+ * rake task for cross interpreter testing
24
+
25
+
26
+ === v0.5.5
27
+
28
+ * Rev gem is optional. Fixes issue #1
29
+ Install Rev to automatically get evented handler on *nix
30
+
31
+ gem install rev
32
+
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright © 2013 Martin Aumont (mynyml)
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7
+ of the Software, and to permit persons to whom the Software is furnished to do
8
+ so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
@@ -0,0 +1,119 @@
1
+ Summary
2
+ -------
3
+
4
+ Agile development tool that monitors a directory tree, and triggers a user
5
+ defined action whenever an observed file is modified. Its most typical use is
6
+ continuous testing, and as such it is a more flexible alternative to autotest.
7
+
8
+ Features
9
+ --------
10
+
11
+ observr is:
12
+
13
+ * Simple to use
14
+ * Highly flexible
15
+ * Evented ( Listens for filesystem events with native c libs )
16
+ * Portable ( Linux, \*BSD, OSX, Solaris, Windows )
17
+ * Fast ( Immediately reacts to file changes )
18
+
19
+ Most importantly it allows running tests in an environment that is **agnostic** to:
20
+
21
+ * Web frameworks ( rails, merb, sinatra, camping, invisible, ... )
22
+ * Test frameworks ( test/unit, minitest, rspec, test/spec, expectations, ... )
23
+ * Ruby interpreters ( ruby1.8, ruby1.9, MRI, JRuby, Rubinius, ... )
24
+ * Package frameworks ( rubygems, rip, ... )
25
+
26
+ Usage
27
+ -----
28
+
29
+ On the command line,
30
+
31
+ $ observr path/to/script.file
32
+
33
+ will monitor files in the current directory tree, and react to events on those
34
+ files in accordance with the script.
35
+
36
+ Scripts
37
+ -------
38
+
39
+ The script contains a set of simple rules that map observed files to an action.
40
+ Its DSL is a single method: `watch(pattern, &action)`
41
+
42
+ watch( 'a regexp pattern matching paths to observe' ) {|match_data_object| command_to_run }
43
+
44
+ So for example,
45
+
46
+ watch( 'test/test_.*\.rb' ) {|md| system("ruby #{md[0]}") }
47
+
48
+ will match any test file and run it whenever it is saved.
49
+
50
+ A continuous testing script for a basic project could be
51
+
52
+ watch( 'test/test_.*\.rb' ) {|md| system("ruby #{md[0]}") }
53
+ watch( 'lib/(.*)\.rb' ) {|md| system("ruby test/test_#{md[1]}.rb") }
54
+
55
+ which, in addition to running any saved test file as above, will also run a
56
+ lib file's associated test. This mimics the equivalent autotest behaviour.
57
+
58
+ It's easy to see why observr is so flexible, since the whole command is custom.
59
+ The above actions could just as easily call "jruby", "ruby --rubygems", "ruby
60
+ -Ilib", "specrb", "rbx", ... or any combination of these. For the sake of
61
+ comparison, autotest runs with:
62
+
63
+ $ /usr/bin/ruby1.8 -I.:lib:test -rubygems -e "%w[test/unit test/test_helper.rb test/test_observr.rb].each { |f| require f }"
64
+
65
+ locking the environment into ruby1.8, rubygems and test/unit for all tests.
66
+
67
+ And remember the scripts are pure ruby, so feel free to add methods,
68
+ `Signal#trap` calls, etc. Updates to script files are picked up on the fly (no
69
+ need to restart observr) so experimenting is painless.
70
+
71
+ The [wiki][5] has more details and examples. You might also want to take a
72
+ look at observr's own scripts, [specs.observr][1], [docs.observr][2] and
73
+ [gem.observr][3], to get you started.
74
+
75
+ Install
76
+ -------
77
+
78
+ gem install observr
79
+
80
+ If you're on Linux/BSD and have the [rev][4] gem installed, Observr will detect
81
+ it and use it automatically. This will make Observr evented.
82
+
83
+ gem install rev
84
+
85
+ You can get the same evented behaviour on OS X by installing
86
+ [ruby-fsevent][10].
87
+
88
+ gem install ruby-fsevent
89
+
90
+ See Also
91
+ --------
92
+
93
+ * [redgreen][6]: Standalone redgreen eye candy for test results, ala autotest.
94
+ * [phocus][7]: Run focused tests when running the whole file/suite is unnecessary.
95
+ * [autoobservr][8]: Provides some autotest-like behavior for observr
96
+ * [nestor][9]: Continuous testing server for Rails
97
+
98
+ Links
99
+ -----
100
+
101
+ * code: <http://github.com/kevinburke/observr>
102
+ * docs: <http://yardoc.org/docs/mynyml-observr/file:README.rdoc>
103
+ * wiki: <http://wiki.github.com/mynyml/observr>
104
+ * bugs: <http://github.com/kevinburke/observr/issues>
105
+
106
+
107
+
108
+
109
+ [1]: http://github.com/kevinburke/observr/blob/master/specs.observr
110
+ [2]: http://github.com/kevinburke/observr/blob/master/docs.observr
111
+ [3]: http://github.com/kevinburke/observr/blob/master/gem.observr
112
+ [4]: http://github.com/tarcieri/rev/
113
+ [5]: http://wiki.github.com/mynyml/observr
114
+ [6]: http://github.com/mynyml/redgreen
115
+ [7]: http://github.com/mynyml/phocus
116
+ [8]: http://github.com/viking/autoobservr
117
+ [9]: http://github.com/francois/nestor
118
+ [10]: http://github.com/sandro/ruby-fsevent
119
+
@@ -0,0 +1,34 @@
1
+ def gem_opt
2
+ defined?(Gem) ? "-rubygems" : ""
3
+ end
4
+
5
+ def ruby
6
+ require 'rbconfig'
7
+ File.join([Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name']]) << Config::CONFIG['EXEEXT']
8
+ end
9
+
10
+ # --------------------------------------------------
11
+ # Tests
12
+ # --------------------------------------------------
13
+ task(:default => "test:all")
14
+
15
+ namespace(:test) do
16
+
17
+ desc "Run all tests"
18
+ task(:all) do
19
+ tests = Dir['test/**/test_*.rb'] - ['test/test_helper.rb']
20
+ exit system(%Q{#{ruby} #{gem_opt} -I.:lib -e"%w( #{tests.join(' ')} ).each {|file| require file }"})
21
+ end
22
+
23
+ desc "Run all tests on multiple ruby versions (requires rvm)"
24
+ task(:portability) do
25
+ %w( 1.8.6 1.8.7 1.9.1 1.9.2 ).each do |version|
26
+ system <<-BASH
27
+ bash -c 'source ~/.rvm/scripts/rvm;
28
+ rvm #{version};
29
+ echo "--------- v#{version} ----------\n";
30
+ rake -s test:all'
31
+ BASH
32
+ end
33
+ end
34
+ end
data/TODO.md ADDED
@@ -0,0 +1,31 @@
1
+ Features
2
+ --------
3
+
4
+ * observr -e ( `$ observr -e "watch('foo.gemspec') { system('gem build foo.gemspec') }"` )
5
+ * observr --auto
6
+ * observr --fetch
7
+
8
+ * enable ability to watch dirs
9
+ * requires new handler(s)
10
+ * will allow recognizing `:added` events
11
+
12
+ * allow setting latency
13
+
14
+ Bugs
15
+ ----
16
+
17
+ * sometimes an action is fired without a file being saved
18
+ * buffer flushing issue?
19
+ * libev issue?
20
+ * probably fixed with event type handling update, which ignores atime
21
+ updates by defaults
22
+
23
+ * when a file is saved twice quickly, subsequent events are ignored.
24
+ * seems like rev/libev drops the file watch
25
+
26
+ Other
27
+ -----
28
+
29
+ * add tests for executable
30
+ * memory profiling / benchmarks
31
+
@@ -0,0 +1,105 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'pathname'
4
+ require 'optparse'
5
+ require 'tempfile'
6
+
7
+ require File.dirname(__FILE__) + '/../lib/observr'
8
+
9
+ module Observr
10
+ # Namespaced to avoid defining global methods
11
+ #
12
+ # @private
13
+ module Bin
14
+ extend self
15
+
16
+ DEFAULT_SCRIPT_PATH = Pathname.new('specs.observr')
17
+
18
+ attr_accessor :path
19
+
20
+ def usage
21
+ "Usage: observr [opts] path/to/script"
22
+ end
23
+
24
+ def version
25
+ "observr version: %s" % Observr::VERSION
26
+ end
27
+
28
+ # Absolute path to script file
29
+ #
30
+ # Unless set manually, the script's path is either first arg or
31
+ # `DEFAULT_SCRIPT_PATH`. If neither exists, the script immediatly aborts
32
+ # with an appropriate error message.
33
+ #
34
+ # @return [Pathname]
35
+ # absolute path to script
36
+ #
37
+ def path!
38
+ return @path unless @path.nil?
39
+ rel = relative_path or abort( usage )
40
+ find_in_load_path(rel) or abort("no script found: file #{rel.to_s.inspect} is not in path.")
41
+ end
42
+
43
+ # Find a partial path name in load path
44
+ #
45
+ # @param [Pathname] path
46
+ # partial pathname
47
+ #
48
+ # @return [Pathname]
49
+ # absolute path of first occurence of partial path in load path, or nil if not found
50
+ #
51
+ def find_in_load_path(path)
52
+ # Adds '.' for ruby1.9.2
53
+ dir = (['.'] + $LOAD_PATH).uniq.detect {|p| Pathname(p).join(path).exist? }
54
+ dir ? path.expand_path(dir) : nil
55
+ end
56
+
57
+ private
58
+
59
+ def relative_path
60
+ return Pathname.new(ARGV.first) if ARGV.first
61
+ return DEFAULT_SCRIPT_PATH if DEFAULT_SCRIPT_PATH.exist?
62
+ end
63
+ end
64
+ end
65
+
66
+ opts = OptionParser.new do |opts|
67
+ opts.banner = Observr::Bin.usage
68
+
69
+ opts.on('-d', '--debug', "Print extra debug info while program runs") {
70
+ Observr.options.debug = true
71
+ begin
72
+ require 'ruby-debug'
73
+ rescue LoadError, RuntimeError
74
+ end
75
+ }
76
+ opts.on('-l', '--list', "Display list of files monitored by script and exit") {
77
+ script = Observr::Script.new(Observr::Bin.path!)
78
+ controller = Observr::Controller.new(script, Observr.handler.new)
79
+ script.parse!
80
+ puts controller.monitored_paths
81
+ exit
82
+ }
83
+
84
+ def assert_syntax(code)
85
+ catch(:ok) { Object.new.instance_eval("BEGIN { throw :ok }; #{code}", %|-e "#{code}"|, 0) }
86
+ rescue SyntaxError => e
87
+ puts e.message.split("\n")[1]
88
+ exit
89
+ end
90
+
91
+ opts.on('-e', '--eval INLINE_SCRIPT', %|Evaluate script inline ($ observr -e "watch('foo') { puts 'bar' }")|) {|code|
92
+ assert_syntax(code)
93
+
94
+ Tempfile.open('foo') {|f| f << code; @__path = f.path }
95
+ Observr::Bin.path = Pathname(@__path)
96
+ }
97
+
98
+ opts.on_tail('-h', '--help', "Print inline help") { puts opts; exit }
99
+ opts.on_tail('-v', '--version', "Print version" ) { puts Observr::Bin.version; exit }
100
+
101
+ opts.parse! ARGV
102
+ end
103
+
104
+ Observr::Controller.new(Observr::Script.new(Observr::Bin.path!), Observr.handler.new).run
105
+
@@ -0,0 +1,7 @@
1
+
2
+ Suggestions:
3
+ macournoyer, foca
4
+
5
+ Patches:
6
+ TwP, gzuki, spraints, francois
7
+
@@ -0,0 +1,26 @@
1
+ # Run me with:
2
+ # $ observr docs.observr
3
+
4
+ require 'yard'
5
+ # --------------------------------------------------
6
+ # Rules
7
+ # --------------------------------------------------
8
+ watch( 'lib/.*\.rb' ) { yard }
9
+ watch( 'README.md' ) { yard }
10
+ watch( 'TODO.md' ) { yard }
11
+ watch( 'LICENSE' ) { yard }
12
+
13
+ # --------------------------------------------------
14
+ # Signal Handling
15
+ # --------------------------------------------------
16
+ Signal.trap('QUIT') { yard } # Ctrl-\
17
+ Signal.trap('INT' ) { abort("\n") } # Ctrl-C
18
+
19
+ # --------------------------------------------------
20
+ # Helpers
21
+ # --------------------------------------------------
22
+ def yard
23
+ print "Updating yardocs... "; STDOUT.flush
24
+ YARD::CLI::Yardoc.run *%w( -o doc/yard --readme README.md --markup markdown - LICENSE TODO.md )
25
+ print "done\n"
26
+ end
@@ -0,0 +1,22 @@
1
+ # Run me with:
2
+ # $ observr gem.observr
3
+
4
+ def gemspec() Dir['*.gemspec'].first end
5
+ # --------------------------------------------------
6
+ # Rules
7
+ # --------------------------------------------------
8
+ watch( gemspec ) { build }
9
+
10
+ # --------------------------------------------------
11
+ # Signal Handling
12
+ # --------------------------------------------------
13
+ Signal.trap('QUIT') { build } # Ctrl-\
14
+ Signal.trap('INT' ) { abort("\n") } # Ctrl-C
15
+
16
+ # --------------------------------------------------
17
+ # Helpers
18
+ # --------------------------------------------------
19
+ def build
20
+ puts; system "gem build #{gemspec}"
21
+ FileUtils.mv( Dir['*.gem'], 'pkg/' )
22
+ end
@@ -0,0 +1,133 @@
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
+ # See README for more details
9
+ #
10
+ # @example
11
+ #
12
+ # # on command line, from project's root dir
13
+ # $ observr path/to/script
14
+ #
15
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
16
+ module Observr
17
+ VERSION = '1.0'
18
+
19
+ begin
20
+ #require 'fsevent'
21
+ #HAVE_FSE = true
22
+ #rescue LoadError, RuntimeError
23
+ HAVE_FSE = false
24
+ end
25
+
26
+ begin
27
+ require 'rev'
28
+ HAVE_REV = true
29
+ rescue LoadError, RuntimeError
30
+ HAVE_REV = false
31
+ end
32
+
33
+ autoload :Script, 'observr/script'
34
+ autoload :Controller, 'observr/controller'
35
+
36
+ module EventHandler
37
+ autoload :Base, 'observr/event_handlers/base'
38
+ autoload :Portable, 'observr/event_handlers/portable'
39
+ autoload :Unix, 'observr/event_handlers/unix' if ::Observr::HAVE_REV
40
+ autoload :Darwin, 'observr/event_handlers/darwin' if ::Observr::HAVE_FSE
41
+ end
42
+
43
+ class << self
44
+ attr_accessor :options
45
+ attr_accessor :handler
46
+
47
+ # @deprecated
48
+ def version #:nodoc:
49
+ Observr::VERSION
50
+ end
51
+
52
+ # Options proxy.
53
+ #
54
+ # Currently supported options:
55
+ #
56
+ # * debug[Boolean] Debugging state. More verbose.
57
+ #
58
+ # @example
59
+ #
60
+ # Observr.options.debug #=> false
61
+ # Observr.options.debug = true
62
+ #
63
+ # @return [Struct]
64
+ # options proxy.
65
+ #
66
+ def options
67
+ @options ||= Struct.new(:debug).new
68
+ @options.debug ||= false
69
+ @options
70
+ end
71
+
72
+ # Outputs formatted debug statement to stdout, only if `::options.debug` is true
73
+ #
74
+ # @example
75
+ #
76
+ # Observr.options.debug = true
77
+ # Observr.debug('im in ur codes, notifayinin u')
78
+ #
79
+ # #outputs: "[observr debug] im in ur codes, notifayinin u"
80
+ #
81
+ # @param [String] message
82
+ # debug message to print
83
+ #
84
+ # @return [nil]
85
+ #
86
+ def debug(msg)
87
+ puts "[observr debug] #{msg}" if options.debug
88
+ end
89
+
90
+ # Detect current OS and return appropriate handler.
91
+ #
92
+ # @example
93
+ #
94
+ # Config::CONFIG['host_os'] #=> 'linux-gnu'
95
+ # Observr.handler #=> Observr::EventHandler::Unix
96
+ #
97
+ # Config::CONFIG['host_os'] #=> 'cygwin'
98
+ # Observr.handler #=> Observr::EventHandler::Portable
99
+ #
100
+ # ENV['HANDLER'] #=> 'unix'
101
+ # Observr.handler #=> Observr::EventHandler::Unix
102
+ #
103
+ # ENV['HANDLER'] #=> 'portable'
104
+ # Observr.handler #=> Observr::EventHandler::Portable
105
+ #
106
+ # @return [Class]
107
+ # handler class for current architecture
108
+ #
109
+ def handler
110
+ @handler ||=
111
+ case ENV['HANDLER'] || Config::CONFIG['host_os']
112
+ when /darwin|mach|osx|fsevents?/i
113
+ if Observr::HAVE_FSE
114
+ Observr::EventHandler::Darwin
115
+ else
116
+ Observr.debug "fsevent not found. `gem install ruby-fsevent` to get evented handler"
117
+ Observr::EventHandler::Portable
118
+ end
119
+ when /sunos|solaris|bsd|linux|unix/i
120
+ if Observr::HAVE_REV
121
+ Observr::EventHandler::Unix
122
+ else
123
+ Observr.debug "rev not found. `gem install rev` to get evented handler"
124
+ Observr::EventHandler::Portable
125
+ end
126
+ when /mswin|windows|cygwin/i
127
+ Observr::EventHandler::Portable
128
+ else
129
+ Observr::EventHandler::Portable
130
+ end
131
+ end
132
+ end
133
+ end