hubeye 0.3.3 → 0.3.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,24 +2,21 @@ module Hubeye
2
2
  module Server
3
3
  class Session
4
4
  attr_accessor :repo_name, :username, :continuous
5
- attr_writer :tracker, :hooks
5
+ attr_writer :hooks
6
6
 
7
7
  def initialize
8
- setup_singleton_methods
9
- end
10
-
11
- def tracker
12
- @tracker ||= {}
8
+ defaults!
13
9
  end
14
10
 
15
11
  def hooks
16
12
  @hooks ||= {}
17
13
  end
18
14
 
19
- def cleanup
15
+ def defaults!
20
16
  reset_username
21
17
  reset_repo_name
22
18
  end
19
+ alias cleanup! defaults!
23
20
 
24
21
  private
25
22
  def reset_username
@@ -30,30 +27,6 @@ module Hubeye
30
27
  self.repo_name = ""
31
28
  end
32
29
 
33
- def setup_singleton_methods
34
- tracker.singleton_class.class_eval do
35
- def add_or_replace! input, new_sha=nil
36
- if Hash === input and new_sha.nil?
37
- repo = input.keys.first
38
- hash = true
39
- else
40
- repo = input
41
- two_args = true
42
- end
43
- if keys.include? repo and self[repo] == new_sha
44
- return
45
- elsif keys.include? repo
46
- ret = {:replace => true}
47
- else
48
- ret = {:add => true}
49
- end
50
- two_args ? merge!(repo => new_sha) : merge!(input)
51
- ret
52
- end
53
- end
54
- end
55
-
56
- end # end of Session class
30
+ end
57
31
  end
58
32
  end
