hubeye 0.3.3 → 0.3.5
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +59 -40
- data/VERSION.rb +2 -2
- data/bin/hubeye +7 -12
- data/lib/hubeye/client/client.rb +3 -5
- data/lib/hubeye/config/environment.rb +0 -1
- data/lib/hubeye/hooks/{executer.rb → command.rb} +8 -4
- data/lib/hubeye/hooks/git.rb +19 -0
- data/lib/hubeye/log/logger.rb +1 -0
- data/lib/hubeye/server/commit.rb +17 -39
- data/lib/hubeye/server/server.rb +79 -531
- data/lib/hubeye/server/session.rb +5 -32
- data/lib/hubeye/server/strategies/add_hook.rb +32 -0
- data/lib/hubeye/server/strategies/add_repo.rb +91 -0
- data/lib/hubeye/server/strategies/decision.rb +121 -0
- data/lib/hubeye/server/strategies/exit.rb +23 -0
- data/lib/hubeye/server/strategies/list_hooks.rb +38 -0
- data/lib/hubeye/server/strategies/list_tracking.rb +27 -0
- data/lib/hubeye/server/strategies/load_hook.rb +34 -0
- data/lib/hubeye/server/strategies/load_repo.rb +35 -0
- data/lib/hubeye/server/strategies/next.rb +13 -0
- data/lib/hubeye/server/strategies/rm_repo.rb +34 -0
- data/lib/hubeye/server/strategies/save_hook.rb +31 -0
- data/lib/hubeye/server/strategies/save_repo.rb +31 -0
- data/lib/hubeye/server/strategies/shutdown.rb +23 -0
- data/lib/hubeye/server/tracker.rb +89 -0
- data/tasks/install.rb +8 -9
- data/test/helpers/server.rb +39 -0
- metadata +19 -4
- data/lib/hubeye/hooks/git_hooks.rb +0 -19
data/lib/hubeye/server/server.rb
CHANGED
@@ -1,6 +1,14 @@
|
|
1
1
|
require "hubeye/shared/hubeye_protocol"
|
2
2
|
require "hubeye/log/logger"
|
3
3
|
require "hubeye/helpers/time"
|
4
|
+
require "hubeye/config/parser"
|
5
|
+
require "hubeye/notification/finder"
|
6
|
+
require "hubeye/hooks/command"
|
7
|
+
require "hubeye/hooks/git"
|
8
|
+
|
9
|
+
require File.expand_path("../strategies/decision", __FILE__)
|
10
|
+
require File.expand_path("../tracker", __FILE__)
|
11
|
+
require File.expand_path("../session", __FILE__)
|
4
12
|
|
5
13
|
include Hubeye::Helpers::Time
|
6
14
|
include Hubeye::Log
|
@@ -8,20 +16,7 @@ include Hubeye::Log
|
|
8
16
|
module Hubeye
|
9
17
|
module Server
|
10
18
|
attr_accessor :remote_connection
|
11
|
-
attr_reader :socket, :sockets, :session, :daemonized
|
12
|
-
|
13
|
-
require 'yaml'
|
14
|
-
require 'json'
|
15
|
-
require 'open-uri'
|
16
|
-
require 'forwardable'
|
17
|
-
|
18
|
-
require_relative "commit"
|
19
|
-
require_relative "session"
|
20
|
-
|
21
|
-
require "hubeye/config/parser"
|
22
|
-
require "hubeye/notification/finder"
|
23
|
-
require "hubeye/hooks/git_hooks"
|
24
|
-
require "hubeye/hooks/executer"
|
19
|
+
attr_reader :socket, :sockets, :tracker, :session, :daemonized
|
25
20
|
|
26
21
|
CONFIG_FILE = File.join(ENV['HOME'], ".hubeye", "hubeyerc")
|
27
22
|
CONFIG = {}
|
@@ -61,495 +56,57 @@ module Hubeye
|
|
61
56
|
end
|
62
57
|
|
63
58
|
if CONFIG[:notification_wanted]
|
64
|
-
CONFIG[:desktop_notification] =
|
65
|
-
Notification::Finder.find_notify
|
66
|
-
end
|
67
|
-
|
68
|
-
class Exit
|
69
|
-
def call
|
70
|
-
socket = server.socket
|
71
|
-
session = server.session
|
72
|
-
socket.deliver "Bye!"
|
73
|
-
# mark the session as continuous to not wipe the log file
|
74
|
-
session.continuous = true
|
75
|
-
Logger.log "Closing connection to #{socket.peeraddr[2]}"
|
76
|
-
server.remote_connection = false
|
77
|
-
unless session.tracker.empty?
|
78
|
-
Logger.log "Tracking: #{session.tracker.keys.join ', '}"
|
79
|
-
end
|
80
|
-
Logger.log ""
|
81
|
-
server.sockets.delete(socket)
|
82
|
-
socket.close
|
83
|
-
end
|
59
|
+
CONFIG[:desktop_notification] = Notification::Finder.find_notify
|
84
60
|
end
|
85
61
|
|
86
|
-
|
87
|
-
def call
|
88
|
-
socket = server.socket
|
89
|
-
Logger.log "Closing connection to #{socket.peeraddr[2]}"
|
90
|
-
Logger.log "Shutting down... (#{NOW})"
|
91
|
-
Logger.log ""
|
92
|
-
Logger.log ""
|
93
|
-
socket.deliver "Shutting down server"
|
94
|
-
server.sockets.delete(socket)
|
95
|
-
socket.close
|
96
|
-
unless server.daemonized
|
97
|
-
STDOUT.puts "Shutting down gracefully."
|
98
|
-
end
|
99
|
-
exit 0
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
class SaveHook
|
104
|
-
def call
|
105
|
-
socket = server.socket
|
106
|
-
hooks = server.session.hooks
|
107
|
-
if !hooks.empty?
|
108
|
-
file = "#{ENV['HOME']}/.hubeye/hooks/#{@matches[2]}.yml"
|
109
|
-
if File.exists? file
|
110
|
-
override?
|
111
|
-
end
|
112
|
-
File.open(file, "w") do |f_out|
|
113
|
-
::YAML.dump(hooks, f_out)
|
114
|
-
end
|
115
|
-
socket.deliver "Saved hook#{@matches[1]} as #{@matches[2]}"
|
116
|
-
else
|
117
|
-
socket.deliver "No hook#{@matches[1]} to save"
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
private
|
122
|
-
def override?
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
class SaveRepo
|
127
|
-
def call
|
128
|
-
socket = server.socket
|
129
|
-
if !server.session.tracker.empty?
|
130
|
-
file = "#{ENV['HOME']}/.hubeye/repos/#{@matches[2]}.yml"
|
131
|
-
if File.exists? file
|
132
|
-
override?
|
133
|
-
end
|
134
|
-
# dump only the repository names, not the shas
|
135
|
-
File.open(file, "w") do |f_out|
|
136
|
-
::YAML.dump(server.session.tracker.keys, f_out)
|
137
|
-
end
|
138
|
-
socket.deliver "Saved repo#{@matches[1]} as #{@matches[2]}"
|
139
|
-
else
|
140
|
-
socket.deliver "No remote repos are being tracked"
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
private
|
145
|
-
def override?
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
class LoadHook
|
150
|
-
def call
|
151
|
-
socket = server.socket
|
152
|
-
if _t = @options[:internal]
|
153
|
-
@silent = _t
|
154
|
-
end
|
155
|
-
hookfile = "#{ENV['HOME']}/.hubeye/hooks/#{@matches[2]}.yml"
|
156
|
-
new_hooks = nil
|
157
|
-
if File.exists?(hookfile)
|
158
|
-
File.open(hookfile) do |f|
|
159
|
-
new_hooks = ::YAML.load(f)
|
160
|
-
end
|
161
|
-
# need to fix this to check if there are already commands for that
|
162
|
-
# repo
|
163
|
-
server.session.hooks.merge!(new_hooks)
|
164
|
-
unless @silent
|
165
|
-
socket.deliver "Loaded #{@matches[1]} #{@matches[2]}"
|
166
|
-
end
|
167
|
-
else
|
168
|
-
unless @silent
|
169
|
-
socket.deliver "No #{@matches[1]} file to load from"
|
170
|
-
end
|
171
|
-
end
|
172
|
-
end
|
173
|
-
end
|
174
|
-
|
175
|
-
class LoadRepo
|
176
|
-
def call
|
177
|
-
socket = server.socket
|
178
|
-
if _t = @options[:internal]
|
179
|
-
@silent = _t
|
180
|
-
end
|
181
|
-
if File.exists?(repo_file = "#{ENV['HOME']}/.hubeye/repos/#{@matches[2]}.yml")
|
182
|
-
new_repos = nil
|
183
|
-
File.open(repo_file) do |f|
|
184
|
-
new_repos = ::YAML.load(f)
|
185
|
-
end
|
186
|
-
if !new_repos
|
187
|
-
socket.deliver "Unable to load #{@matches[2]}: empty file" unless @silent
|
188
|
-
return
|
189
|
-
end
|
190
|
-
new_repos.each do |r|
|
191
|
-
# add the repo name to the hubeye tracker
|
192
|
-
commit = server.track(r)
|
193
|
-
server.session.tracker.add_or_replace!(commit.repo, commit.sha)
|
194
|
-
end
|
195
|
-
unless @silent
|
196
|
-
socket.deliver "Loaded #{@matches[2]}.\nTracking:\n#{server.session.tracker.keys.join ', '}"
|
197
|
-
end
|
198
|
-
else
|
199
|
-
socket.deliver "No file to load from" unless @silent
|
200
|
-
end
|
201
|
-
end
|
202
|
-
end
|
203
|
-
|
204
|
-
class AddHook
|
205
|
-
def call
|
206
|
-
socket = server.socket
|
207
|
-
cwd = File.expand_path('.')
|
208
|
-
repo = @matches[1]
|
209
|
-
_dir = @matches[3]
|
210
|
-
cmd = @matches[4]
|
211
|
-
hooks = server.session.hooks
|
212
|
-
if repo.nil? and cmd.nil?
|
213
|
-
socket.deliver "Format: 'hook add user/repo [dir: /my/dir/repo ] cmd: some_cmd'"
|
214
|
-
return
|
215
|
-
end
|
216
|
-
if hooks[repo]
|
217
|
-
_dir ? dir = _dir : dir = cwd
|
218
|
-
if hooks[repo][dir]
|
219
|
-
hooks[repo][dir] << cmd
|
220
|
-
else
|
221
|
-
hooks[repo][dir] = [cmd]
|
222
|
-
end
|
223
|
-
else
|
224
|
-
dir = _dir || cwd
|
225
|
-
hooks[repo] = {dir => [cmd]}
|
226
|
-
end
|
227
|
-
socket.deliver "Hook added"
|
228
|
-
end
|
229
|
-
end
|
230
|
-
|
231
|
-
class ListHooks
|
232
|
-
def call
|
233
|
-
socket = server.socket
|
234
|
-
hooks = server.session.hooks
|
235
|
-
if hooks.empty?
|
236
|
-
socket.deliver "No hooks"
|
237
|
-
return
|
238
|
-
end
|
239
|
-
pwd = File.expand_path('.')
|
240
|
-
format_string = ""
|
241
|
-
hooks.each do |repo, hash|
|
242
|
-
local_dir = nil
|
243
|
-
command = nil
|
244
|
-
hash.each do |dir,cmd|
|
245
|
-
if dir.nil?
|
246
|
-
local_dir = pwd
|
247
|
-
command = cmd.join("\n" + (' ' * 8))
|
248
|
-
else
|
249
|
-
command = cmd
|
250
|
-
local_dir = dir
|
251
|
-
end
|
252
|
-
end
|
253
|
-
format_string << <<EOS
|
254
|
-
remote: #{repo}
|
255
|
-
dir: #{local_dir}
|
256
|
-
cmds: #{command}\n
|
257
|
-
EOS
|
258
|
-
end
|
259
|
-
socket.deliver format_string
|
260
|
-
end
|
261
|
-
end
|
262
|
-
|
263
|
-
class ListTracking
|
264
|
-
def call
|
265
|
-
socket = server.socket
|
266
|
-
tracker = server.session.tracker
|
267
|
-
output = ''
|
268
|
-
if @options[:details]
|
269
|
-
commit_list = []
|
270
|
-
tracker.keys.each do |repo|
|
271
|
-
commit = server.track(repo, :list => true)
|
272
|
-
commit_list << commit
|
273
|
-
end
|
274
|
-
commit_list.each do |c|
|
275
|
-
output << c.repo + "\n"
|
276
|
-
underline = '=' * c.repo.length
|
277
|
-
output << underline + "\n\n"
|
278
|
-
output << c.commit_message + "\n=> " +
|
279
|
-
c.committer_name + "\n"
|
280
|
-
output << "\n" unless c.repo == commit_list.last.repo
|
281
|
-
end
|
282
|
-
else
|
283
|
-
output << tracker.keys.join(', ')
|
284
|
-
end
|
285
|
-
output = "none" if output.empty?
|
286
|
-
socket.deliver output
|
287
|
-
end
|
288
|
-
end
|
289
|
-
|
290
|
-
class Next
|
291
|
-
def call
|
292
|
-
server.socket.deliver ""
|
293
|
-
end
|
294
|
-
end
|
295
|
-
|
296
|
-
class RmRepo
|
297
|
-
def call
|
298
|
-
socket = server.socket
|
299
|
-
session = server.session
|
300
|
-
username = session.username
|
301
|
-
repo_name = session.repo_name
|
302
|
-
m1 = @matches[1]
|
303
|
-
if m1.include?('/')
|
304
|
-
username, repo_name = m1.split('/')
|
305
|
-
else
|
306
|
-
repo_name = m1
|
307
|
-
end
|
308
|
-
full_repo_name = "#{username}/#{repo_name}"
|
309
|
-
rm = session.tracker.delete(full_repo_name)
|
310
|
-
if rm
|
311
|
-
socket.deliver "Stopped watching repository #{full_repo_name}"
|
312
|
-
else
|
313
|
-
socket.deliver "Repository #{full_repo_name} not currently being watched"
|
314
|
-
end
|
315
|
-
end
|
316
|
-
end
|
317
|
-
|
318
|
-
class AddRepo
|
319
|
-
def call
|
320
|
-
session = server.session
|
321
|
-
if @options and @options[:fullpath]
|
322
|
-
session.username, session.repo_name = input.split('/')
|
323
|
-
else
|
324
|
-
session.repo_name = input
|
325
|
-
end
|
326
|
-
add_repo
|
327
|
-
end
|
328
|
-
|
329
|
-
private
|
330
|
-
def add_repo
|
331
|
-
socket = server.socket
|
332
|
-
session = server.session
|
333
|
-
full_repo_name = "#{session.username}/#{session.repo_name}"
|
334
|
-
commit = server.track(full_repo_name, :latest => true)
|
335
|
-
new_sha = commit.sha
|
336
|
-
commit_msg = commit.commit_message
|
337
|
-
committer = commit.committer_name
|
338
|
-
msg = "#{commit_msg}\n=> #{committer}"
|
339
|
-
change = session.tracker.add_or_replace!(full_repo_name, new_sha)
|
340
|
-
# new repo to track
|
341
|
-
if !change
|
342
|
-
socket.deliver "Repository #{full_repo_name} has not changed"
|
343
|
-
return
|
344
|
-
elsif change[:add]
|
345
|
-
# log the fact that the user added a repo to be tracked
|
346
|
-
Logger.log("Added to tracker: #{full_repo_name} (#{NOW})")
|
347
|
-
# show the user, via the client, the info and commit msg for the commit
|
348
|
-
socket.deliver msg
|
349
|
-
elsif change[:replace]
|
350
|
-
change_msg = "New commit on #{full_repo_name}\n"
|
351
|
-
change_msg << msg
|
352
|
-
socket.deliver change_msg
|
353
|
-
if server.daemonized
|
354
|
-
Logger.log_change(full_repo_name, commit_msg, committer)
|
355
|
-
else
|
356
|
-
Logger.log_change(full_repo_name, commit_msg, committer,
|
357
|
-
:include_terminal => true)
|
358
|
-
end
|
359
|
-
end
|
360
|
-
end
|
361
|
-
end
|
362
|
-
|
363
|
-
class Strategy
|
364
|
-
attr_reader :server, :input
|
365
|
-
|
366
|
-
UnknownStrategy = Class.new(StandardError)
|
367
|
-
extend Forwardable
|
368
|
-
def_delegator :@server, :socket
|
369
|
-
|
370
|
-
def initialize(server, options={})
|
371
|
-
@server = server
|
372
|
-
opts = {:internal_input => nil}.merge options
|
373
|
-
invalid_input = lambda {
|
374
|
-
@server.remote_connection = false
|
375
|
-
throw(:invalid_input)
|
376
|
-
}
|
377
|
-
|
378
|
-
if !opts[:internal_input]
|
379
|
-
begin
|
380
|
-
@input = socket.read_all
|
381
|
-
rescue => e
|
382
|
-
STDOUT.puts e
|
383
|
-
invalid_input.call
|
384
|
-
end
|
385
|
-
# check if the client pressed ^C or ^D
|
386
|
-
if @input.nil?
|
387
|
-
invalid_input.call
|
388
|
-
end
|
389
|
-
else
|
390
|
-
@input = opts[:internal_input]
|
391
|
-
end
|
392
|
-
@input = @input.strip.downcase
|
393
|
-
@input.gsub! /diiv/, '/'
|
394
|
-
end
|
395
|
-
|
396
|
-
STRATEGY_CLASSES = [ "Shutdown", "Exit", "SaveHook", "SaveRepo",
|
397
|
-
"LoadHook", "LoadRepo", "AddHook", "ListHooks", "ListTracking",
|
398
|
-
"Next", "RmRepo", "AddRepo" ]
|
399
|
-
|
400
|
-
STRATEGY_CLASSES.each do |klass_str|
|
401
|
-
klass = eval "::Hubeye::Server::#{klass_str}"
|
402
|
-
klass.class_eval do
|
403
|
-
extend Forwardable
|
404
|
-
def_delegators :@strategy, :input, :server
|
405
|
-
def initialize matches, strategy, options={}
|
406
|
-
@matches = matches
|
407
|
-
@strategy = strategy
|
408
|
-
@options = options
|
409
|
-
call
|
410
|
-
end
|
411
|
-
end
|
412
|
-
end
|
413
|
-
|
414
|
-
# strategy classes
|
415
|
-
|
416
|
-
# STRATEGIES hash
|
417
|
-
# ===============
|
418
|
-
# keys: input matches
|
419
|
-
# OR
|
420
|
-
# lambda {|input| input.something?} => value
|
421
|
-
#
|
422
|
-
# values: lambda {|matchdata, basestrategy| SomeStrategy.new(matchdata, basestrategy)}
|
423
|
-
STRATEGIES = {
|
424
|
-
%r{\Ashutdown\Z} => lambda {|m, s| Shutdown.new(m, s)},
|
425
|
-
%r{\Aquit|exit\Z} => lambda {|m, s| Exit.new(m, s)},
|
426
|
-
%r{\Atracking\s*\Z} => lambda {|m, s| ListTracking.new(m, s)},
|
427
|
-
%r{\Atracking\s*-d\Z} => lambda {|m, s| ListTracking.new(m, s, :details => true)},
|
428
|
-
%r{\A\s*save hook(s?) as (.+)\Z} => lambda {|m, s| SaveHook.new(m, s)},
|
429
|
-
%r{\A\s*save repo(s?) as (.+)\Z} => lambda {|m, s| SaveRepo.new(m, s)},
|
430
|
-
%r{\A\s*load hook(s?) (.+)\Z} => lambda {|m, s| LoadHook.new(m, s)},
|
431
|
-
%r{\A\s*load repo(s?) (.+)\Z} => lambda {|m, s| LoadRepo.new(m, s)},
|
432
|
-
%r{\A\s*internal load hook(s?) (.+)\Z} => lambda {|m, s| LoadHook.new(m, s, :internal => true)},
|
433
|
-
%r{\A\s*internal load repo(s?) (.+)\Z} => lambda {|m, s| LoadRepo.new(m, s, :internal => true)},
|
434
|
-
%r{\Ahook add ([-\w]+/[-\w]+) (dir:\s?(.*))?\s*cmd:\s?(.*)\Z} => lambda {|m, s| AddHook.new(m, s)},
|
435
|
-
%r{\Ahook list\Z} => lambda {|m, s| ListHooks.new(m, s)},
|
436
|
-
%r{^\s*$} => lambda {|m, s| Next.new(m, s)},
|
437
|
-
%r{\Arm ([-\w]+/?[-\w]*)\Z} => lambda {|m, s| RmRepo.new(m, s)},
|
438
|
-
lambda {|inp| inp.include? '/'} => lambda {|m, s| AddRepo.new(m, s, :fullpath => true)},
|
439
|
-
lambda {|inp| not inp.nil?} => lambda {|m, s| AddRepo.new(m, s)}
|
440
|
-
}
|
441
|
-
|
442
|
-
def call
|
443
|
-
STRATEGIES.each do |inp,strat|
|
444
|
-
if inp.respond_to? :match
|
445
|
-
if m = @input.match(inp)
|
446
|
-
return strat.call(m, self)
|
447
|
-
end
|
448
|
-
elsif inp.respond_to? :call
|
449
|
-
if m = inp.call(@input)
|
450
|
-
return strat.call(m, self)
|
451
|
-
end
|
452
|
-
end
|
453
|
-
end
|
454
|
-
raise UnknownStrategy
|
455
|
-
end
|
456
|
-
end # end of Strategy
|
457
|
-
|
458
|
-
|
62
|
+
# main server loop
|
459
63
|
def start(port, options={})
|
460
64
|
listen(port)
|
461
65
|
setup_env(options)
|
462
66
|
loop do
|
463
|
-
|
464
|
-
look_for_changes
|
67
|
+
unless @remote_connection
|
68
|
+
look_for_changes
|
69
|
+
client_connect(@sockets)
|
465
70
|
end
|
466
|
-
client_connect(@sockets) if waiting
|
467
71
|
catch(:invalid_input) do
|
468
|
-
|
469
|
-
|
72
|
+
decision = Strategies::Decision.new(self)
|
73
|
+
decision.call_strategy
|
470
74
|
end
|
471
|
-
@session.cleanup
|
75
|
+
@session.cleanup!
|
472
76
|
end
|
473
77
|
end
|
474
78
|
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
# Options: :sha, :latest, :full, :list (all boolean).
|
479
|
-
# The :list => true option gives back the commit object from the list.
|
480
|
-
list = []
|
481
|
-
|
482
|
-
define_method :track do |repo, options={}|
|
483
|
-
if repo.include? '/'
|
484
|
-
username, repo_name = repo.split '/'
|
485
|
-
full_repo_name = repo
|
486
|
-
else
|
487
|
-
username, repo_name = @session.username, repo
|
488
|
-
full_repo_name = "#{username}/#{repo_name}"
|
489
|
-
end
|
490
|
-
unless options[:list]
|
491
|
-
hist = nil
|
492
|
-
begin
|
493
|
-
open "https://api.github.com/repos/#{username}/" \
|
494
|
-
"#{repo_name}/commits" do |f|
|
495
|
-
hist = JSON.parse f.read
|
496
|
-
end
|
497
|
-
rescue
|
498
|
-
@socket.deliver "Not a Github repository name"
|
499
|
-
throw(:invalid_input)
|
500
|
-
end
|
501
|
-
new_info =
|
502
|
-
{full_repo_name =>
|
503
|
-
{'sha' => hist.first['sha'],
|
504
|
-
'commit' =>
|
505
|
-
{'message' => hist.first['commit']['message'],
|
506
|
-
'committer' => {'name' => hist.first['commit']['committer']['name']}
|
507
|
-
}
|
508
|
-
}
|
509
|
-
}
|
510
|
-
commit = Commit.new(new_info)
|
511
|
-
# update the list
|
512
|
-
list.reject! {|cmt| cmt.repo == full_repo_name}
|
513
|
-
list << commit
|
514
|
-
end
|
515
|
-
if options[:full]
|
516
|
-
# unsupported so far
|
517
|
-
raise ArgumentError.new
|
518
|
-
elsif options[:latest]
|
519
|
-
commit.dup
|
520
|
-
elsif options[:list]
|
521
|
-
list.each {|c| return c if c.repo == full_repo_name}
|
522
|
-
nil
|
523
|
-
else
|
524
|
-
Commit.new full_repo_name => {'sha' => hist.first['sha']}
|
525
|
-
end
|
79
|
+
def full_repo_name(repo)
|
80
|
+
return repo if repo.include? '/'
|
81
|
+
[@session.username, repo].join '/'
|
526
82
|
end
|
527
83
|
|
528
84
|
private
|
529
85
|
def listen(port)
|
530
|
-
@
|
86
|
+
@tcp_server = TCPServer.open(port)
|
531
87
|
end
|
532
88
|
|
533
89
|
def setup_env(options={})
|
534
90
|
@remote_connection = false
|
535
91
|
@daemonized = options[:daemon]
|
536
|
-
@sockets = [@
|
92
|
+
@sockets = [@tcp_server]
|
537
93
|
trap_signals 'INT', 'KILL'
|
538
94
|
@session = Session.new
|
539
95
|
@session.username = CONFIG[:username]
|
96
|
+
@tracker = Tracker.new
|
540
97
|
unless CONFIG[:default_track].empty?
|
541
|
-
repos = CONFIG[:default_track]
|
98
|
+
repos = CONFIG[:default_track]
|
542
99
|
repos.each do |repo|
|
543
|
-
|
544
|
-
@
|
100
|
+
repo_name = full_repo_name(repo)
|
101
|
+
@tracker << repo_name
|
545
102
|
end
|
546
103
|
end
|
547
104
|
unless CONFIG[:load_hooks].empty?
|
548
|
-
hooks = CONFIG[:load_hooks]
|
105
|
+
hooks = CONFIG[:load_hooks]
|
549
106
|
session_load :hooks => hooks
|
550
107
|
end
|
551
108
|
unless CONFIG[:load_repos].empty?
|
552
|
-
repos = CONFIG[:load_repos]
|
109
|
+
repos = CONFIG[:load_repos]
|
553
110
|
session_load :repos => repos
|
554
111
|
end
|
555
112
|
end
|
@@ -558,7 +115,7 @@ EOS
|
|
558
115
|
sigs.each do |sig|
|
559
116
|
trap(sig) do
|
560
117
|
@sockets.each {|s| s.close}
|
561
|
-
STDOUT.
|
118
|
+
STDOUT.print "\n"
|
562
119
|
exit 1
|
563
120
|
end
|
564
121
|
end
|
@@ -568,94 +125,88 @@ EOS
|
|
568
125
|
opts = {:hooks => nil, :repos => nil}.merge options
|
569
126
|
if hooks = opts[:hooks]
|
570
127
|
hooks.each do |h|
|
571
|
-
|
572
|
-
|
128
|
+
decision = Strategies::Decision.new(self, :internal_input => "internal load hook #{h}")
|
129
|
+
decision.call_strategy
|
573
130
|
end
|
574
131
|
elsif repos = opts[:repos]
|
575
132
|
repos.each do |r|
|
576
|
-
|
577
|
-
|
133
|
+
decision = Strategies::Decision.new(self, :internal_input => "internal load repo #{r}")
|
134
|
+
decision.call_strategy
|
578
135
|
end
|
579
136
|
else
|
580
137
|
raise ArgumentError.new "Must load either hooks or repos"
|
581
138
|
end
|
582
139
|
end
|
583
140
|
|
584
|
-
#TODO: refactor this ugly, long method into a new class
|
585
141
|
def look_for_changes
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
already_logged = true
|
617
|
-
end
|
142
|
+
if @tracker.length.zero?
|
143
|
+
@remote_connection = client_ready(@sockets, :block => true)
|
144
|
+
end
|
145
|
+
while not @remote_connection
|
146
|
+
sleep_amt = CONFIG[:oncearound] / @tracker.length
|
147
|
+
@tracker.repo_names.each do |repo_name|
|
148
|
+
change_state = @tracker << repo_name
|
149
|
+
if change_state == :unchanged
|
150
|
+
(sleep_amt).times do
|
151
|
+
@remote_connection = client_ready(@sockets)
|
152
|
+
return if @remote_connection
|
153
|
+
end
|
154
|
+
else
|
155
|
+
# There was a change to a tracked repository.
|
156
|
+
commit = @tracker.last
|
157
|
+
full_repo_name = commit.repo
|
158
|
+
commit_msg = commit.message
|
159
|
+
committer = commit.committer_name
|
160
|
+
new_sha = commit.sha
|
161
|
+
change_msg = "Repo #{full_repo_name} has changed\nNew commit: " \
|
162
|
+
"#{commit_msg}\n=> #{committer}"
|
163
|
+
case CONFIG[:desktop_notification]
|
164
|
+
when "libnotify"
|
165
|
+
Notification::GnomeNotify.notify("Hubeye", change_msg)
|
166
|
+
when "growl"
|
167
|
+
Autotest::Growl.growl("Hubeye", change_msg)
|
168
|
+
when nil
|
169
|
+
unless @daemonized
|
170
|
+
Logger.log_change(full_repo_name, commit_msg, committer, :include_terminal => true)
|
171
|
+
already_logged = true
|
618
172
|
end
|
619
|
-
|
173
|
+
end
|
174
|
+
Logger.log_change(full_repo_name, commit_msg, committer) unless
|
620
175
|
already_logged
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
end
|
176
|
+
# execute any hooks for that repository
|
177
|
+
unless @session.hooks.empty?
|
178
|
+
if hooks = @session.hooks[full_repo_name]
|
179
|
+
hooks.each do |dir,cmds|
|
180
|
+
Hooks::Command.execute(cmds, :directory => dir, :repo => full_repo_name)
|
627
181
|
end
|
628
182
|
end
|
629
|
-
@session.tracker.add_or_replace!(full_repo_name, new_sha)
|
630
183
|
end
|
631
184
|
end
|
632
|
-
end
|
633
|
-
else
|
634
|
-
@remote_connection = client_ready(@sockets, :block => true) ? true : false
|
635
|
-
throw(:connect, true) if @remote_connection
|
185
|
+
end
|
636
186
|
end
|
637
187
|
end
|
638
188
|
|
639
189
|
def client_ready(sockets, options={})
|
640
190
|
if options[:block]
|
641
|
-
select(sockets, nil, nil)
|
191
|
+
r = select(sockets, nil, nil)
|
642
192
|
else
|
643
|
-
select(sockets, nil, nil, 1)
|
193
|
+
r = select(sockets, nil, nil, 1)
|
644
194
|
end
|
195
|
+
not r.nil?
|
645
196
|
end
|
646
197
|
|
647
198
|
def client_connect(sockets)
|
648
199
|
ready = select(sockets)
|
649
200
|
readable = ready[0]
|
650
201
|
readable.each do |socket|
|
651
|
-
if socket == @
|
652
|
-
@socket = @
|
653
|
-
@socket.sync =
|
202
|
+
if socket == @tcp_server
|
203
|
+
@socket = @tcp_server.accept
|
204
|
+
@socket.sync = true
|
654
205
|
sockets << @socket
|
655
206
|
# Inform the client of connection
|
656
207
|
basic_inform = "Hubeye running on #{Socket.gethostname} as #{@session.username}"
|
657
|
-
if !@
|
658
|
-
@socket.deliver "#{basic_inform}\nTracking: #{@
|
208
|
+
if !@tracker.empty?
|
209
|
+
@socket.deliver "#{basic_inform}\nTracking: #{@tracker.repo_names.join ', '}"
|
659
210
|
else
|
660
211
|
@socket.deliver basic_inform
|
661
212
|
end
|
@@ -679,8 +230,5 @@ EOS
|
|
679
230
|
@debug = debug
|
680
231
|
end
|
681
232
|
end
|
682
|
-
|
683
233
|
end # of Server module
|
684
|
-
|
685
234
|
end # end of Hubeye module
|
686
|
-
|