kennethkalmer-autotest-growl-remote 0.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.
- data/History.txt +4 -0
- data/Manifest.txt +17 -0
- data/PostInstall.txt +7 -0
- data/README.rdoc +59 -0
- data/Rakefile +26 -0
- data/TODO.txt +1 -0
- data/lib/autotest-growl-remote.rb +10 -0
- data/lib/autotest/growl/remote.rb +156 -0
- data/lib/autotest/growl/result.rb +64 -0
- data/lib/autotest/growl/ruby-growl.rb +286 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/spec/autotest-growl-remote_spec.rb +11 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +10 -0
- data/tasks/rspec.rake +21 -0
- metadata +94 -0
data/History.txt
ADDED
data/Manifest.txt
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
History.txt
|
2
|
+
Manifest.txt
|
3
|
+
PostInstall.txt
|
4
|
+
README.rdoc
|
5
|
+
Rakefile
|
6
|
+
TODO.txt
|
7
|
+
lib/autotest-growl-remote.rb
|
8
|
+
lib/autotest/growl/remote.rb
|
9
|
+
lib/autotest/growl/result.rb
|
10
|
+
lib/autotest/growl/ruby-growl.rb
|
11
|
+
script/console
|
12
|
+
script/destroy
|
13
|
+
script/generate
|
14
|
+
spec/autotest-growl-remote_spec.rb
|
15
|
+
spec/spec.opts
|
16
|
+
spec/spec_helper.rb
|
17
|
+
tasks/rspec.rake
|
data/PostInstall.txt
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
= autotest-growl-remote
|
2
|
+
|
3
|
+
* http://github.com/kennethkalmer/autotest-growl-remote
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
A minimal copy of autotest-growl that only sends network notifications to
|
8
|
+
Growl. No fancy icons, but great for sending messages from a virtual machine
|
9
|
+
or a local CI box.
|
10
|
+
|
11
|
+
== SYNOPSIS:
|
12
|
+
|
13
|
+
Add to your project's .autotest, or to ~/.autotest
|
14
|
+
|
15
|
+
require 'autotest/growl/remote'
|
16
|
+
|
17
|
+
Autotest::Growl::Remote.remote_host = 'ip.or.host.name'
|
18
|
+
Autotest::Growl::Remote.remote_password = 'foo' # if needed
|
19
|
+
|
20
|
+
== REQUIREMENTS:
|
21
|
+
|
22
|
+
* ZenTest 4.0.0 or later
|
23
|
+
|
24
|
+
== INSTALL:
|
25
|
+
|
26
|
+
* gem install kennethkalmer-autotest-growl-remote
|
27
|
+
|
28
|
+
== ACTUAL WORK:
|
29
|
+
|
30
|
+
The actual work was done by Sven Schwyn (svoop) when he made the autotest-growl
|
31
|
+
project (which I just copied and pasted), and Eric Hodel (drbrain) for his
|
32
|
+
ruby-growl library that I bundled in here.
|
33
|
+
|
34
|
+
I only changed one method, and I did this for my own convenience.
|
35
|
+
|
36
|
+
== LICENSE:
|
37
|
+
|
38
|
+
(The MIT License)
|
39
|
+
|
40
|
+
Copyright (c) 2009 Kenneth Kalmer
|
41
|
+
|
42
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
43
|
+
a copy of this software and associated documentation files (the
|
44
|
+
'Software'), to deal in the Software without restriction, including
|
45
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
46
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
47
|
+
permit persons to whom the Software is furnished to do so, subject to
|
48
|
+
the following conditions:
|
49
|
+
|
50
|
+
The above copyright notice and this permission notice shall be
|
51
|
+
included in all copies or substantial portions of the Software.
|
52
|
+
|
53
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
54
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
55
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
56
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
57
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
58
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
59
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
gem 'hoe', '>= 2.1.0'
|
3
|
+
require 'hoe'
|
4
|
+
require 'fileutils'
|
5
|
+
require './lib/autotest-growl-remote'
|
6
|
+
|
7
|
+
Hoe.plugin :newgem
|
8
|
+
# Hoe.plugin :website
|
9
|
+
# Hoe.plugin :cucumberfeatures
|
10
|
+
|
11
|
+
# Generate all the Rake tasks
|
12
|
+
# Run 'rake -T' to see list of generated tasks (from gem root directory)
|
13
|
+
$hoe = Hoe.spec 'autotest-growl-remote' do
|
14
|
+
self.developer 'Kenneth Kalmer', 'kenneth.kalmer@mgila.com'
|
15
|
+
self.post_install_message = 'PostInstall.txt' # TODO remove if post-install message not required
|
16
|
+
self.rubyforge_name = self.name # TODO this is default value
|
17
|
+
self.extra_deps = [['ZenTest','>= 4.0.0']]
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'newgem/tasks'
|
22
|
+
Dir['tasks/**/*.rake'].each { |t| load t }
|
23
|
+
|
24
|
+
# TODO - want other tests/tasks run by default? Add them to the list
|
25
|
+
# remove_task :default
|
26
|
+
# task :default => [:spec, :features]
|
data/TODO.txt
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
* Get this merged into autotest-growl
|
@@ -0,0 +1,156 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'autotest'
|
3
|
+
require File.join( File.dirname(__FILE__), 'ruby-growl' )
|
4
|
+
require File.join(File.dirname(__FILE__), 'result')
|
5
|
+
|
6
|
+
##
|
7
|
+
# Autotest::Growl
|
8
|
+
#
|
9
|
+
# == FEATUERS:
|
10
|
+
# * Display autotest results as local or remote Growl notifications.
|
11
|
+
# * Clean the terminal on every test cycle while maintaining scrollback.
|
12
|
+
#
|
13
|
+
# == SYNOPSIS:
|
14
|
+
# ~/.autotest
|
15
|
+
# require 'autotest/growl'
|
16
|
+
class Autotest
|
17
|
+
module Growl
|
18
|
+
module Remote
|
19
|
+
|
20
|
+
@label = ''
|
21
|
+
@modified_files = []
|
22
|
+
@ran_tests = false
|
23
|
+
@ran_features = false
|
24
|
+
|
25
|
+
@@remote_host = nil
|
26
|
+
@@remote_password = nil
|
27
|
+
|
28
|
+
@@one_notification_per_run = false
|
29
|
+
@@clear_terminal = false
|
30
|
+
@@hide_label = false
|
31
|
+
@@show_modified_files = false
|
32
|
+
|
33
|
+
# Hostname or IP address to send the notifications to
|
34
|
+
def self.remote_host=(hostname_or_ip)
|
35
|
+
@@remote_host = hostname_or_ip
|
36
|
+
end
|
37
|
+
|
38
|
+
# Growl password
|
39
|
+
def self.remote_password=( password )
|
40
|
+
@@remote_password = password
|
41
|
+
end
|
42
|
+
|
43
|
+
# Whether to limit the number of notifications per run to one or not (default).
|
44
|
+
def self.one_notification_per_run=(boolean)
|
45
|
+
@@one_notification_per_run = boolean
|
46
|
+
end
|
47
|
+
|
48
|
+
# Whether to clear the terminal before running tests (default) or not.
|
49
|
+
def self.clear_terminal=(boolean)
|
50
|
+
@@clear_terminal = boolean
|
51
|
+
end
|
52
|
+
|
53
|
+
# Whether to display the label (default) or not.
|
54
|
+
def self.hide_label=(boolean)
|
55
|
+
@@hide_label = boolean
|
56
|
+
end
|
57
|
+
|
58
|
+
# Whether to display the modified files or not (default).
|
59
|
+
def self.show_modified_files=(boolean)
|
60
|
+
@@show_modified_files = boolean
|
61
|
+
end
|
62
|
+
|
63
|
+
# Display a message through Growl.
|
64
|
+
def self.growl(title, message, icon, priority=0, stick="")
|
65
|
+
raise "Remote host not configured" if @@remote_host.nil?
|
66
|
+
|
67
|
+
g = ::Growl.new( @@remote_host, "autotest", [ "autotest Notification"], nil, @@remote_password )
|
68
|
+
g.notify "autotest Notification", title, message, priority, stick
|
69
|
+
end
|
70
|
+
|
71
|
+
# Display the modified files.
|
72
|
+
Autotest.add_hook :updated do |autotest, modified|
|
73
|
+
@ran_tests = @ran_features = false
|
74
|
+
if @@show_modified_files
|
75
|
+
if modified != @last_modified
|
76
|
+
growl @label + 'Modifications detected.', modified.collect {|m| m[0]}.join(', '), 'info', 0
|
77
|
+
@last_modified = modified
|
78
|
+
end
|
79
|
+
end
|
80
|
+
false
|
81
|
+
end
|
82
|
+
|
83
|
+
# Set the label and clear the terminal.
|
84
|
+
Autotest.add_hook :run_command do
|
85
|
+
@label = File.basename(Dir.pwd).upcase + ': ' if !@@hide_label
|
86
|
+
print "\n"*2 + '-'*80 + "\n"*2
|
87
|
+
print "\e[2J\e[f" if @@clear_terminal
|
88
|
+
false
|
89
|
+
end
|
90
|
+
|
91
|
+
# Parse the RSpec and Test::Unit results and send them to Growl.
|
92
|
+
Autotest.add_hook :ran_command do |autotest|
|
93
|
+
unless @@one_notification_per_run && @ran_tests
|
94
|
+
result = Result.new(autotest)
|
95
|
+
if result.exists?
|
96
|
+
case result.framework
|
97
|
+
when 'test-unit'
|
98
|
+
if result.has?('test-error')
|
99
|
+
growl @label + 'Cannot run some unit tests.', "#{result.get('test-error')} in #{result.get('test')}", 'error', 2
|
100
|
+
elsif result.has?('test-failed')
|
101
|
+
growl @label + 'Some unit tests failed.', "#{result['test-failed']} of #{result.get('test-assertion')} in #{result.get('test')} failed", 'failed', 2
|
102
|
+
else
|
103
|
+
growl @label + 'All unit tests passed.', "#{result.get('test-assertion')} in #{result.get('test')}", 'passed', -2
|
104
|
+
end
|
105
|
+
when 'rspec'
|
106
|
+
if result.has?('example-failed')
|
107
|
+
growl @label + 'Some RSpec examples failed.', "#{result['example-failed']} of #{result.get('example')} failed", 'failed', 2
|
108
|
+
elsif result.has?('example-pending')
|
109
|
+
growl @label + 'Some RSpec examples are pending.', "#{result['example-pending']} of #{result.get('example')} pending", 'pending', -1
|
110
|
+
else
|
111
|
+
growl @label + 'All RSpec examples passed.', "#{result.get('example')}", 'passed', -2
|
112
|
+
end
|
113
|
+
end
|
114
|
+
else
|
115
|
+
growl @label + 'Could not run tests.', '', 'error', 2
|
116
|
+
end
|
117
|
+
@ran_test = true
|
118
|
+
end
|
119
|
+
false
|
120
|
+
end
|
121
|
+
|
122
|
+
# Parse the Cucumber results and sent them to Growl.
|
123
|
+
Autotest.add_hook :ran_features do |autotest|
|
124
|
+
unless @@one_notification_per_run && @ran_features
|
125
|
+
result = Result.new(autotest)
|
126
|
+
if result.exists?
|
127
|
+
case result.framework
|
128
|
+
when 'cucumber'
|
129
|
+
explanation = []
|
130
|
+
if result.has?('scenario-undefined') || result.has?('step-undefined')
|
131
|
+
explanation << "#{result['scenario-undefined']} of #{result.get('scenario')} not defined" if result['scenario-undefined']
|
132
|
+
explanation << "#{result['step-undefined']} of #{result.get('step')} not defined" if result['step-undefined']
|
133
|
+
growl @label + 'Some Cucumber scenarios are not defined.', "#{explanation.join("\n")}", 'pending', -1
|
134
|
+
elsif result.has?('scenario-failed') || result.has?('step-failed')
|
135
|
+
explanation << "#{result['scenario-failed']} of #{result.get('scenario')} failed" if result['scenario-failed']
|
136
|
+
explanation << "#{result['step-failed']} of #{result.get('step')} failed" if result['step-failed']
|
137
|
+
growl @label + 'Some Cucumber scenarios failed.', "#{explanation.join("\n")}", 'failed', 2
|
138
|
+
elsif result.has?('scenario-pending') || result.has?('step-pending')
|
139
|
+
explanation << "#{result['scenario-pending']} of #{result.get('scenario')} pending" if result['scenario-pending']
|
140
|
+
explanation << "#{result['step-pending']} of #{result.get('step')} pending" if result['step-pending']
|
141
|
+
growl @label + 'Some Cucumber scenarios are pending.', "#{explanation.join("\n")}", 'pending', -1
|
142
|
+
else
|
143
|
+
growl @label + 'All Cucumber features passed.', '', 'passed', -2
|
144
|
+
end
|
145
|
+
end
|
146
|
+
else
|
147
|
+
growl @label + 'Could not run features.', '', 'error', 2
|
148
|
+
end
|
149
|
+
@ran_features = true
|
150
|
+
end
|
151
|
+
false
|
152
|
+
end
|
153
|
+
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
class Result
|
2
|
+
|
3
|
+
##
|
4
|
+
# Analyze test result lines and return the numbers in a hash.
|
5
|
+
def initialize(autotest)
|
6
|
+
@numbers = {}
|
7
|
+
lines = autotest.results.map {|s| s.gsub(/(\e.*?m|\n)/, '') } # remove escape sequences
|
8
|
+
lines.reject! {|line| !line.match(/\d+\s+(example|test|scenario|step)s?/) } # isolate result numbers
|
9
|
+
lines.each do |line|
|
10
|
+
prefix = nil
|
11
|
+
line.scan(/([1-9]\d*)\s(\w+)/) do |number, kind|
|
12
|
+
kind.sub!(/s$/, '') # singularize
|
13
|
+
kind.sub!(/failure/, 'failed') # homogenize
|
14
|
+
if prefix
|
15
|
+
@numbers["#{prefix}-#{kind}"] = number.to_i
|
16
|
+
else
|
17
|
+
@numbers[kind] = number.to_i
|
18
|
+
prefix = kind
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
##
|
25
|
+
# Determine the testing framework used.
|
26
|
+
def framework
|
27
|
+
case
|
28
|
+
when @numbers['test'] then 'test-unit'
|
29
|
+
when @numbers['example'] then 'rspec'
|
30
|
+
when @numbers['scenario'] then 'cucumber'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
##
|
35
|
+
# Determine whether a result exists at all.
|
36
|
+
def exists?
|
37
|
+
!@numbers.empty?
|
38
|
+
end
|
39
|
+
|
40
|
+
##
|
41
|
+
# Check whether a specific result is present.
|
42
|
+
def has?(kind)
|
43
|
+
@numbers.has_key?(kind)
|
44
|
+
end
|
45
|
+
|
46
|
+
##
|
47
|
+
# Get a plain result number.
|
48
|
+
def [](kind)
|
49
|
+
@numbers[kind]
|
50
|
+
end
|
51
|
+
|
52
|
+
##
|
53
|
+
# Get a labelled result number. The prefix is removed and the label pluralized if necessary.
|
54
|
+
def get(kind)
|
55
|
+
"#{@numbers[kind]} #{kind.sub(/^.*-/, '')}#{'s' if @numbers[kind] != 1 && !kind.match(/(ed|ing)$/)}" if @numbers[kind]
|
56
|
+
end
|
57
|
+
|
58
|
+
##
|
59
|
+
# Get the fatal error if any.
|
60
|
+
def fatal_error
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
@@ -0,0 +1,286 @@
|
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
|
+
|
3
|
+
$TESTING = false unless defined? $TESTING
|
4
|
+
|
5
|
+
require 'md5'
|
6
|
+
require 'socket'
|
7
|
+
|
8
|
+
##
|
9
|
+
# ruby-growl allows you to perform Growl notification via UDP from machines
|
10
|
+
# without growl installed (for example, non-OSX machines).
|
11
|
+
#
|
12
|
+
# What's Growl? Growl is a really cool "global notification system for Mac OS
|
13
|
+
# X". See http://growl.info/
|
14
|
+
#
|
15
|
+
# You'll need a Mac to recieve Growl notifications, but you can send Growl
|
16
|
+
# notifications from any UDP-capable machine that runs Ruby.
|
17
|
+
#
|
18
|
+
# See also the Ruby Growl bindings in Growl's subversion repository:
|
19
|
+
# http://growl.info/documentation/growl-source-install.php
|
20
|
+
#
|
21
|
+
# ruby-growl also contains a command-line notification tool named 'growl'. It
|
22
|
+
# is almost completely option-compatible with growlnotify. (All except for -p
|
23
|
+
# is supported, use --priority instead.)
|
24
|
+
#
|
25
|
+
# = Synopsis
|
26
|
+
#
|
27
|
+
# g = Growl.new "127.0.0.1", "ruby-growl",
|
28
|
+
# ["ruby-growl Notification"]
|
29
|
+
# g.notify "ruby-growl Notification", "It Came From Ruby-Growl",
|
30
|
+
# "Greetings!"
|
31
|
+
|
32
|
+
class Growl
|
33
|
+
|
34
|
+
##
|
35
|
+
# The Ruby that ships with Tiger has a broken #pack, so 'v' means network
|
36
|
+
# byte order instead of 'n'.
|
37
|
+
|
38
|
+
BROKEN_PACK = [1].pack("n") != "\000\001" # :nodoc:
|
39
|
+
|
40
|
+
##
|
41
|
+
# ruby-growl Version
|
42
|
+
|
43
|
+
VERSION = "1.0.1"
|
44
|
+
|
45
|
+
##
|
46
|
+
# Growl Network Registration Packet +pack+ Format
|
47
|
+
#--
|
48
|
+
# Format:
|
49
|
+
#
|
50
|
+
# struct GrowlNetworkRegistration {
|
51
|
+
# struct GrowlNetworkPacket {
|
52
|
+
# unsigned char version;
|
53
|
+
# unsigned char type;
|
54
|
+
# } __attribute__((packed));
|
55
|
+
# unsigned short appNameLen;
|
56
|
+
# unsigned char numAllNotifications;
|
57
|
+
# unsigned char numDefaultNotifications;
|
58
|
+
# /*
|
59
|
+
# * Variable sized. Format:
|
60
|
+
# * <application name><all notifications><default notifications><checksum>
|
61
|
+
# * where <all notifications> is of the form (<length><name>){num} and
|
62
|
+
# * <default notifications> is an array of indices into the all notifications
|
63
|
+
# * array, each index being 8 bits.
|
64
|
+
# */
|
65
|
+
# unsigned char data[];
|
66
|
+
# } __attribute__((packed));
|
67
|
+
|
68
|
+
GNR_FORMAT = "CCnCCa*"
|
69
|
+
|
70
|
+
GNR_FORMAT.gsub!(/n/, 'v') if BROKEN_PACK
|
71
|
+
|
72
|
+
##
|
73
|
+
# Growl Network Notification Packet +pack+ Format
|
74
|
+
#--
|
75
|
+
# Format:
|
76
|
+
#
|
77
|
+
# struct GrowlNetworkNotification {
|
78
|
+
# struct GrowlNetworkPacket {
|
79
|
+
# unsigned char version;
|
80
|
+
# unsigned char type;
|
81
|
+
# } __attribute__((packed));
|
82
|
+
# struct GrowlNetworkNotificationFlags {
|
83
|
+
# unsigned reserved: 12;
|
84
|
+
# signed priority: 3;
|
85
|
+
# unsigned sticky: 1;
|
86
|
+
# } __attribute__((packed)) flags; //size = 16 (12 + 3 + 1)
|
87
|
+
# unsigned short nameLen;
|
88
|
+
# unsigned short titleLen;
|
89
|
+
# unsigned short descriptionLen;
|
90
|
+
# unsigned short appNameLen;
|
91
|
+
# /*
|
92
|
+
# * Variable sized. Format:
|
93
|
+
# * <notification name><title><description><application name><checksum>
|
94
|
+
# */
|
95
|
+
# unsigned char data[];
|
96
|
+
# } __attribute__((packed));
|
97
|
+
|
98
|
+
GNN_FORMAT = "CCnnnnna*"
|
99
|
+
|
100
|
+
GNN_FORMAT.gsub!(/n/, 'v') if BROKEN_PACK
|
101
|
+
|
102
|
+
##
|
103
|
+
# Growl UDP Port
|
104
|
+
|
105
|
+
GROWL_UDP_PORT = 9887
|
106
|
+
|
107
|
+
##
|
108
|
+
# Growl Protocol Version
|
109
|
+
|
110
|
+
GROWL_PROTOCOL_VERSION = 1
|
111
|
+
|
112
|
+
##
|
113
|
+
# Growl Registration Packet Id
|
114
|
+
|
115
|
+
GROWL_TYPE_REGISTRATION = 0
|
116
|
+
|
117
|
+
##
|
118
|
+
# Growl Notification Packet Id
|
119
|
+
|
120
|
+
GROWL_TYPE_NOTIFICATION = 1
|
121
|
+
|
122
|
+
##
|
123
|
+
# Creates a new Growl notifier and automatically registers any notifications
|
124
|
+
# with the remote machine.
|
125
|
+
#
|
126
|
+
# +host+ is the host to contact.
|
127
|
+
#
|
128
|
+
# +app_name+ is the name of the application sending the notifications.
|
129
|
+
#
|
130
|
+
# +all_notifies+ is a list of notification types your application sends.
|
131
|
+
#
|
132
|
+
# +default_notifies+ is a list of notification types that are turned on by
|
133
|
+
# default.
|
134
|
+
#
|
135
|
+
# I'm not sure about what +default_notifies+ is supposed to be set to, since
|
136
|
+
# there is a comment that says "not a subset of all_notifies" in the code.
|
137
|
+
#
|
138
|
+
# +password+ is the password needed to send notifications to +host+.
|
139
|
+
|
140
|
+
def initialize(host, app_name, all_notifies, default_notifies = nil,
|
141
|
+
password = nil)
|
142
|
+
@socket = UDPSocket.open
|
143
|
+
# FIXME This goes somewhere else
|
144
|
+
@socket.connect host, GROWL_UDP_PORT
|
145
|
+
@app_name = app_name
|
146
|
+
@all_notifies = all_notifies
|
147
|
+
@default_notifies = default_notifies.nil? ? all_notifies : default_notifies
|
148
|
+
@password = password
|
149
|
+
|
150
|
+
register
|
151
|
+
end
|
152
|
+
|
153
|
+
##
|
154
|
+
# Sends a notification.
|
155
|
+
#
|
156
|
+
# +notify_type+ is the type of notification to send.
|
157
|
+
#
|
158
|
+
# +title+ is a title for the notification.
|
159
|
+
#
|
160
|
+
# +message+ is the body of the notification.
|
161
|
+
#
|
162
|
+
# +priority+ is the priorty of message to send.
|
163
|
+
#
|
164
|
+
# +sticky+ makes the notification stick until clicked.
|
165
|
+
|
166
|
+
def notify(notify_type, title, message, priority = 0, sticky = false)
|
167
|
+
raise "Unknown Notification" unless @all_notifies.include? notify_type
|
168
|
+
raise "Invalid Priority" unless priority >= -2 and priority <= 2
|
169
|
+
|
170
|
+
send notification_packet(notify_type, title, message, priority, sticky)
|
171
|
+
end
|
172
|
+
|
173
|
+
private unless $TESTING
|
174
|
+
|
175
|
+
##
|
176
|
+
# Registers the notification types with +host+.
|
177
|
+
|
178
|
+
def register
|
179
|
+
send registration_packet
|
180
|
+
end
|
181
|
+
|
182
|
+
##
|
183
|
+
# Sends a Growl packet
|
184
|
+
|
185
|
+
def send(packet)
|
186
|
+
set_sndbuf packet.length
|
187
|
+
@socket.send packet, 0
|
188
|
+
@socket.flush
|
189
|
+
end
|
190
|
+
|
191
|
+
##
|
192
|
+
# Builds a Growl registration packet
|
193
|
+
|
194
|
+
def registration_packet
|
195
|
+
length = 0
|
196
|
+
data = []
|
197
|
+
data_format = ""
|
198
|
+
|
199
|
+
packet = [
|
200
|
+
GROWL_PROTOCOL_VERSION,
|
201
|
+
GROWL_TYPE_REGISTRATION
|
202
|
+
]
|
203
|
+
|
204
|
+
packet << @app_name.length
|
205
|
+
packet << @all_notifies.length
|
206
|
+
packet << @default_notifies.length
|
207
|
+
|
208
|
+
data << @app_name
|
209
|
+
data_format = "a#{@app_name.length}"
|
210
|
+
|
211
|
+
@all_notifies.each do |notify|
|
212
|
+
data << notify.length
|
213
|
+
data << notify
|
214
|
+
data_format << "na#{notify.length}"
|
215
|
+
end
|
216
|
+
|
217
|
+
@default_notifies.each do |notify|
|
218
|
+
data << @all_notifies.index(notify) if @all_notifies.include? notify
|
219
|
+
data_format << "C"
|
220
|
+
end
|
221
|
+
|
222
|
+
data_format.gsub!(/n/, 'v') if BROKEN_PACK
|
223
|
+
|
224
|
+
data = data.pack data_format
|
225
|
+
|
226
|
+
packet << data
|
227
|
+
|
228
|
+
packet = packet.pack GNR_FORMAT
|
229
|
+
|
230
|
+
checksum = MD5.new packet
|
231
|
+
checksum.update @password unless @password.nil?
|
232
|
+
|
233
|
+
packet << checksum.digest
|
234
|
+
|
235
|
+
return packet
|
236
|
+
end
|
237
|
+
|
238
|
+
##
|
239
|
+
# Builds a Growl notification packet
|
240
|
+
|
241
|
+
def notification_packet(name, title, description, priority, sticky)
|
242
|
+
flags = 0
|
243
|
+
data = []
|
244
|
+
|
245
|
+
packet = [
|
246
|
+
GROWL_PROTOCOL_VERSION,
|
247
|
+
GROWL_TYPE_NOTIFICATION,
|
248
|
+
]
|
249
|
+
|
250
|
+
flags = 0
|
251
|
+
flags |= ((0x7 & priority) << 1) # 3 bits for priority
|
252
|
+
flags |= 1 if sticky # 1 bit for sticky
|
253
|
+
|
254
|
+
packet << flags
|
255
|
+
packet << name.length
|
256
|
+
packet << title.length
|
257
|
+
packet << description.length
|
258
|
+
packet << @app_name.length
|
259
|
+
|
260
|
+
data << name
|
261
|
+
data << title
|
262
|
+
data << description
|
263
|
+
data << @app_name
|
264
|
+
|
265
|
+
packet << data.join
|
266
|
+
packet = packet.pack GNN_FORMAT
|
267
|
+
|
268
|
+
checksum = MD5.new packet
|
269
|
+
checksum.update @password unless @password.nil?
|
270
|
+
|
271
|
+
packet << checksum.digest
|
272
|
+
|
273
|
+
return packet
|
274
|
+
end
|
275
|
+
|
276
|
+
##
|
277
|
+
# Set the size of the send buffer
|
278
|
+
#--
|
279
|
+
# Is this truly necessary?
|
280
|
+
|
281
|
+
def set_sndbuf(length)
|
282
|
+
@socket.setsockopt Socket::SOL_SOCKET, Socket::SO_SNDBUF, length
|
283
|
+
end
|
284
|
+
|
285
|
+
end
|
286
|
+
|
data/script/console
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# File: script/console
|
3
|
+
irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
|
4
|
+
|
5
|
+
libs = " -r irb/completion"
|
6
|
+
# Perhaps use a console_lib to store any extra methods I may want available in the cosole
|
7
|
+
# libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
|
8
|
+
libs << " -r #{File.dirname(__FILE__) + '/../lib/autotest-growl-remote.rb'}"
|
9
|
+
puts "Loading autotest-growl-remote gem"
|
10
|
+
exec "#{irb} #{libs} --simple-prompt"
|
data/script/destroy
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'rubigen'
|
6
|
+
rescue LoadError
|
7
|
+
require 'rubygems'
|
8
|
+
require 'rubigen'
|
9
|
+
end
|
10
|
+
require 'rubigen/scripts/destroy'
|
11
|
+
|
12
|
+
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
|
13
|
+
RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
|
14
|
+
RubiGen::Scripts::Destroy.new.run(ARGV)
|
data/script/generate
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'rubigen'
|
6
|
+
rescue LoadError
|
7
|
+
require 'rubygems'
|
8
|
+
require 'rubigen'
|
9
|
+
end
|
10
|
+
require 'rubigen/scripts/generate'
|
11
|
+
|
12
|
+
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
|
13
|
+
RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
|
14
|
+
RubiGen::Scripts::Generate.new.run(ARGV)
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour
|
data/spec/spec_helper.rb
ADDED
data/tasks/rspec.rake
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
begin
|
2
|
+
require 'spec'
|
3
|
+
rescue LoadError
|
4
|
+
require 'rubygems' unless ENV['NO_RUBYGEMS']
|
5
|
+
require 'spec'
|
6
|
+
end
|
7
|
+
begin
|
8
|
+
require 'spec/rake/spectask'
|
9
|
+
rescue LoadError
|
10
|
+
puts <<-EOS
|
11
|
+
To use rspec for testing you must install rspec gem:
|
12
|
+
gem install rspec
|
13
|
+
EOS
|
14
|
+
exit(0)
|
15
|
+
end
|
16
|
+
|
17
|
+
desc "Run the specs under spec/models"
|
18
|
+
Spec::Rake::SpecTask.new do |t|
|
19
|
+
t.spec_opts = ['--options', "spec/spec.opts"]
|
20
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
21
|
+
end
|
metadata
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: kennethkalmer-autotest-growl-remote
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Kenneth Kalmer
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-09-15 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: ZenTest
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 4.0.0
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: hoe
|
27
|
+
type: :development
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 2.3.2
|
34
|
+
version:
|
35
|
+
description: A minimal copy of autotest-growl that only sends network notifications to Growl. No fancy icons, but great for sending messages from a virtual machine or a local CI box.
|
36
|
+
email:
|
37
|
+
- kenneth.kalmer@mgila.com
|
38
|
+
executables: []
|
39
|
+
|
40
|
+
extensions: []
|
41
|
+
|
42
|
+
extra_rdoc_files:
|
43
|
+
- History.txt
|
44
|
+
- Manifest.txt
|
45
|
+
- PostInstall.txt
|
46
|
+
- TODO.txt
|
47
|
+
files:
|
48
|
+
- History.txt
|
49
|
+
- Manifest.txt
|
50
|
+
- PostInstall.txt
|
51
|
+
- README.rdoc
|
52
|
+
- Rakefile
|
53
|
+
- TODO.txt
|
54
|
+
- lib/autotest-growl-remote.rb
|
55
|
+
- lib/autotest/growl/remote.rb
|
56
|
+
- lib/autotest/growl/result.rb
|
57
|
+
- lib/autotest/growl/ruby-growl.rb
|
58
|
+
- script/console
|
59
|
+
- script/destroy
|
60
|
+
- script/generate
|
61
|
+
- spec/autotest-growl-remote_spec.rb
|
62
|
+
- spec/spec.opts
|
63
|
+
- spec/spec_helper.rb
|
64
|
+
- tasks/rspec.rake
|
65
|
+
has_rdoc: false
|
66
|
+
homepage: http://github.com/kennethkalmer/autotest-growl-remote
|
67
|
+
licenses:
|
68
|
+
post_install_message: PostInstall.txt
|
69
|
+
rdoc_options:
|
70
|
+
- --main
|
71
|
+
- README.rdoc
|
72
|
+
require_paths:
|
73
|
+
- lib
|
74
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: "0"
|
79
|
+
version:
|
80
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: "0"
|
85
|
+
version:
|
86
|
+
requirements: []
|
87
|
+
|
88
|
+
rubyforge_project: autotest-growl-remote
|
89
|
+
rubygems_version: 1.3.5
|
90
|
+
signing_key:
|
91
|
+
specification_version: 3
|
92
|
+
summary: A minimal copy of autotest-growl that only sends network notifications to Growl
|
93
|
+
test_files: []
|
94
|
+
|