watcher 1.1.0 → 1.2.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.
@@ -1,7 +1,7 @@
1
1
  module Watcher
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 1
4
- MINOR = 1
4
+ MINOR = 2
5
5
  TINY = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
data/script/txt2html CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/ruby
1
+ #!/usr/bin/env ruby
2
2
 
3
3
  GEM_NAME = 'watcher' # what ppl will type to install your gem
4
4
  RUBYFORGE_PROJECT = 'watcher'
data/test/tc_event.rb ADDED
@@ -0,0 +1,73 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- Ruby -*-
3
+ # Watcher Tests
4
+ #
5
+ # Summary:: Watcher provides advanced integrated exception handling and
6
+ # logging functionality to your Ruby programs.
7
+ # Author:: Karrick McDermott (karrick@karrick.org)
8
+ # Date:: 2008-07-04
9
+ # Copyright:: Copyright (c) 2008 by Karrick McDermott. All rights reserved.
10
+ # License:: Simplified BSD License.
11
+
12
+ ######################################################################
13
+
14
+ require "test/unit"
15
+ require "event"
16
+
17
+ class TestEvent < Test::Unit::TestCase
18
+ def setup
19
+ @title = 'TITLE'
20
+ @time = Time.now.utc
21
+ @fail_actions = {:failure => :error}
22
+ @relationship = :child
23
+ @base = nil
24
+
25
+ # Create a root event node
26
+ # (time, hier, title, fail_actions, relationship)
27
+ @root = Event.new(@time, nil, @title, @fail_actions, :child)
28
+ end
29
+
30
+ def test_child_of_child
31
+ first_child = @root.child
32
+ assert_kind_of(Event, first_child)
33
+ assert_equal('0.a', first_child.hier)
34
+
35
+ second_child = first_child.child
36
+ assert_equal('0.a.0', second_child.hier)
37
+ end
38
+
39
+ def test_sibling_of_sibling
40
+ first_sibling = @root.sibling
41
+ assert_kind_of(Event, first_sibling)
42
+ assert_equal('1', first_sibling.hier)
43
+
44
+ second_sibling = first_sibling.sibling
45
+ assert_kind_of(Event, second_sibling)
46
+ assert_equal('2', second_sibling.hier)
47
+ end
48
+
49
+ def test_child_of_sibling
50
+ sibling = @root.sibling
51
+ assert_kind_of(Event, sibling)
52
+ assert_equal('1', sibling.hier)
53
+
54
+ child = sibling.child
55
+ assert_kind_of(Event, child)
56
+ assert_equal('1.a', child.hier)
57
+ end
58
+
59
+ def test_sibling_of_child
60
+ child = @root.child
61
+ assert_kind_of(Event, child)
62
+ assert_equal('0.a', child.hier)
63
+
64
+ sibling = child.sibling
65
+ assert_kind_of(Event, sibling)
66
+ assert_equal('0.b', sibling.hier)
67
+ end
68
+
69
+ # def test_initialize_fail_actions
70
+ # assert_raise(:ArgumentError) { Event.new(@time, nil, @title, {}, :child)
71
+ #
72
+ # end
73
+ end
data/test/test_watcher.rb CHANGED
@@ -1,11 +1,98 @@
1
- require File.dirname(__FILE__) + '/test_helper.rb'
2
-
3
- class TestWatcher < Test::Unit::TestCase
4
-
5
- def setup
6
- end
7
-
8
- def test_truth
9
- assert true
10
- end
11
- end
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+ require File.dirname(__FILE__) + '/tc_event.rb'
3
+
4
+ class TestWatcher < Test::Unit::TestCase
5
+ MAX_ATTEMPTS = 3
6
+
7
+ def setup
8
+ params = {:warn_symbol=>'WARNING', :error_symbol => 'ERROR'}
9
+ params = params.merge(:verbosity => :verbose)
10
+ params = params.merge(:default_fail => {:failure => :error})
11
+ @w = Watcher.create(params)
12
+ end
13
+
14
+ def test_exception_causes_warning
15
+ @w.verbose("Test -- exception causes warning") do
16
+ # Ensure that when pass :warn, Watcher will not re-raise exception,
17
+ # provided the :proc doesn't throw an exception as well
18
+ assert_nothing_thrown do
19
+ @w.debug("causing an exception, but catch with :warn", :failure => :warn) do
20
+ raise RuntimeError.new("exception")
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ def test_exception_reraised
27
+ @w.verbose("Test -- exception re-raised") do
28
+ # Ensure that when no :failure passed, Watcher will re-raise exception
29
+ assert_raise(RuntimeError) do
30
+ @w.debug("causing an exception, no catch") do
31
+ raise RuntimeError.new("exception")
32
+ end
33
+ end
34
+
35
+ # Ensure that when pass :error, Watcher will re-raise exception,
36
+ assert_raise(RuntimeError) do
37
+ @w.debug("causing an exception, no catch", :failure => :error) do
38
+ raise RuntimeError.new("exception")
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ def test_retries_then_reraise
45
+ @w.verbose("Test -- retries resulting in re-raising exception") do
46
+ # Watcher will execute specified number of tries, then re-raise.
47
+ # The Proc simply closes over out retry_count variable, incrementing it.
48
+ attempt_count = 0 # Count how many tries actually occured
49
+ assert_raise(RuntimeError) do
50
+ @w.debug("causing exception with #{MAX_ATTEMPTS} tries then error", {:tries => MAX_ATTEMPTS, :proc => lambda { |e| attempt_count += 1 }, :failure => :error}) do
51
+ raise RuntimeError.new("exception")
52
+ end
53
+ end
54
+ # NOTE: off-by-one because we run Proc in-between attempts
55
+ assert_equal(MAX_ATTEMPTS-1, attempt_count)
56
+ end
57
+ end
58
+
59
+ def test_retries_then_warn
60
+ @w.verbose("Test -- retries resulting in log warning") do
61
+ # Watcher will execute specified number of tries, then warn.
62
+ # The Proc simply closes over out retry_count variable, incrementing it.
63
+ attempt_count = 0 # Count how many tries actually occured
64
+ assert_nothing_thrown do
65
+ @w.debug("causing exception with #{MAX_ATTEMPTS} tries then warning", {:tries => MAX_ATTEMPTS, :proc => lambda { |e| attempt_count += 1 }, :failure => :warn}) do
66
+ raise RuntimeError.new("exception")
67
+ end
68
+ end
69
+ # NOTE: off-by-one because we run Proc in-between attempts
70
+ assert_equal(MAX_ATTEMPTS-1, attempt_count)
71
+ end
72
+ end
73
+
74
+ def test_embedded_levels
75
+ @w.verbose("Test -- embedded levels") do
76
+ assert_nothing_thrown do
77
+ @w.debug("outside level, re-raise if error", :failure => :error) do
78
+ @w.debug("inside level, warn if error", :failure => :warn) do
79
+ raise RuntimeError.new("exception")
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
85
+
86
+ def test_send_email_without_output_file
87
+ # Watcher with output sent to STDOUT, and give
88
+ # signal to send email.
89
+ # Result should append a note to the log.
90
+ # (It should probably throw an exception, because invocation is wrong.)
91
+
92
+ # Let's get an entry on the log, but don't wrap around a block
93
+ @w.always("about to test sending email without output file")
94
+ assert_raise(ArgumentError) do
95
+ @w.send_email("root@localhost", "FAIL: Watcher should not have sent this")
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- Ruby -*-
3
+ #
4
+ # TO EXECUTE:
5
+ # $ cd ~/dev/watcher
6
+ # $ ruby -I lib:test test/ts_package.rb
7
+
8
+ require "test/unit"
9
+
10
+ require "tc_event"
11
+ require "test_watcher"
data/website/index.html CHANGED
@@ -33,104 +33,105 @@
33
33
  <h1>watcher</h1>