59
-
@@ -0,0 +1,32 @@
1
+ module Hubeye
2
+ module Server
3
+ module Strategies
4
+
5
+ class AddHook
6
+ def call
7
+ cwd = File.expand_path('.')
8
+ repo_name = @matches[1]
9
+ directory = @matches[3]
10
+ command = @matches[4]
11
+ hooks = session.hooks
12
+ if repo_name.nil? and command.nil?
13
+ socket.deliver "Format: 'hook add user/repo [dir: /my/dir/repo ] cmd: some_cmd'"
14
+ return
15
+ end
16
+ directory = directory || cwd
17
+ if hooks[repo_name]
18
+ if hooks[repo_name][directory]
19
+ hooks[repo_name][directory] << command
20
+ else
21
+ hooks[repo_name][directory] = [command]
22
+ end
23
+ else
24
+ hooks[repo_name] = {directory => [command]}
25
+ end
26
+ socket.deliver "Hook added"
27
+ end
28
+ end
29
+
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,91 @@
1
+ require 'set'
2
+
3
+ module Hubeye
4
+ module Server
5
+ module Strategies
6
+
7
+ class AddRepo
8
+ STATES = [:added, :replaced, :unchanged, :invalid].freeze
9
+ ADDED = "%{committer} => %{message}\n".freeze
10
+ REPLACED = "New commit on %s\n".freeze
11
+ UNCHANGED = "Repository %s hasn't changed\n".freeze
12
+ INVALID = "%s isn't a valid Github repository\n".freeze
13
+
14
+ # Add the given space-separated Github repo(s) if they're valid
15
+ def call
16
+ repo_names_given = @matches[1].split
17
+ @multiple_repos_given = repo_names_given.size > 1
18
+ @unique_repo_names = Set.new
19
+ # hash of states associated with repository names.
20
+ # Ex: {:added => ['luke-gru/hubeye'], :replaced => ['rails/rails'], ...}
21
+ @states_with_repos = Hash[STATES.map {|s| [ s, [] ]}]
22
+ repo_names_given.each do |name|
23
+ full_name = server.full_repo_name(name)
24
+ @unique_repo_names << full_name
25
+ end
26
+ add_repos
27
+ gather_output
28
+ socket.deliver @output
29
+ end
30
+
31
+ private
32
+
33
+ def add_repos
34
+ @unique_repo_names.each do |full_name|
35
+ change_state = tracker << full_name
36
+ @states_with_repos[change_state] << full_name
37
+ end
38
+ end
39
+
40
+ def gather_output
41
+ @output = ''
42
+ STATES.each do |state|
43
+ @states_with_repos[state].each do |full_name|
44
+ @output << header(full_name) if @multiple_repos_given
45
+ case state
46
+ when :added
47
+ cmt = tracker.commit(full_name)
48
+ @output << ADDED % {:committer => cmt.committer_name, :message => cmt.message}
49
+ when :replaced
50
+ cmt = tracker.commit(full_name)
51
+ @output << REPLACED % full_name
52
+ log_change(full_name, cmt)
53
+ when :unchanged
54
+ @output << UNCHANGED % full_name
55
+ when :invalid
56
+ @output << INVALID % full_name
57
+ end
58
+ @output << "\n" if @multiple_repos_given && full_name != last_repo_outputted
59
+ end
60
+ end
61
+ end
62
+
63
+ def header(full_name)
64
+ ''.tap do |output|
65
+ output << full_name + "\n"
66
+ output << ('=' * full_name.length) + ("\n" * 2)
67
+ end
68
+ end
69
+
70
+ def log_change(repo_name, cmt)
71
+ if server.daemonized
72
+ Logger.log_change("#{repo_name}", cmt.message, cmt.committer_name)
73
+ else
74
+ Logger.log_change("#{repo_name}", cmt.message, cmt.committer_name,
75
+ :include_terminal => true)
76
+ end
77
+ end
78
+
79
+ def last_repo_outputted
80
+ return @last if @last
81
+ STATES.reverse_each do |state|
82
+ repo_names = @states_with_repos[state]
83
+ next if repo_names.last.nil?
84
+ return (@last = repo_names.last)
85
+ end
86
+ end
87
+ end # end of AddRepo
88
+
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,121 @@
1
+ require 'forwardable'
2
+
3
+ $decision_relatives = Dir.glob( File.join(File.expand_path("../", __FILE__), '*') )
4
+ $decision_relatives.each {|file| require file }
5
+
6
+ module Hubeye
7
+ module Server
8
+ module Strategies
9
+
10
+ # STRATEGIES hash
11
+ # ===============
12
+ # keys: input matches
13
+ # OR
14
+ # lambda {|input| input.something?} => SomeStrategy.new(decision)
15
+ #
16
+ # values: lambda {|decision, matches| SomeStrategy.new(decision, matches)}
17
+ STRATEGIES = {
18
+ %r{\Ashutdown\Z} => lambda {|d, m| Shutdown.new(d, m)},
19
+ %r{\Aquit|exit\Z} => lambda {|d, m| Exit.new(d, m)},
20
+ %r{\Atracking\s*\Z} => lambda {|d, m| ListTracking.new(d, m)},
21
+ %r{\Atracking\s*-d\Z} => lambda {|d, m| ListTracking.new(d, m, :details => true)},
22
+ %r{\Aadd (.*)} => lambda {|d, m| AddRepo.new(d, m)},
23
+ %r{\A\s*save hook(s?) as (.+)\Z} => lambda {|d, m| SaveHook.new(d, m)},
24
+ %r{\A\s*save repo(s?) as (.+)\Z} => lambda {|d, m| SaveRepo.new(d, m)},
25
+ %r{\A\s*load hook(s?) (.+)\Z} => lambda {|d, m| LoadHook.new(d, m)},
26
+ %r{\A\s*load repo(s?) (.+)\Z} => lambda {|d, m| LoadRepo.new(d, m)},
27
+ %r{\A\s*internal load hook(s?) (.+)\Z} => lambda {|d, m| LoadHook.new(d, m, :internal => true)},
28
+ %r{\A\s*internal load repo(s?) (.+)\Z} => lambda {|d, m| LoadRepo.new(d, m, :internal => true)},
29
+ %r{\Ahook add ([-\w]+/[-\w]+) (dir:\s?(.*))?\s*cmd:\s?(.*)\Z} => lambda {|d, m| AddHook.new(d, m)},
30
+ %r{\Ahook list\Z} => lambda {|d, m| ListHooks.new(d, m)},
31
+ %r{^\s*$} => lambda {|d, m| Next.new(d, m)},
32
+ %r{\Arm\s*-a\Z} => lambda {|d, m| RmRepo.new(d, m, :all => true)},
33
+ %r{\Arm ([-\w]+/?[-\w]*)\Z} => lambda {|d, m| RmRepo.new(d, m)},
34
+ # if all else fails, try to add the input as a repo
35
+ %r{\A(.*)} => lambda {|d, m| AddRepo.new(d, m)},
36
+ }
37
+
38
+ class Decision
39
+ extend Forwardable
40
+ attr_reader :server, :input
41
+ InvalidInput = Class.new(StandardError)
42
+
43
+ def_delegators :@server, :tracker, :session, :sockets, :socket
44
+
45
+ def initialize(server, options={})
46
+ @server = server
47
+ opts = {:internal_input => nil}.merge options
48
+ invalid_input = lambda {
49
+ @server.remote_connection = false
50
+ throw(:invalid_input)
51
+ }
52
+
53
+ if !opts[:internal_input]
54
+ begin
55
+ @input = socket.read_all
56
+ rescue => e
57
+ STDOUT.puts e
58
+ invalid_input.call
59
+ end
60
+ # check if the client pressed ^C or ^D
61
+ if @input.nil?
62
+ invalid_input.call
63
+ end
64
+ else
65
+ @input = opts[:internal_input]
66
+ end
67
+ @input = @input.strip.downcase
68
+ @input.gsub! /diiv/, '/'
69
+ end
70
+
71
+ # Get all the strategy classes from the files names in the /server/strategies/
72
+ # directory
73
+
74
+ @@strategy_classes = []
75
+ relatives = $decision_relatives.dup
76
+ relatives.delete_if {|file| file == __FILE__}
77
+
78
+ relatives.each do |file|
79
+ strat = File.basename(file)
80
+ class_name = strat.sub(/\.rb/, '').split('_').map(&:capitalize).join
81
+ @@strategy_classes << class_name
82
+ end
83
+
84
+ @@strategy_classes.each do |class_name|
85
+ klass = Hubeye::Server::Strategies.const_get(class_name)
86
+ klass.class_eval do
87
+ extend Forwardable
88
+ attr_reader :server
89
+
90
+ def_delegators :@decision, :input
91
+ def_delegators :@server, :tracker, :session, :sockets, :socket
92
+
93
+ def initialize decision, matches=nil, options={}
94
+ @decision = decision
95
+ @matches = matches
96
+ @options = options
97
+ @server = @decision.server
98
+ call
99
+ end
100
+ end
101
+ end
102
+
103
+ def call_strategy
104
+ STRATEGIES.each do |inp,strat|
105
+ if inp.respond_to? :match
106
+ if m = @input.match(inp)
107
+ return strat.call(self, m)
108
+ end
109
+ elsif inp.respond_to? :call
110
+ if inp.call(@input)
111
+ return strat.call(self)
112
+ end
113
+ end
114
+ end
115
+ raise InvalidInput
116
+ end
117
+ end # end of Decision
118
+
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,23 @@
1
+ module Hubeye
2
+ module Server
3
+ module Strategies
4
+
5
+ class Exit
6
+ def call
7
+ socket.deliver "Bye!"
8
+ # mark the session as continuous to not wipe the log file
9
+ session.continuous = true
10
+ server.remote_connection = false
11
+ Logger.log "Closing connection to #{socket.peeraddr[2]}"
12
+ unless tracker.empty?
13
+ Logger.log "Tracking: #{tracker.repo_names.join ', '}"
14
+ end
15
+ Logger.log ""
16
+ sockets.delete(socket)
17
+ socket.close
18
+ end
19
+ end
20
+
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,38 @@
1
+ module Hubeye
2
+ module Server
3
+ module Strategies
4
+
5
+ class ListHooks
6
+ def call
7
+ hooks = session.hooks
8
+ if hooks.empty?
9
+ socket.deliver "No hooks"
10
+ return
11
+ end
12
+ pwd = File.expand_path('.')
13
+ format_string = ""
14
+ hooks.each do |repo, hash|
15
+ local_dir = nil
16
+ command = nil
17
+ hash.each do |dir,cmd|
18
+ if dir.nil?
19
+ local_dir = pwd
20
+ command = cmd.join("\n" + (' ' * 8))
21
+ else
22
+ command = cmd
23
+ local_dir = dir
24
+ end
25
+ end
26
+ format_string << <<EOS
27
+ remote: #{repo}
28
+ dir: #{local_dir}
29
+ cmds: #{command}\n
30
+ EOS
31
+ end
32
+ socket.deliver format_string
33
+ end
34
+ end
35
+
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,27 @@
1
+ module Hubeye
2
+ module Server
3
+ module Strategies
4
+
5
+ class ListTracking
6
+ def call
7
+ output = ''
8
+ if @options[:details]
9
+ commit_list = tracker.commit_list
10
+ commit_list.each do |cmt|
11
+ output << cmt.repo_name + "\n"
12
+ underline = '=' * cmt.repo_name.length
13
+ output << underline + "\n\n"
14
+ output << (cmt.committer_name + " => ") + (cmt.message + "\n")
15
+ output << "\n" unless cmt.repo_name == commit_list.last.repo_name
16
+ end
17
+ else
18
+ output << tracker.repo_names.join(', ')
19
+ end
20
+ output = "none" if output.empty?
21
+ socket.deliver output
22
+ end
23
+ end
24
+
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,34 @@
1
+ require 'yaml'
2
+
3
+ module Hubeye
4
+ module Server
5
+ module Strategies
6
+
7
+ class LoadHook
8
+ def call
9
+ if _t = @options[:internal]
10
+ @silent = _t
11
+ end
12
+ hookfile = "#{ENV['HOME']}/.hubeye/hooks/#{@matches[2]}.yml"
13
+ new_hooks = nil
14
+ if File.exists?(hookfile)
15
+ File.open(hookfile) do |f|
16
+ new_hooks = YAML.load(f)
17
+ end
18
+ # need to fix this to check if there are already commands for that
19
+ # repo
20
+ session.hooks.merge!(new_hooks)
21
+ unless @silent
22
+ socket.deliver "Loaded #{@matches[1]} #{@matches[2]}"
23
+ end
24
+ else
25
+ unless @silent
26
+ socket.deliver "No #{@matches[1]} file to load from"
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,35 @@
1
+ require 'yaml'
2
+
3
+ module Hubeye
4
+ module Server
5
+ module Strategies
6
+
7
+ class LoadRepo
8
+ def call
9
+ if _t = @options[:internal]
10
+ @silent = _t
11
+ end
12
+ if File.exists?(repo_file = "#{ENV['HOME']}/.hubeye/repos/#{@matches[2]}.yml")
13
+ new_repos = nil
14
+ File.open(repo_file) do |f|
15
+ new_repos = YAML.load(f)
16
+ end
17
+ if !new_repos
18
+ socket.deliver "Unable to load #{@matches[2]}: empty file" unless @silent
19
+ return
20
+ end
21
+ new_repos.each do |r|
22
+ tracker << server.full_repo_name(r)
23
+ end
24
+ unless @silent
25
+ socket.deliver "Loaded #{@matches[2]}.\nTracking:\n#{tracker.repo_names.join ', '}"
26
+ end
27
+ else
28
+ socket.deliver "No file to load from" unless @silent
29
+ end
30
+ end
31
+ end
32
+
33
+ end
34
+ end
35
+ end