hubeye 0.3.0 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION.rb +2 -2
- data/bin/hubeye +69 -67
- data/lib/hubeye/client/client.rb +83 -0
- data/lib/hubeye/client/connection.rb +44 -0
- data/lib/hubeye/config/environment.rb +13 -0
- data/lib/{config → hubeye/config}/parser.rb +1 -1
- data/lib/hubeye/helpers/time.rb +8 -0
- data/lib/{hooks → hubeye/hooks}/executer.rb +6 -5
- data/lib/{hooks → hubeye/hooks}/git_hooks.rb +2 -3
- data/lib/hubeye/log/logger.rb +39 -0
- data/lib/hubeye/notification/finder.rb +64 -0
- data/lib/hubeye/notification/gnomenotify.rb +15 -0
- data/lib/{notification → hubeye/notification}/growl.rb +0 -0
- data/lib/hubeye/server/commit.rb +51 -0
- data/lib/hubeye/server/server.rb +686 -0
- data/lib/hubeye/server/session.rb +59 -0
- data/lib/hubeye/shared/hubeye_protocol.rb +36 -0
- data/test/config_parser.rb +2 -2
- data/test/environment.rb +1 -1
- data/test/integration.rb +24 -0
- data/test/notification.rb +3 -2
- data/test/runner.rb +3 -3
- metadata +18 -13
- data/lib/client/hubeye_client.rb +0 -103
- data/lib/environment.rb +0 -10
- data/lib/helpers/time.rb +0 -5
- data/lib/log/logger.rb +0 -38
- data/lib/notification/finder.rb +0 -62
- data/lib/notification/gnomenotify.rb +0 -13
- data/lib/server/hubeye_server.rb +0 -767
data/VERSION.rb
CHANGED
data/bin/hubeye
CHANGED
@@ -1,79 +1,82 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
|
4
|
-
require File.join(File.expand_path(File.dirname(__FILE__) + "/../"), "lib/environment")
|
5
|
-
include Environment
|
6
|
-
require File.join(ROOTDIR, 'VERSION')
|
3
|
+
module Hubeye
|
7
4
|
|
8
|
-
#
|
9
|
-
require
|
10
|
-
|
5
|
+
# require environment and VERSION files
|
6
|
+
require File.join(File.expand_path(File.dirname(__FILE__) + "/../"), "lib/hubeye/config/environment")
|
7
|
+
include Environment
|
8
|
+
require File.join(ROOTDIR, 'VERSION')
|
11
9
|
|
12
|
-
|
13
|
-
require '
|
10
|
+
# standard lib
|
11
|
+
require 'optparse'
|
12
|
+
require 'ostruct'
|
14
13
|
|
15
|
-
|
16
|
-
|
17
|
-
|
14
|
+
unless File.exists?(File.join(ENV['HOME'],'.hubeye'))
|
15
|
+
require 'rake'
|
16
|
+
require File.join(ROOTDIR, 'tasks', 'install')
|
17
|
+
Rake.application['install'].invoke
|
18
|
+
end
|
18
19
|
|
19
|
-
class Options
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
20
|
+
class Options
|
21
|
+
DEFAULT_PORT = 4545
|
22
|
+
|
23
|
+
def self.parse(args)
|
24
|
+
|
25
|
+
# defaults
|
26
|
+
options = OpenStruct.new
|
27
|
+
options.server_wanted = true
|
28
|
+
options.client_wanted = false
|
29
|
+
options.server_daemonized = true
|
30
|
+
options.port = DEFAULT_PORT
|
31
|
+
options.host = 'localhost'
|
32
|
+
|
33
|
+
opts_saved = OptionParser.new do |opts|
|
34
|
+
opts.banner = "Usage: hubeye [options]"
|
35
|
+
opts.separator ""
|
36
|
+
opts.separator "Note: The default port (for server and client) is #{DEFAULT_PORT}"
|
37
|
+
opts.separator " The default host (for server and client) is localhost"
|
38
|
+
opts.separator ""
|
39
|
+
opts.separator "Specific options:"
|
40
|
+
|
41
|
+
opts.on("-s", "--server", "Start the server (default: daemonized)") do
|
42
|
+
options.client_wanted = false
|
43
|
+
options.server_wanted = true
|
44
|
+
end
|
40
45
|
|
41
|
-
|
42
|
-
|
43
|
-
|
46
|
+
opts.on("-t", "--top", "Run server process in terminal") do
|
47
|
+
options.server_daemonized = false
|
48
|
+
end
|
44
49
|
|
45
|
-
|
46
|
-
|
47
|
-
|
50
|
+
opts.on("-o", "--host HOST", "Host that the server runs on / client connects to") do |h|
|
51
|
+
options.host = h
|
52
|
+
end
|
48
53
|
|
49
|
-
|
50
|
-
|
51
|
-
|
54
|
+
opts.on("-p", "--port PORT", "Port that the server runs on / client connects to") do |p|
|
55
|
+
options.port = p.to_i
|
56
|
+
end
|
52
57
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
58
|
+
opts.on("-c", "--client", "Start hubeye client to interact with server") do
|
59
|
+
options.server_wanted = false
|
60
|
+
options.client_wanted = true
|
61
|
+
end
|
57
62
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
63
|
+
opts.on_tail("-v", "--version", "Show hubeye version") do
|
64
|
+
puts VERSION.join('.')
|
65
|
+
exit
|
66
|
+
end
|
62
67
|
|
63
|
-
|
64
|
-
|
65
|
-
|
68
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
69
|
+
puts opts
|
70
|
+
exit
|
71
|
+
end
|
66
72
|
end
|
67
|
-
end
|
68
|
-
|
69
|
-
opts_saved.parse!(args)
|
70
|
-
options
|
71
|
-
end # end of Options::parse
|
72
73
|
|
73
|
-
|
74
|
+
opts_saved.parse!(args)
|
75
|
+
options
|
76
|
+
end # end of Options::parse
|
74
77
|
|
78
|
+
end # end of class
|
75
79
|
|
76
|
-
class Hubeye
|
77
80
|
class << self
|
78
81
|
|
79
82
|
def start
|
@@ -86,7 +89,7 @@ class Hubeye
|
|
86
89
|
puts "A service is already running on this port"
|
87
90
|
exit 1
|
88
91
|
end
|
89
|
-
require File.join(
|
92
|
+
require File.join('hubeye', 'server', 'server')
|
90
93
|
options.server_daemonized ?
|
91
94
|
start_server(port, :daemon => true) :
|
92
95
|
start_server(port, :daemon => false)
|
@@ -94,7 +97,7 @@ class Hubeye
|
|
94
97
|
['INT', 'KILL'].each do |sig|
|
95
98
|
trap(sig) { STDOUT.puts; exit 1 }
|
96
99
|
end
|
97
|
-
require File.join(
|
100
|
+
require File.join('hubeye', 'client', 'client')
|
98
101
|
start_client(host, port)
|
99
102
|
end
|
100
103
|
end
|
@@ -109,17 +112,16 @@ class Hubeye
|
|
109
112
|
true
|
110
113
|
end
|
111
114
|
|
112
|
-
def start_server(port, options={})
|
113
|
-
server =
|
115
|
+
def start_server(port, options={}, *)
|
116
|
+
server = Server::Server.new(true) # debug
|
114
117
|
if options[:daemon]
|
115
118
|
Process.daemon(true) # don't change dir to '/'
|
116
119
|
end
|
117
120
|
server.start(port, options)
|
118
121
|
end
|
119
122
|
|
120
|
-
|
121
|
-
|
122
|
-
client = HubeyeClient.new
|
123
|
+
def start_client(host, port, *)
|
124
|
+
client = Client::Client.new(false) # debug
|
123
125
|
client.start(host, port)
|
124
126
|
end
|
125
127
|
|
@@ -0,0 +1,83 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'readline'
|
3
|
+
require_relative 'connection'
|
4
|
+
|
5
|
+
module Hubeye
|
6
|
+
module Client
|
7
|
+
class Client
|
8
|
+
@@stty_save = `stty -g`
|
9
|
+
|
10
|
+
begin
|
11
|
+
Readline.emacs_editing_mode
|
12
|
+
rescue NotImplementedError
|
13
|
+
@@libedit = true
|
14
|
+
ensure
|
15
|
+
LIST = %w{quit shutdown exit tracking hook add dir}
|
16
|
+
comp_proc = Proc.new {|s| LIST.grep /^#{Regexp.escape(s)}/}
|
17
|
+
Readline.completion_proc = comp_proc rescue nil
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize(debug=false)
|
21
|
+
@debug = debug
|
22
|
+
end
|
23
|
+
|
24
|
+
def start(host, port)
|
25
|
+
conn = Connection.new(host, port)
|
26
|
+
conn.receive_welcome
|
27
|
+
@s = conn.s
|
28
|
+
interact
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
# Now begin a loop of client/server interaction.
|
34
|
+
def interact
|
35
|
+
loop do
|
36
|
+
get_input_from_readline
|
37
|
+
begin
|
38
|
+
if @input.match(/^\.$/) # '.' = pwd (of client process)
|
39
|
+
@input.gsub!(/\A\.\Z/, File.split(File.expand_path('.')).last)
|
40
|
+
else
|
41
|
+
@input.gsub!(/\//, 'diiv')
|
42
|
+
end
|
43
|
+
@s.deliver @input
|
44
|
+
rescue => e
|
45
|
+
# Errno::EPIPE for broken pipes in Unix (server got an ^C or
|
46
|
+
# something like that)
|
47
|
+
puts e.message
|
48
|
+
puts e.backtrace
|
49
|
+
exit 1
|
50
|
+
end
|
51
|
+
if @input =~ /load repo/
|
52
|
+
puts "Loading..."
|
53
|
+
end
|
54
|
+
begin
|
55
|
+
mesg = @s.read_all
|
56
|
+
rescue EOFError
|
57
|
+
mesg = "Bye!\n"
|
58
|
+
end
|
59
|
+
if mesg.chop.strip == "Bye!"
|
60
|
+
mesg[-1] == "\n" ? print(mesg) : puts(mesg)
|
61
|
+
@s.close
|
62
|
+
exit 0
|
63
|
+
elsif mesg.chop.strip.match(/shutting/i)
|
64
|
+
@s.close
|
65
|
+
exit 0
|
66
|
+
else
|
67
|
+
mesg[-1] == "\n" ? print(mesg) : puts(mesg)
|
68
|
+
next
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def get_input_from_readline
|
74
|
+
begin
|
75
|
+
@input = Readline.readline('> ', true)
|
76
|
+
rescue Interrupt => e
|
77
|
+
system('stty', @@stty_save)
|
78
|
+
exit
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require "hubeye/shared/hubeye_protocol"
|
2
|
+
|
3
|
+
module Hubeye
|
4
|
+
module Client
|
5
|
+
class Connection
|
6
|
+
attr_reader :s, :local, :peer, :peeraddr
|
7
|
+
|
8
|
+
def initialize(host, port)
|
9
|
+
_begin do
|
10
|
+
print "Connecting..."
|
11
|
+
@s = TCPSocket.open(host, port)
|
12
|
+
@s.sync = false
|
13
|
+
@local, @peer = @s.addr, @s.peeraddr
|
14
|
+
puts "Done" if @s
|
15
|
+
puts "Connected to #{peer[2]}:#{peer[1]} using port #{local[1]}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def receive_welcome
|
20
|
+
begin
|
21
|
+
mesg = @s.read_all
|
22
|
+
puts mesg
|
23
|
+
rescue SystemCallError, NoMethodError
|
24
|
+
puts "The server's not running!"
|
25
|
+
rescue EOFError
|
26
|
+
@retried ||= -1
|
27
|
+
@retried += 1
|
28
|
+
retry unless @retried >= 1
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def _begin
|
35
|
+
begin
|
36
|
+
yield
|
37
|
+
rescue
|
38
|
+
@debug ? puts($!) : nil
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -1,7 +1,8 @@
|
|
1
|
-
module
|
2
|
-
|
1
|
+
module Hubeye
|
2
|
+
module Hooks
|
3
|
+
class Command
|
3
4
|
|
4
|
-
|
5
|
+
class NoHookError < ArgumentError; end
|
5
6
|
|
6
7
|
#options include the directory to execute the command
|
7
8
|
#(that's it for now, will add more functionality later)
|
@@ -20,10 +21,10 @@ module Hooks
|
|
20
21
|
end
|
21
22
|
end
|
22
23
|
rescue ArgumentError
|
23
|
-
raise NoHookError
|
24
|
+
raise NoHookError "There aren't any hook commands for the repository #{repo}"
|
24
25
|
end
|
25
26
|
end
|
26
27
|
|
28
|
+
end
|
27
29
|
end
|
28
30
|
end
|
29
|
-
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Hubeye
|
2
|
+
module Log
|
3
|
+
class Logger
|
4
|
+
|
5
|
+
LOG_DIR = File.join(ENV['HOME'], '.hubeye', 'log')
|
6
|
+
|
7
|
+
def self.log(msg)
|
8
|
+
File.open(LOG_DIR, "a") do |f|
|
9
|
+
f.puts(msg)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.relog(msg)
|
14
|
+
#wipe the file and start anew
|
15
|
+
File.open(LOG_DIR, "w") do |f|
|
16
|
+
f.puts(msg)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# If :include_terminal => true, log to the terminal too (make sure that the
|
21
|
+
# process is not daemonized). Always log to the logfile.
|
22
|
+
def self.log_change(repo_name, commit_msg, committer, options={})
|
23
|
+
opts = {:include_terminal => false}.merge options
|
24
|
+
change_msg = <<MSG
|
25
|
+
===============================
|
26
|
+
Repository: #{repo_name.downcase.strip} has changed (#{Time.now.strftime("%m/%d/%Y at %I:%M%p")})
|
27
|
+
Commit msg: #{commit_msg}
|
28
|
+
Committer : #{committer}
|
29
|
+
===============================
|
30
|
+
MSG
|
31
|
+
if opts[:include_terminal]
|
32
|
+
STDOUT.puts change_msg
|
33
|
+
end
|
34
|
+
log(change_msg)
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Hubeye
|
2
|
+
module Notification
|
3
|
+
include Environment
|
4
|
+
|
5
|
+
CHANGE_ICON = "change_icon.jpg"
|
6
|
+
CHANGE_ICON_PATH = (File.join(ROOTDIR, "images", CHANGE_ICON))
|
7
|
+
|
8
|
+
class Finder
|
9
|
+
def self.find_notify
|
10
|
+
if RUBY_PLATFORM =~ /mswin/
|
11
|
+
return
|
12
|
+
elsif RUBY_PLATFORM =~ /linux/
|
13
|
+
libnotify = system('locate libnotify-bin > /dev/null')
|
14
|
+
if libnotify
|
15
|
+
require_relative "gnomenotify"
|
16
|
+
return "libnotify"
|
17
|
+
elsif LibCheck.autotest_notification
|
18
|
+
require_relative "growl"
|
19
|
+
return "growl"
|
20
|
+
end
|
21
|
+
elsif RUBY_PLATFORM =~ /darwin/i and LibCheck.autotest_notification
|
22
|
+
require_relative "growl"
|
23
|
+
return "growl"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class LibCheck
|
29
|
+
class << self
|
30
|
+
def autotest
|
31
|
+
begin
|
32
|
+
require 'autotest'
|
33
|
+
rescue LoadError
|
34
|
+
if require 'rubygems'
|
35
|
+
retry
|
36
|
+
else
|
37
|
+
return
|
38
|
+
end
|
39
|
+
end
|
40
|
+
if defined? Autotest
|
41
|
+
true
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def autotest_notification
|
46
|
+
begin
|
47
|
+
require 'autotest_notification'
|
48
|
+
rescue LoadError
|
49
|
+
if require 'rubygems'
|
50
|
+
retry
|
51
|
+
else
|
52
|
+
return
|
53
|
+
end
|
54
|
+
end
|
55
|
+
if defined? Autotest
|
56
|
+
true
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end # end Notification
|
63
|
+
end # end Hubeye
|
64
|
+
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Hubeye
|
2
|
+
module Notification
|
3
|
+
module GnomeNotify
|
4
|
+
|
5
|
+
EXPIRATION_IN_SECONDS = 2
|
6
|
+
|
7
|
+
def self.notify(title, msg, img=CHANGE_ICON_PATH)
|
8
|
+
options = "-t #{EXPIRATION_IN_SECONDS * 1000} -i #{img}"
|
9
|
+
system "notify-send #{options} '#{title}' '#{msg}'"
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
File without changes
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Hubeye
|
2
|
+
module Server
|
3
|
+
|
4
|
+
# simple interface to Github's api v3 for commits
|
5
|
+
class Commit
|
6
|
+
attr_reader :raw_input, :repo, :only_sha, :latest
|
7
|
+
|
8
|
+
def initialize(input)
|
9
|
+
@raw_input = input
|
10
|
+
@repo = input.keys.first
|
11
|
+
if Hash === input
|
12
|
+
if input[@repo].keys == ["sha"]
|
13
|
+
@only_sha = true
|
14
|
+
else
|
15
|
+
@latest = true
|
16
|
+
end
|
17
|
+
else
|
18
|
+
raise ArgumentError.new "input must be a kind of hash"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def sha
|
23
|
+
@sha ||= @raw_input[@repo]['sha']
|
24
|
+
end
|
25
|
+
|
26
|
+
def commit_message
|
27
|
+
if @only_sha
|
28
|
+
return
|
29
|
+
elsif @latest
|
30
|
+
@commit_message ||=
|
31
|
+
@raw_input[@repo]['commit']['message']
|
32
|
+
else
|
33
|
+
raise
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def committer_name
|
38
|
+
if @only_sha
|
39
|
+
return
|
40
|
+
elsif @latest
|
41
|
+
@committer_name ||=
|
42
|
+
@raw_input[@repo]['commit']['committer']['name']
|
43
|
+
else
|
44
|
+
raise
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|