34
34
  <div id="version" class="clickable" onclick='document.location = "http://rubyforge.org/projects/watcher"; return false'>
35
35
  <p>Get Version</p>
36
- <a href="http://rubyforge.org/projects/watcher" class="numbers">1.1.0</a>
36
+ <a href="http://rubyforge.org/projects/watcher" class="numbers">1.2.0</a>
37
37
  </div>
38
- <h1>&#x2192; &#8216;watcher&#8217;</h1>
39
-
40
-
41
- <h2>What</h2>
42
-
43
-
44
- <h2>Installing</h2>
45
-
46
-
47
- <p><pre class='syntax'><span class="ident">sudo</span> <span class="ident">gem</span> <span class="ident">install</span> <span class="ident">watcher</span></pre></p>
48
-
49
-
50
- <h2>The basics</h2>
51
-
52
-
53
- <h2>Demonstration of usage</h2>
54
-
55
-
56
- <h2>Forum</h2>
57
-
58
-
59
- <p><a href="http://groups.google.com/group/watcher">http://groups.google.com/group/watcher</a></p>
60
-
61
-
62
- <p><span class="caps">TODO</span> &#8211; create Google Group &#8211; watcher</p>
63
-
64
-
65
- <h2>How to submit patches</h2>
66
-
67
-
68
- <p>Read the <a href="http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/">8 steps for fixing other people&#8217;s code</a> and for section <a href="http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/#8b-google-groups">8b: Submit patch to Google Groups</a>, use the Google Group above.</p>
69
-
70
-
71
- <p><span class="caps">TODO</span> &#8211; pick <span class="caps">SVN</span> or Git instructions</p>
72
-
73
-
74
- <p>The trunk repository is <code>svn://rubyforge.org/var/svn/watcher/trunk</code> for anonymous access.</p>
75
-
76
-
77
- <p><span class="caps">OOOORRRR</span></p>
78
-
79
-
80
- <p>You can fetch the source from either:</p>
81
-
82
-
83
- <ul>
84
- <li>rubyforge: <span class="caps">MISSING IN ACTION</span></li>
85
- </ul>
86
-
87
-
88
- <p><span class="caps">TODO</span> &#8211; You can not created a RubyForge project, OR have not run <code>rubyforge config</code>
38
+ <h1>&amp;#x2192; &#8216;watcher&#8217;</h1>
39
+ <h2>What</h2>
40
+ <ul>
41
+ <li>Exception handling without the boiler-plate code.</li>
42
+ <li>Multiple tiers of verbosity.</li>
43
+ <li>Flexible logging capabilities, including to files, <span class="caps">STDERR</span>, email.</li>
44
+ <li>Nested, and hierarchical log output for descriptive stack-frame level<br />
45
+ understanding where an exception was thrown.</li>
46
+ <li>Ability to change the time format of your logs by supplying an arbitrary<br />
47
+ Proc to return the time in the format of your choice.</li>
48
+ <li>Ability to customize the layout of the logs, by turning off hierarchical<br />
49
+ view, or changing Strings used to indicate events.</li>
50
+ <li>Email log files automatically, based on number of errors or warnings.</li>
51
+ <li>Ability to invoke arbitrary sequence of events if exception is thrown,<br />
52
+ including invocation of Proc objects.</li>
53
+ </ul>
54
+ <h2>Installing</h2>
55
+ <p><pre class='syntax'><span class="ident">sudo</span> <span class="ident">gem</span> <span class="ident">install</span> <span class="ident">watcher</span></pre></p>
56
+ <h2>The basics</h2>
57
+ <p>A simple example demonstrating multiple embedded levels, and how the<br />
58
+ inside block simply logs the error so that the second puts statement still executes.<br />
59
+ <br />
60
+ <pre class='syntax'>
61
+ <span class="comment"># create Watcher instance with defaults</span>
62
+ <span class="global">$watcher</span> <span class="punct">=</span> <span class="constant">Watcher</span><span class="punct">.</span><span class="ident">create</span>
63
+
64
+ <span class="global">$watcher</span><span class="punct">.</span><span class="ident">verbose</span><span class="punct">(&quot;</span><span class="string">doing something dangerous</span><span class="punct">&quot;)</span> <span class="keyword">do</span>
65
+ <span class="ident">puts</span> <span class="punct">&quot;</span><span class="string">be careful...</span><span class="punct">&quot;</span>
66
+ <span class="global">$watcher</span><span class="punct">.</span><span class="ident">debug</span><span class="punct">(&quot;</span><span class="string">going to do something very dangerous</span><span class="punct">&quot;,</span> <span class="symbol">:failure</span> <span class="punct">=&gt;</span> <span class="symbol">:warn</span><span class="punct">)</span> <span class="keyword">do</span>
67
+ <span class="keyword">raise</span> <span class="punct">&quot;</span><span class="string">ouch!</span><span class="punct">&quot;</span>
68
+ <span class="keyword">end</span>
69
+ <span class="ident">puts</span> <span class="punct">&quot;</span><span class="string">that wasn't so bad... just a log entry!</span><span class="punct">&quot;</span>
70
+ <span class="keyword">end</span>
71
+ </pre><br />
72
+ <br />
73
+ h2. Demonstration of usage<br />
74
+ <br />
75
+ <p>A more complicated example of sending a reference to a Proc to attempt<br />
76
+ to recover from an condition.</p>
77
+ <p><pre class='syntax'>
78
+ <span class="comment"># create Watcher instance with slightly modified defaults</span>
79
+ <span class="global">$watcher</span> <span class="punct">=</span> <span class="constant">Watcher</span><span class="punct">.</span><span class="ident">create</span><span class="punct">(</span><span class="symbol">:output</span> <span class="punct">=&gt;</span> <span class="ident">log_file</span><span class="punct">)</span>
80
+
81
+ <span class="global">$watcher</span><span class="punct">.</span><span class="ident">debug</span><span class="punct">(&quot;</span><span class="string">starting <span class="expr">#{File.basename($0)}</span></span><span class="punct">&quot;)</span> <span class="keyword">do</span>
82
+ <span class="comment"># Look for CONFIG_PATH. If not found, log warning then re-write it</span>
83
+ <span class="ident">params</span> <span class="punct">=</span> <span class="punct">{</span><span class="symbol">:tries</span> <span class="punct">=&gt;</span> <span class="number">2</span><span class="punct">,</span> <span class="symbol">:failure</span> <span class="punct">=&gt;</span> <span class="symbol">:error</span><span class="punct">,</span>
84
+ <span class="symbol">:proc</span> <span class="punct">=&gt;</span> <span class="ident">lambda</span> <span class="punct">{</span> <span class="punct">|</span><span class="ident">e</span><span class="punct">|</span> <span class="ident">write_config</span><span class="punct">(</span><span class="ident">config_path</span><span class="punct">)</span> <span class="punct">}}</span>
85
+ <span class="ident">msg</span> <span class="punct">=</span> <span class="punct">&quot;</span><span class="string">ensuring existance of config file [<span class="expr">#{config_path}</span>]</span><span class="punct">&quot;</span>
86
+ <span class="global">$watcher</span><span class="punct">.</span><span class="ident">verbose</span><span class="punct">(</span><span class="ident">msg</span><span class="punct">,</span> <span class="ident">params</span><span class="punct">)</span> <span class="keyword">do</span>
87
+ <span class="keyword">raise</span> <span class="punct">&quot;</span><span class="string">file not found</span><span class="punct">&quot;</span> <span class="keyword">unless</span> <span class="constant">File</span><span class="punct">.</span><span class="ident">file?</span><span class="punct">(</span><span class="constant">File</span><span class="punct">.</span><span class="ident">expand_path</span><span class="punct">(</span><span class="ident">config_path</span><span class="punct">))</span>
88
+ <span class="keyword">end</span>
89
+
90
+ <span class="comment"># invoke utility, which uses $watcher as well</span>
91
+ <span class="ident">fsc</span> <span class="punct">=</span> <span class="constant">FileSystemChecker</span><span class="punct">.</span><span class="ident">new</span><span class="punct">(</span><span class="symbol">:config_path</span> <span class="punct">=&gt;</span> <span class="ident">config_path</span><span class="punct">)</span>
92
+ <span class="ident">fsc</span><span class="punct">.</span><span class="ident">check_file_systems</span><span class="punct">(</span><span class="symbol">:all</span> <span class="punct">=&gt;</span> <span class="ident">all_flag</span><span class="punct">,</span> <span class="symbol">:remount</span> <span class="punct">=&gt;</span> <span class="ident">remount_flag</span><span class="punct">)</span>
93
+ <span class="keyword">end</span>
94
+
95
+ <span class="keyword">if</span> <span class="ident">email_flag</span> <span class="keyword">and</span> <span class="punct">(</span><span class="global">$watcher</span><span class="punct">.</span><span class="ident">errors</span> <span class="punct">&gt;</span> <span class="number">0</span> <span class="keyword">or</span> <span class="global">$watcher</span><span class="punct">.</span><span class="ident">warnings</span> <span class="punct">&gt;</span> <span class="number">0</span><span class="punct">)</span>
96
+ <span class="global">$watcher</span><span class="punct">.</span><span class="ident">send_email</span><span class="punct">(</span><span class="ident">email</span><span class="punct">,</span> <span class="punct">'</span><span class="string">FAIL: Required filesystems are not mounted</span><span class="punct">')</span>
97
+ <span class="keyword">end</span>
98
+ </pre></p>
99
+ <h2>Forum</h2>
100
+ <p><a href="http://groups.google.com/group/watcher">http://groups.google.com/group/watcher</a></p>
101
+ <p><span class="caps">TODO</span> &#8211; create Google Group &#8211; watcher</p>
102
+ <h2>How to submit patches</h2>
103
+ <p>Read the <a href="http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/">8 steps for fixing other people&#8217;s code</a> and for section <a href="http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/#8b-google-groups">8b: Submit patch to Google Groups</a>, use the Google Group above.</p>
104
+ <p><span class="caps">TODO</span> &#8211; pick <span class="caps">SVN</span> or Git instructions</p>
105
+ <p>The trunk repository is <code>svn://rubyforge.org/var/svn/watcher/trunk</code> for anonymous access.</p>
106
+ <p><span class="caps">OOOORRRR</span></p>
107
+ <p>You can fetch the source from either:</p>
108
+ <ul>
109
+ <li>rubyforge: <span class="caps">MISSING</span> IN <span class="caps">ACTION</span></li>
110
+ </ul>
111
+ <p><span class="caps">TODO</span> &#8211; You can not created a RubyForge project, OR have not run <code>rubyforge config</code><br />
89
112
  yet to refresh your local rubyforge data with this projects&#8217; id information.</p>
90
-
91
-
92
- <p>When you do this, this message will magically disappear!</p>
93
-
94
-
95
- <p>Or you can hack website/index.txt and make it all go away!!</p>
96
-
97
-
98
- <ul>
113
+ <p>When you do this, this message will magically disappear!</p>
114
+ <p>Or you can hack website/index.txt and make it all go away!!</p>
115
+ <ul>
99
116
  <li>github: <a href="http://github.com/GITHUB_USERNAME/watcher/tree/master">http://github.com/GITHUB_USERNAME/watcher/tree/master</a></li>
100
- </ul>
101
-
102
-
117
+ </ul>
103
118
  <pre>git clone git://github.com/GITHUB_USERNAME/watcher.git</pre>
104
-
105
- <p><span class="caps">TODO</span> &#8211; add &#8220;github_username: username&#8221; to ~/.rubyforge/user-config.yml and newgem will reuse it for future projects.</p>
106
-
107
-
108
- <ul>
119
+ <p><span class="caps">TODO</span> &#8211; add &#8220;github_username: username&#8221; to ~/.rubyforge/user-config.yml and newgem will reuse it for future projects.</p>
120
+ <ul>
109
121
  <li>gitorious: <a href="git://gitorious.org/watcher/mainline.git">git://gitorious.org/watcher/mainline.git</a></li>
110
- </ul>
111
-
112
-
122
+ </ul>
113
123
  <pre>git clone git://gitorious.org/watcher/mainline.git</pre>
114
-
115
- <h3>Build and test instructions</h3>
116
-
124
+ <h3>Build and test instructions</h3>
125
+ <p><i>Sorry, no unit tests yet&#8230;</i></p>
117
126
 
118
127
  <pre>cd watcher
119
- rake test
120
128
  rake install_gem</pre>
121
-
122
- <h2>License</h2>
123
-
124
-
125
- <p>This code is free to use under the terms of the <span class="caps">MIT</span> license.</p>
126
-
127
-
128
- <h2>Contact</h2>
129
-
130
-
131
- <p>Comments are welcome. Send an email to <a href="mailto:karrick@karrick.net"><span class="caps">FIXME</span> full name</a> via the <a href="http://groups.google.com/group/watcher">forum</a></p>
129
+ <h2>License</h2>
130
+ <p>This code is free to use under the terms of the Simplified <span class="caps">BSD</span> license.</p>
131
+ <h2>Contact</h2>
132
+ <p>Comments are welcome. Send an email to <a href="mailto:karrick@karrick.org">Karrick McDermott</a> via the <a href="http://groups.google.com/group/watcher">forum</a></p>
132
133
  <p class="coda">
133
- <a href="karrick@karrick.net">FIXME full name</a>, 20th July 2008<br>
134
+ <a href="karrick@karrick.org">Karrick McDermott</a>, 30th July 2008<br>
134
135
  Theme extended from <a href="http://rb2js.rubyforge.org/">Paul Battley</a>
135
136
  </p>
136
137
  </div>
data/website/index.txt CHANGED
@@ -5,6 +5,18 @@ h1. &#x2192; 'watcher'
5
5
 
6
6
  h2. What
7
7
 
8
+ * Exception handling without the boiler-plate code.
9
+ * Multiple tiers of verbosity.
10
+ * Flexible logging capabilities, including to files, STDERR, email.
11
+ * Nested, and hierarchical log output for descriptive stack-frame level
12
+ understanding where an exception was thrown.
13
+ * Ability to change the time format of your logs by supplying an arbitrary
14
+ Proc to return the time in the format of your choice.
15
+ * Ability to customize the layout of the logs, by turning off hierarchical
16
+ view, or changing Strings used to indicate events.
17
+ * Email log files automatically, based on number of errors or warnings.
18
+ * Ability to invoke arbitrary sequence of events if exception is thrown,
19
+ including invocation of Proc objects.
8
20
 
9
21
  h2. Installing
10
22
 
@@ -12,10 +24,49 @@ h2. Installing
12
24
 
13
25
  h2. The basics
14
26
 
27
+ <p>A simple example demonstrating multiple embedded levels, and how the
28
+ inside block simply logs the error so that the second puts statement still executes.
29
+
30
+ <pre syntax="ruby">
31
+ # create Watcher instance with defaults
32
+ $watcher = Watcher.create
33
+
34
+ $watcher.verbose("doing something dangerous") do
35
+ puts "be careful..."
36
+ $watcher.debug("going to do something very dangerous", :failure => :warn) do
37
+ raise "ouch!"
38
+ end
39
+ puts "that wasn't so bad... just a log entry!"
40
+ end
41
+ </pre>
15
42
 
16
43
  h2. Demonstration of usage
17
44
 
45
+ <p>A more complicated example of sending a reference to a Proc to attempt
46
+ to recover from an condition.</p>
47
+
48
+ <pre syntax="ruby">
49
+ # create Watcher instance with slightly modified defaults
50
+ $watcher = Watcher.create(:output => log_file)
18
51
 
52
+ $watcher.debug("starting #{File.basename($0)}") do
53
+ # Look for CONFIG_PATH. If not found, log warning then re-write it
54
+ params = {:tries => 2, :failure => :error,
55
+ :proc => lambda { |e| write_config(config_path) }}
56
+ msg = "ensuring existance of config file [#{config_path}]"
57
+ $watcher.verbose(msg, params) do
58
+ raise "file not found" unless File.file?(File.expand_path(config_path))
59
+ end
60
+
61
+ # invoke utility, which uses $watcher as well
62
+ fsc = FileSystemChecker.new(:config_path => config_path)
63
+ fsc.check_file_systems(:all => all_flag, :remount => remount_flag)
64
+ end
65
+
66
+ if email_flag and ($watcher.errors > 0 or $watcher.warnings > 0)
67
+ $watcher.send_email(email, 'FAIL: Required filesystems are not mounted')
68
+ end
69
+ </pre>
19
70
 
20
71
  h2. Forum
21
72
 
@@ -68,16 +119,17 @@ TODO - add "github_username: username" to ~/.rubyforge/user-config.yml and newge
68
119
 
69
120
  h3. Build and test instructions
70
121
 
122
+ <p><i>Sorry, no unit tests yet...</i></p>
123
+
71
124
  <pre>cd watcher
72
- rake test
73
125
  rake install_gem</pre>
74
126
 
75
127
 
76
128
  h2. License
77
129
 
78
- This code is free to use under the terms of the MIT license.
130
+ This code is free to use under the terms of the Simplified BSD license.
79
131
 
80
132
  h2. Contact
81
133
 
82
- Comments are welcome. Send an email to "FIXME full name":mailto:karrick@karrick.net via the "forum":http://groups.google.com/group/watcher
134
+ Comments are welcome. Send an email to "Karrick McDermott":mailto:karrick@karrick.org via the "forum":http://groups.google.com/group/watcher
83
135