hubeye 0.0.4 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+ $:.unshift 'lib'
2
+
3
+ require 'rake/testtask'
4
+ require 'rake/clean'
5
+
6
+ task :default => [:test]
7
+
8
+ desc 'Run tests (default)'
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.test_files = FileList['test/runner.rb']
11
+ end
12
+
13
+ desc 'Display current version'
14
+ task :version do
15
+ require_relative 'VERSION'
16
+ puts Hubeye::VERSION * '.'
17
+ end
data/VERSION.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  class Hubeye
2
- # 0.0.4 since sept.5 2011
3
- VERSION = [0,0,4]
2
+ # 0.1.0 since oct.4, 2011
3
+ VERSION = [0,1,0]
4
4
  end
5
5
 
data/bin/hubeye CHANGED
@@ -17,7 +17,7 @@ unless RUBY_VERSION >= '1.9'
17
17
  retry
18
18
  else
19
19
  raise "The daemons gem is needed to run hubeye as a daemon " +
20
- "on Ruby < 1.9"
20
+ "on Ruby < 1.9"
21
21
  end
22
22
  end
23
23
 
@@ -36,12 +36,11 @@ class HubeyeClient
36
36
  def read_welcome
37
37
  # Wait just a bit, to see if the server sends any initial message.
38
38
  begin
39
- sleep(0.5) # Wait half a second
39
+ sleep(1) # Wait a second
40
40
  msg = @s.readpartial(4096) # Read whatever is ready
41
41
  STDOUT.puts msg.chop # And display it
42
42
  # If nothing was ready to read, just ignore the exception.
43
- rescue SystemCallError
44
- rescue NoMethodError
43
+ rescue SystemCallError, NoMethodError
45
44
  STDOUT.puts "The server's not running!"
46
45
  end
47
46
  end
@@ -64,7 +63,13 @@ class HubeyeClient
64
63
  # The server may send more than one line, so use readpartial
65
64
  # to read whatever it sends (as long as it all arrives in one chunk).
66
65
 
67
- sleep 0.5
66
+ if local =~ /load repo/
67
+ puts "Loading..."
68
+ sleep 1
69
+ else
70
+ sleep 0.5
71
+ end
72
+
68
73
  begin
69
74
  response = @s.readpartial(4096)
70
75
  rescue EOFError
data/lib/log/logger.rb CHANGED
@@ -14,12 +14,11 @@ class Logger
14
14
  end
15
15
  end
16
16
 
17
- ##If {include_socket: true} is passed, then log to the client as well. If
18
- #{include_terminal: true}, log to the terminal too (make sure that the
19
- #process is not daemonized). Always log to the logfile.
17
+ # If {include_terminal: true}, log to the terminal too (make sure that the
18
+ # process is not daemonized). Always log to the logfile.
20
19
 
21
20
  def self.log_change(repo_name, commit_msg, committer, options={})
22
- opts = {:include_socket => false, :include_terminal => false}.merge options
21
+ opts = {:include_terminal => false}.merge options
23
22
  change_msg = <<-MSG
24
23
  ===============================
25
24
  Repository: #{repo_name.downcase.strip} has changed (#{Time.now.strftime("%m/%d/%Y at %I:%M%p")})
@@ -27,10 +26,6 @@ class Logger
27
26
  Committer : #{committer}
28
27
  ===============================
29
28
  MSG
30
- if opts[:include_socket]
31
- socket.puts(change_msg)
32
- end
33
-
34
29
  if opts[:include_terminal]
35
30
  puts change_msg
36
31
  end
@@ -8,10 +8,10 @@ module Notification
8
8
  elsif RUBY_PLATFORM =~ /linux/
9
9
  libnotify = system('locate libnotify-bin > /dev/null')
10
10
 
11
- if libnotify && LibChecker.autotest
11
+ if libnotify && LibCheck.autotest
12
12
  require_relative "gnomenotify"
13
13
  return "libnotify"
14
- elsif LibChecker.autotest_notification
14
+ elsif LibCheck.autotest_notification
15
15
  require_relative "growl"
16
16
  return "growl"
17
17
  else
@@ -20,9 +20,9 @@ module Notification
20
20
 
21
21
  elsif RUBY_PLATFORM =~ /darwin/i
22
22
 
23
- if LibChecker.autotest_notification
24
- require_relative "growl"
25
- return "growl"
23
+ if LibCheck.autotest_notification
24
+ require_relative "growl"
25
+ return "growl"
26
26
  else
27
27
  return
28
28
  end
@@ -32,7 +32,7 @@ module Notification
32
32
 
33
33
  end
34
34
 
35
- class LibChecker
35
+ class LibCheck
36
36
 
37
37
  class << self
38
38
  def autotest
@@ -1,19 +1,19 @@
1
1
  module Server
2
2
  # standard lib.
3
3
  require 'socket'
4
- require 'open-uri'
5
4
  require 'yaml'
6
5
 
7
6
  # vendor
8
7
  begin
9
- require 'nokogiri'
8
+ require 'octopi'
10
9
  rescue LoadError
11
10
  if require 'rubygems'
12
11
  retry
13
12
  else
14
- abort 'Nokogiri is needed to run hubeye. Gem install nokogiri'
13
+ abort 'Octopi is needed to run hubeye. Gem install octopi'
15
14
  end
16
15
  end
16
+ include Octopi
17
17
 
18
18
  # hubeye
19
19
  require "config/parser"
@@ -32,28 +32,27 @@ module Server
32
32
  #
33
33
  # Option overview:
34
34
  #
35
- # CONFIG[:oncearound]: 30 (seconds) is the default amount of time for looking
35
+ # CONFIG[:oncearound]: 60 (seconds) is the default amount of time for looking
36
36
  # for changes in every single repository. If tracking lots of repos,
37
37
  # it might be a good idea to increase the value, or hubeye will cry
38
38
  # due to overwork, fatigue and general anhedonia.
39
39
  #
40
- # hubeyerc format: oncearound: 1000
40
+ # hubeyerc format => oncearound: 1000
41
41
  #
42
- # CONFIG[:username] is the username used when not specified:
42
+ # CONFIG[:username] is the username used when not specified.
43
+ # hubeyerc format => username: 'hansolo'
43
44
  # when set to 'hansolo'
44
45
  # >rails
45
46
  # would track https://www.github.com/hansolo/rails
46
47
  # but a full URI path won't use CONFIG[:username]
47
48
  # >rails/rails
48
49
  # would track https://www.github.com/rails/rails
49
- #
50
- # hubeyerc format: username: hansolo
51
50
  ::Hubeye::Config::Parser.new(CONFIG_FILE) do |c|
52
- CONFIG[:username] = c.username || ''
51
+ CONFIG[:username] = c.username || 'john_doe'
53
52
  CONFIG[:oncearound] = c.oncearound || 60
54
53
  CONFIG[:load_repos] = c.load_repos || []
55
54
  CONFIG[:load_hooks] = c.load_hooks || []
56
- CONFIG[:default_track] = c.default_track || []
55
+ CONFIG[:default_track] = c.default_track || nil
57
56
  # returns true or false if defined in hubeyerc
58
57
  CONFIG[:notification_wanted] = case c.notification_wanted
59
58
  when false
@@ -66,7 +65,8 @@ module Server
66
65
  end
67
66
  end
68
67
 
69
- CONFIG[:desktop_notification] = (CONFIG[:notification_wanted] ? Notification::Finder.find_notify : nil)
68
+ CONFIG[:desktop_notification] = (CONFIG[:notification_wanted] ?
69
+ Notification::Finder.find_notify : nil)
70
70
 
71
71
  class InputError < StandardError; end
72
72
 
@@ -79,7 +79,6 @@ module Server
79
79
  get_input(@socket)
80
80
  puts @input if @debug
81
81
  parse_input()
82
- get_github_doc("/#{@username}/#{@repo_name}")
83
82
  parse_doc()
84
83
  @username = CONFIG[:username]
85
84
  end
@@ -95,14 +94,18 @@ module Server
95
94
  def setup_env(options={})
96
95
  @daemonized = options[:daemon]
97
96
  @sockets = [@server] # An array of sockets we'll monitor
98
- if CONFIG[:default_track].empty?
99
- @ary_commits_repos = []
97
+ if CONFIG[:default_track].nil?
98
+ # will be array of 2-element arrays that contain the
99
+ # tracked repo name [0] and hash of latest sha and latest commit object
100
+ # for that repo [1]
101
+ # Example:
102
+ # [ ['luke-gru/hubeye', {:sha1 => 90j93r0rf389, :commit => <#Commit Object>}], [..., ...] ]
100
103
  @hubeye_tracker = []
101
104
  else
102
105
  # default tracking arrays (hubeyerc configurations)
103
106
  @hubeye_tracker = CONFIG[:default_track]
104
- @ary_commits_repos = insert_default_tracking_messages
105
107
  end
108
+ setup_hubeye_singleton_methods
106
109
 
107
110
  if CONFIG[:load_hooks].empty?
108
111
  # do nothing (the hooks hash is only assigned when needed)
@@ -125,89 +128,148 @@ module Server
125
128
  @remote_connection = false
126
129
  end
127
130
 
128
- def insert_default_tracking_messages
129
- track_default = CONFIG[:default_track].dup
130
- track_default.each do |repo|
131
- commit_msg = get_commit_msg(repo)
132
- # next unless commit_msg is non-false
133
- commit_msg ? nil : next
134
- ary_index = track_default.index(repo)
135
- track_default.insert(ary_index + 1, commit_msg)
131
+ class ::Array
132
+ include Octopi
133
+ class NotTrackerElementError < TypeError ; end
134
+
135
+ def extract_old_and_new
136
+ if length != 2
137
+ raise NotTrackerElementError.new "#{self} is not a @hubeye_tracker element"
138
+ else
139
+ tracked_repo, tracked_sha = self[0], self[1][:sha1]
140
+ username, repo_name = tracked_repo.split '/'
141
+ begin
142
+ gh_user = User.find(username)
143
+ rescue Octopi::NotFound
144
+ # fall back to using default username if not found
145
+ gh_user = @username
146
+ end
147
+ begin
148
+ repo = gh_user.repository repo_name
149
+ rescue Octopi::NotFound
150
+ raise
151
+ end
152
+ end
153
+ [tracked_sha, repo]
136
154
  end
137
- track_default
138
155
  end
139
- private :insert_default_tracking_messages
140
156
 
157
+ def setup_hubeye_singleton_methods
158
+ def_try_append_or_replace!
159
+ def_eyeing
160
+ def_rm_repo
161
+ end
141
162
 
142
- def not_connected
143
- # if no client is connected, but the commits array contains repos
144
- if @sockets.size == 1 and @ary_commits_repos.empty? == false
145
-
146
- while @remote_connection == false
147
- @hubeye_tracker.each do |repo|
148
- doc = Nokogiri::HTML(open("https://github.com/#{repo}/"))
149
-
150
- # make variable not block-local
151
- commit_msg = nil
152
-
153
- doc.xpath('//div[@class = "message"]/pre').each do |node|
154
- commit_msg = node.text
155
- if @ary_commits_repos.include?(commit_msg)
156
- CONFIG[:oncearound].times do
157
- sleep 1
158
- @remote_connection = client_ready(@sockets) ? true : false
159
- break if @remote_connection
160
- end
163
+ def def_try_append_or_replace!
164
+ @hubeye_tracker.singleton_class.class_eval do
165
+ define_method :try_append_or_replace! do |repo_name, new_commit_obj|
166
+ status = {:replace => nil, :add => nil, :same => true}
167
+ match = nil
168
+ map! do |e|
169
+ if e[0] == repo_name
170
+ match = true
171
+ if e[1][:sha1] == new_commit_obj.id
172
+ e
161
173
  else
162
- # There was a change to a tracked repository.
174
+ e[1][:sha1] = new_commit_obj.id
175
+ e[1][:commit] = new_commit_obj
176
+ status = status.merge :replace => true, :same => false
177
+ end
178
+ else
179
+ e
180
+ end
181
+ end # end of map!
182
+ if match
183
+ return status
184
+ else
185
+ self << [repo_name, {:sha1 => new_commit_obj.id,
186
+ :commit => new_commit_obj}]
187
+ return status.merge :add => true, :same => false
188
+ end
189
+ end
190
+ end
191
+ end
163
192
 
164
- # make variable not block-local
165
- committer = nil
193
+ def def_eyeing
194
+ @hubeye_tracker.singleton_class.class_eval do
195
+ define_method :eyeing do
196
+ (ary = []).tap do
197
+ each do |e|
198
+ ary << e[0]
199
+ end
200
+ end
201
+ end
202
+ end
203
+ end
204
+
205
+ def def_rm_repo
206
+ @hubeye_tracker.singleton_class.class_eval do
207
+ define_method :rm_repo do |repo_name|
208
+ match = nil
209
+ reject! do |e|
210
+ e[0] == repo_name ? match = true : nil
211
+ end
212
+ match
213
+ end
214
+ end
215
+ end
166
216
 
167
- doc.xpath('//div[@class = "actor"]/div[@class = "name"]').each do |node|
168
- committer = node.text
169
- end
170
217
 
171
- # notify of change to repository
172
- # if they have a Desktop notification
173
- # library installed
174
- change_msg = "Repo #{repo} has changed\nNew commit: #{commit_msg} => #{committer}"
175
- case CONFIG[:desktop_notification]
176
- when "libnotify"
177
- Autotest::GnomeNotify.notify("Hubeye", change_msg)
178
- Logger.log_change(repo, commit_msg, committer)
179
- when "growl"
180
- Autotest::Growl.growl("Hubeye", change_msg)
181
- Logger.log_change(repo, commit_msg, committer)
182
- when nil
183
-
184
- if @daemonized
185
- Logger.log_change(repo, commit_msg, committer)
186
- else
187
- Logger.log_change(repo, commit_msg, committer, :include_terminal => true)
188
- end
218
+ def not_connected
219
+ # if no client is connected, but the commits array contains repos
220
+ if @sockets.size == 1 and !@hubeye_tracker.empty?
189
221
 
222
+ while @remote_connection == false
223
+ sleep_amt = CONFIG[:oncearound] / @hubeye_tracker.length
224
+ @hubeye_tracker.each do |ary|
225
+ # this method does api calls, takes a couple of seconds to
226
+ # complete right now (TODO: see what's taking so long)
227
+ start_time = Time.now
228
+ old_sha, new_repo = ary.extract_old_and_new
229
+ api_time = (Time.now - start_time).to_i
230
+ new_commit = new_repo.commits.first
231
+ if new_commit.id == old_sha
232
+ (sleep_amt - api_time).times do
233
+ sleep 1
234
+ @remote_connection = client_ready(@sockets) ? true : false
235
+ break if @remote_connection
236
+ end
237
+ else
238
+ # There was a change to a tracked repository.
239
+ full_repo_name = ary[0]
240
+ commit_msg = new_commit.message
241
+ committer = new_commit.author['name']
242
+ # notify of change to repository
243
+ # if they have a Desktop notification
244
+ # library installed
245
+ change_msg = "Repo #{full_repo_name} has changed\nNew commit: " +
246
+ "#{commit_msg}\n=> #{committer}"
247
+ case CONFIG[:desktop_notification]
248
+ when "libnotify"
249
+ Autotest::GnomeNotify.notify("Hubeye", change_msg)
250
+ Logger.log_change(full_repo_name, commit_msg, committer)
251
+ when "growl"
252
+ Autotest::Growl.growl("Hubeye", change_msg)
253
+ Logger.log_change(full_repo_name, commit_msg, committer)
254
+ when nil
255
+ if @daemonized
256
+ Logger.log_change(full_repo_name, commit_msg, committer)
257
+ else
258
+ Logger.log_change(full_repo_name, commit_msg, committer, :include_terminal => true)
190
259
  end
191
- # execute any hooks for that repository
192
- unless @hook_cmds.nil? || @hook_cmds.empty?
193
- if @hook_cmds[repo]
194
- hook_cmds = @hook_cmds[repo].dup
195
- dir = (hook_cmds.include?('/') ? hook_cmds.shift : nil)
196
-
197
- # execute() takes [commands], {options} where
198
- # options = :directory and :repo
199
- Hooks::Command.execute(hook_cmds, :directory => dir, :repo => repo)
200
- end
260
+ end
261
+ # execute any hooks for that repository
262
+ unless @hook_cmds.nil? || @hook_cmds.empty?
263
+ if @hook_cmds[full_repo_name]
264
+ hook_cmds = @hook_cmds[full_repo_name].dup
265
+ dir = (hook_cmds.include?('/') ? hook_cmds.shift : nil)
266
+
267
+ # execute() takes [commands], {options} where
268
+ # options = :directory and :repo
269
+ Hooks::Command.execute(hook_cmds, :directory => dir, :repo => repo)
201
270
  end
202
-
203
- @ary_commits_repos << repo
204
- @ary_commits_repos << commit_msg
205
- # delete the repo and old commit that appear first in the array
206
- index_old_HEAD = @ary_commits_repos.index(repo)
207
- @ary_commits_repos.delete_at(index_old_HEAD)
208
- # and again to get rid of the commit message
209
- @ary_commits_repos.delete_at(index_old_HEAD)
210
271
  end
272
+ @hubeye_tracker.try_append_or_replace!(full_repo_name, new_commit)
211
273
  end
212
274
  end
213
275
  redo unless @remote_connection
@@ -232,10 +294,11 @@ module Server
232
294
  @socket = client # From here on in referred to as @socket
233
295
  sockets << @socket # Add it to the set of sockets
234
296
  # Inform the client of connection
297
+ basic_inform = "Hubeye running on #{Socket.gethostname} as #{@username}"
235
298
  if !@hubeye_tracker.empty?
236
- @socket.puts "Hubeye running on #{Socket.gethostname}\nTracking:#{@hubeye_tracker.join(' ')}"
299
+ @socket.puts "#{basic_inform}\nTracking:#{@hubeye_tracker.eyeing.join ', '}"
237
300
  else
238
- @socket.puts "Hubeye running on #{Socket.gethostname}"
301
+ @socket.puts basic_inform
239
302
  end
240
303
 
241
304
  if !@daemonized
@@ -298,11 +361,8 @@ module Server
298
361
  @socket.puts("Bye!") # Say goodbye
299
362
  Logger.log "Closing connection to #{@socket.peeraddr[2]}"
300
363
  @remote_connection = false
301
- if !@ary_commits_repos.empty?
302
- Logger.log "Tracking: "
303
- @ary_commits_repos.each do |repo|
304
- Logger.log repo if @ary_commits_repos.index(repo).even?
305
- end
364
+ if !@hubeye_tracker.empty?
365
+ Logger.log "Tracking: #{@hubeye_tracker.eyeing.join ', '}"
306
366
  end
307
367
  Logger.log "" # to look pretty when multiple connections per loop
308
368
  @sockets.delete(@socket) # Stop monitoring the socket
@@ -328,7 +388,7 @@ module Server
328
388
  else
329
389
  return
330
390
  end
331
- shutdown()
391
+ shutdown
332
392
  end
333
393
 
334
394
 
@@ -341,14 +401,13 @@ module Server
341
401
 
342
402
  def parse_hook
343
403
  if %r{hook add} =~ @input
344
- hook_add()
404
+ hook_add
345
405
  else
346
406
  return
347
407
  end
348
408
  end
349
409
 
350
410
 
351
- ##
352
411
  # @hook_cmds:
353
412
  # repo is the key, value is array of directory and commands. First element
354
413
  # of array is the local directory for that remote repo, rest are commands
@@ -390,7 +449,7 @@ module Server
390
449
  elsif @input =~ %r{\A\s*save repo(s?) as (.+)\Z}
391
450
  if !@hubeye_tracker.empty?
392
451
  File.open("#{ENV['HOME']}/.hubeye/repos/#{$2}.yml", "w") do |f_out|
393
- ::YAML.dump(@hubeye_tracker, f_out)
452
+ ::YAML.dump(@hubeye_tracker.eyeing, f_out)
394
453
  end
395
454
  @socket.puts("Saved repo#{$1} as #{$2}")
396
455
  else
@@ -452,20 +511,15 @@ module Server
452
511
  end
453
512
  # newrepos is an array of repos to be tracked
454
513
  newrepos.each do |e|
455
- # append the repo and the newest commit message to the repos and
456
- # commit messages array, then inform the client of the newest
457
- # commit message
458
- commit_msg = get_commit_msg(e)
459
- # if the commit_msg is non-false, don't do anything, otherwise 'next'
460
- commit_msg ? nil : next
461
- @ary_commits_repos << e << commit_msg
462
- # and append the repo to the hubeye_tracker array
463
- @hubeye_tracker << e
514
+ # append the repo name and the commit hash to the hubeye tracker
515
+ # array, then inform the client of the newest commit message
516
+ username, repo = e.split '/'
517
+ gh_user = User.find(username)
518
+ gh_repo = gh_user.repository repo
519
+ new_commit = gh_repo.commits.first
520
+ @hubeye_tracker.try_append_or_replace!(e, new_commit)
464
521
  end
465
- @ary_commits_repos.uniq!
466
- @hubeye_tracker.uniq!
467
-
468
- @socket.puts "Loaded #{$2}.\nTracking:\n#{show_repos_pretty()}"
522
+ @socket.puts "Loaded #{$2}.\nTracking:\n#{@hubeye_tracker.eyeing.join ', '}"
469
523
  else
470
524
  # no repo file with that name
471
525
  @socket.puts("No file to load from")
@@ -522,46 +576,18 @@ module Server
522
576
  end # end of input#each
523
577
  # flatten the newrepos array because it contains arrays
524
578
  newrepos.flatten!
525
- newrepos.each do |repo|
526
- commit_msg = get_commit_msg(repo)
527
- commit_msg ? nil : next
528
- @ary_commits_repos << repo << commit_msg
529
- @hubeye_tracker << repo
579
+ newrepos.each do |e|
580
+ username, repo = e.split '/'
581
+ gh_user = User.find(username)
582
+ gh_repo = gh_user.repository repo
583
+ new_commit = gh_repo.commits.first
584
+ @hubeye_tracker.try_append_or_replace!(e, new_commit)
530
585
  end
531
- @ary_commits_repos.uniq!
532
- @hubeye_tracker.uniq!
533
586
  else
534
587
  raise ArgumentError.new "#{input} must be array-like"
535
588
  end
536
589
  end
537
590
 
538
-
539
- # helper method to get commit message for a
540
- # single repo
541
- def get_commit_msg(remote_repo)
542
- begin
543
- @doc = Nokogiri::HTML(open("https://github.com#{'/' + remote_repo}"))
544
- rescue
545
- return nil
546
- end
547
- # returns the commit message
548
- commit_msg = parse_msg(@doc)
549
- end
550
-
551
-
552
- def show_repos_pretty
553
- pretty_repos = ""
554
- @ary_commits_repos.each do |e|
555
- if @ary_commits_repos.index(e).even?
556
- pretty_repos += e + "\n"
557
- else
558
- pretty_repos += " " + e + "\n"
559
- end
560
- end
561
- pretty_repos
562
- end
563
-
564
-
565
591
  def hook_list
566
592
  if @input =~ %r{hook list}
567
593
  unless @hook_cmds.nil? || @hook_cmds.empty?
@@ -597,7 +623,7 @@ remote: #{remote}
597
623
  # they're tracking
598
624
  def tracking_list
599
625
  if @input =~ /\Atracking\s*\Z/
600
- list = show_repos_pretty
626
+ list = @hubeye_tracker.eyeing.join ', '
601
627
  @socket.puts(list)
602
628
  throw(:next)
603
629
  else
@@ -648,24 +674,13 @@ remote: #{remote}
648
674
  else
649
675
  @username, @repo_name = "#{@username}/#{$1}".split('/')
650
676
  end
651
-
652
- begin
653
- index_found = @ary_commits_repos.index("#{@username}/#{@repo_name}")
654
- if index_found
655
- # consecutive indices in the array
656
- for i in 1..2
657
- @ary_commits_repos.delete_at(index_found)
658
- end
659
- @hubeye_tracker.delete("#{@username}/#{@repo_name}")
660
- @socket.puts("Stopped watching repository #{@username}/#{@repo_name}")
661
- sleep 0.5
662
- throw(:next)
663
- else
664
- @socket.puts("Repository #{@username}/#{@repo_name} not currently being watched")
665
- throw(:next)
666
- end
667
- rescue
668
- @socket.puts($!)
677
+ rm = @hubeye_tracker.rm_repo("#{@username}/#{@repo_name}")
678
+ if rm
679
+ @socket.puts("Stopped watching repository #{@username}/#{@repo_name}")
680
+ sleep 0.5
681
+ throw(:next)
682
+ else
683
+ @socket.puts("Repository #{@username}/#{@repo_name} not currently being watched")
669
684
  throw(:next)
670
685
  end
671
686
  else
@@ -690,84 +705,49 @@ remote: #{remote}
690
705
  @repo_name = @input
691
706
  end
692
707
 
693
-
694
- def get_github_doc(full_repo_path)
695
- begin
696
- # if adding a repo with another username
697
- @doc = Nokogiri::HTML(open("https://github.com#{full_repo_path}"))
698
- rescue OpenURI::HTTPError
699
- @socket.puts("Not a Github repository!")
700
- throw(:next)
701
- rescue URI::InvalidURIError
702
- @socket.puts("Not a valid URI")
703
- throw(:next)
704
- end
705
- end
706
-
707
-
708
708
  def parse_doc
709
- # get commit msg
710
- @commit_msg = parse_msg(@doc)
711
- # get committer
712
- @committer = parse_committer()
713
-
709
+ @full_repo_name = "#{@username}/#{@repo_name}"
710
+ begin
711
+ gh_user = User.find(@username)
712
+ gh_repo = gh_user.repository @repo_name
713
+ rescue ArgumentError, Octopi::NotFound
714
+ #Octopi library's User.find ArgumentError
715
+ @socket.puts "Not a Github repository name"
716
+ throw :next
717
+ end
718
+ new_commit = gh_repo.commits.first
719
+ change_status = @hubeye_tracker.try_append_or_replace!(@full_repo_name, new_commit)
720
+ # get commit info
721
+ commit_msg = new_commit.message
722
+ committer = new_commit.author['name']
723
+ url = "https://www.github.com#{new_commit.url[0..-30]}"
724
+ msg = "#{commit_msg}\n=> #{committer}"
714
725
  # new repo to track
715
- full_repo_name = "#{@username}/#{@repo_name}"
716
- if !@ary_commits_repos.include?(full_repo_name)
717
- @ary_commits_repos << full_repo_name
718
- @hubeye_tracker << full_repo_name
719
- @ary_commits_repos << @commit_msg
720
- # get commit info
721
- @info = parse_info()
722
- @msg = "#{@commit_msg} => #{@committer}".gsub(/\(author\)/, '')
726
+ if change_status[:add]
723
727
  # log the fact that the user added a repo to be tracked
724
- Logger.log("Added to tracker: #{@ary_commits_repos[-2]} (#{NOW})")
728
+ Logger.log("Added to tracker: #{@full_repo_name} (#{NOW})")
725
729
  # show the user, via the client, the info and commit msg for the commit
726
- @socket.puts("#{@info}\n#{@msg}")
730
+ @socket.puts("#{msg}\n#{url}")
727
731
 
728
732
  # new commit to tracked repo
729
- elsif !@ary_commits_repos.include?(@commit_msg)
733
+ elsif change_status[:replace]
734
+ change_msg = "New commit on #{@full_repo_name}\n"
735
+ change_msg << "#{msg}\n#{url}"
736
+ @socket.puts(change_msg)
730
737
  begin
731
- index_of_msg = @ary_commits_repos.index(@username + "/" + @repo_name) + 1
732
- @ary_commits_repos.delete_at(index_of_msg)
733
- @ary_commits_repos.insert(index_of_msg - 1, @commit_msg)
734
-
735
738
  # log to the logfile and tell the client
736
739
  if @daemonized
737
- Logger.log_change(@repo_name, @commit_msg, @committer,
738
- :include_socket => true)
740
+ Logger.log_change(@full_repo_name, commit_msg, committer)
739
741
  else
740
- Logger.log_change(@repo_name, @commit_msg, @committer,
741
- :include_socket => true, :include_terminal => true)
742
+ Logger.log_change(@full_repo_name, commit_msg, committer,
743
+ :include_terminal => true)
742
744
  end
743
745
  rescue
744
- @socket.puts($!)
746
+ throw :next
745
747
  end
746
748
  else
747
749
  # no change to the tracked repo
748
- @socket.puts("Repository #{@repo_name} has not changed")
749
- end
750
- end
751
-
752
-
753
- def parse_msg(html_doc)
754
- # get commit msg
755
- html_doc.xpath('//div[@class = "message"]/pre').each do |node|
756
- return commit_msg = node.text
757
- end
758
- end
759
-
760
-
761
- def parse_committer
762
- @doc.xpath('//div[@class = "actor"]/div[@class = "name"]').each do |node|
763
- return committer = node.text
764
- end
765
- end
766
-
767
-
768
- def parse_info
769
- @doc.xpath('//div[@class = "machine"]').each do |node|
770
- return info = node.text.gsub(/\n/, '').gsub(/tree/, "\ntree").gsub(/parent.*?(\w)/, "\nparent \\1").strip!
750
+ @socket.puts("Repository #{@full_repo_name} has not changed")
771
751
  end
772
752
  end
773
753
 
@@ -776,7 +756,7 @@ end # of Server module
776
756
  class HubeyeServer
777
757
  include Server
778
758
 
779
- def initialize(debug=false)
759
+ def initialize(debug=true)
780
760
  @debug = debug
781
761
  end
782
762
 
data/test/runner.rb CHANGED
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  # environment file
4
- require File.join(File.dirname(__FILE__), "/../lib/environment")
4
+ require File.join(File.expand_path(File.dirname(__FILE__) + '/..'), "lib/environment")
5
5
 
6
6
  # test/unit
7
7
  require 'test/unit'
8
8
 
9
9
  # test files
10
10
  require_relative 'environment'
11
- require File.join(File.dirname(__FILE__), "/../lib/notification/notification")
11
+ require File.join(File.expand_path(File.dirname(__FILE__) + '/..'), "lib/notification/notification")
12
12
  require_relative "notification"
13
13
  require Environment::LIBDIR + '/config/parser'
14
14
  require_relative "config_parser"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hubeye
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-09-05 00:00:00.000000000Z
12
+ date: 2011-10-04 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: nokogiri
16
- requirement: &71785010 !ruby/object:Gem::Requirement
15
+ name: octopi
16
+ requirement: &86576300 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,7 +21,7 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *71785010
24
+ version_requirements: *86576300
25
25
  description: Github repository commit watcher -- keep your eye on new commits from
26
26
  multiple repos through an interactive CLI
27
27
  email: luke.gru@gmail.com
@@ -42,7 +42,7 @@ files:
42
42
  - lib/environment.rb
43
43
  - lib/helpers/time.rb
44
44
  - bin/hubeye
45
- - README.md.html
45
+ - Rakefile
46
46
  - README.md
47
47
  - VERSION.rb
48
48
  - LICENSE
data/README.md.html DELETED
@@ -1,212 +0,0 @@
1
- <h1>Hubeye</h1>
2
-
3
- <p><br />
4
- Keep track of repositories on Github, get notified when they change and<br />
5
- (optionally) run local system commands when new commits come in to Github.<br />
6
- <br /></p>
7
-
8
- <p>Hubeye is composed of a client and server. Once the server is run,<br />
9
- you can connect to it via the client. Once connected, you'll be<br />
10
- prompted by a '>'. Type the name of a Github repository.</p>
11
-
12
- <p>Example: (what the user enters is preceded by the prompt)</p>
13
-
14
- <pre><code>&gt;hubeye
15
- commit 77b82b54044c16751228
16
- tree 8ce18af1461b5c741003
17
- parent ea63fe317fe58dff1c95
18
- log tracking info for repos on client quit =&gt; luke-gru
19
- </code></pre>
20
-
21
- <p>What you see is the latest commit reference, tree reference and parent<br />
22
- commit reference on Github for that repository. Note that the user did<br />
23
- not type a username. This is because the user defined a username in his<br />
24
- ~/.hubeye/hubeyerc file.</p>
25
-
26
- <h2>Starting Hubeye</h2>
27
-
28
- <p>To start the server:</p>
29
-
30
- <pre><code>&gt;hubeye -s
31
- </code></pre>
32
-
33
- <p>or just</p>
34
-
35
- <pre><code>&gt;hubeye
36
- </code></pre>
37
-
38
- <p>This starts the server as a daemonized process. To run the server in<br />
39
- your terminal (on <b>t</b>op):</p>
40
-
41
- <pre><code>&gt;hubeye -st
42
- </code></pre>
43
-
44
- <p>Hubeye runs on port 2000 be default. Change the port like this:</p>
45
-
46
- <pre><code>&gt;hubeye -sp 9001
47
- </code></pre>
48
-
49
- <p>To connect with the client:</p>
50
-
51
- <pre><code>&gt;hubeye -c
52
- </code></pre>
53
-
54
- <p>For more options:</p>
55
-
56
- <pre><code>&gt;hubeye -h
57
- </code></pre>
58
-
59
- <h3>~/.hubeye/hubeyerc</h3>
60
-
61
- <pre><code>username: luke-gru
62
- </code></pre>
63
-
64
- <p>This allows the user to type a repository name only, and to receive<br />
65
- information regarding that <i>username</i>'s repository. The username<br />
66
- should be a valid Github username.</p>
67
-
68
- <h3>Keeping track of repositories</h3>
69
-
70
- <p>Hubeye doesn't actually track any repositories unless you disconnect<br />
71
- from the server and leave the server running. This can be done by:</p>
72
-
73
- <pre><code>&gt;quit
74
- Bye!
75
- </code></pre>
76
-
77
- <p>If Hubeye has any repos to watch (track), it will watch Github for changes.<br />
78
- It can keep track of as many repos as you want; just keep typing<br />
79
- them in. If Hubeye finds a change to a repo, it will notify you of the<br />
80
- changes using your Desktop notification system (libnotify, growl). It will<br />
81
- also log the changes to your $HOME/.hubeye/log file. If the server is run<br />
82
- in a terminal (-t option), the changes will also be logged to the terminal.<br
83
- /></p>
84
-
85
- <p>To track your own repository, start the client in the root directory<br />
86
- of your local git repo:</p>
87
-
88
- <pre><code>&gt;.
89
- </code></pre>
90
-
91
- <p>This only works if a <i>username</i> is added to the hubeyerc, and if the<br />
92
- Github repository name is the same as the local root directory name.<br />
93
- ie: '.' put in '/home/luke/code/hubeye' would track https://www.github.com/
94
- luke-gru/hubeye<br />
95
- if <i>username</i> was set to luke-gru.<br /></p>
96
-
97
- <p>You can add another user's repo like this:</p>
98
-
99
- <pre><code>&gt;rails/rails
100
- </code></pre>
101
-
102
- <p>This adds https://github.com/rails/rails to the watch list.<br />
103
- Hubeye does not remove a repo from the watch list unless explicitly<br />
104
- told to do so:</p>
105
-
106
- <pre><code>&gt;rm luke-gru/hubeye
107
- </code></pre>
108
-
109
- <p>To see a list of all repos (with recent commit messages) in the watch (track) list:</p>
110
-
111
- <pre><code>&gt;tracking
112
- </code></pre>
113
-
114
- <h3>Desktop Notification</h3>
115
-
116
- <p><i>On Linux: install libnotify-bin. On Mac: install growl (if not already installed).<br />
117
- The autotest gem is needed for Desktop notification to work in both
118
- cases.</i><br /></p>
119
-
120
- <h3>Shutting down and persistence between sessions</h3>
121
-
122
- <pre><code>&gt;shutdown
123
- </code></pre>
124
-
125
- <p>Next time you start up the server, the watch list will be empty<br />
126
- (and so will the log file). In order to have a default watch list:</p>
127
-
128
- <p><i>~/.hubeye/hubeyerc</i></p>
129
-
130
- <pre><code>track: rails/rails, dchelimsky/rspec
131
- </code></pre>
132
-
133
- <p>These will be watched automatically when starting up the server.<br /></p>
134
-
135
- <p>A way to interactively save all currently tracked repositories:</p>
136
-
137
- <pre><code>&gt;save repos as my_work_repos
138
- </code></pre>
139
-
140
- <p>And then load any time (even after a shutdown; next session, next week, etc...)</p>
141
-
142
- <pre><code>&gt;load repos my_work_repos
143
- </code></pre>
144
-
145
- <h3>Working with hooks</h3>
146
-
147
- <pre><code>&gt;hook add rails/rails dir: /path/to/local/rails cmd: git pull origin master
148
- </code></pre>
149
-
150
- <p>When <b>https://www.github.com/rails/rails</b> changes, a process will start,
151
- <br />
152
- change to the selected directory and execute the command. The <i>(dir: /my/dir)
153
- <br />
154
- </i> part is optional, and when ignored won't change directories. In this
155
- case,
156
- <br />
157
- the directory will be where the hubeye server was originally
158
- started from.<br /></p>
159
-
160
- <p>To see all currently loaded hooks:</p>
161
-
162
- <pre><code>&gt;hook list
163
- </code></pre>
164
-
165
- <p>To save all hooks for next sessions (after a server shutdown)</p>
166
-
167
- <pre><code>&gt;save hooks as weekend_projects_hooks
168
- </code></pre>
169
-
170
- <p>Then, next weekend:</p>
171
-
172
- <pre><code>&gt;load hooks weekend_projects_hooks
173
- </code></pre>
174
-
175
- <p>These hooks, of course, will only really do anything if the repositories they
176
- <br />
177
- are hooked to are currently being watched. This is not done automatically.</p>
178
-
179
- <h3>All ~/.hubeyerc configurations</h3>
180
-
181
- <p>When the server is started, the options are set here.</p>
182
-
183
- <pre><code>username: luke-gru
184
- track: username/reponame, username2/reponame2, myreponame
185
- oncearound = 90
186
- load hooks: myhook1, myworkhooks
187
- load repos: workprojects, funprojects
188
- desktop notification: on/off
189
- </code></pre>
190
-
191
- <p><i>username</i>: username used for Github URLS when the full path is not
192
- given<br />
193
- inside of the client.<br /></p>
194
-
195
- <p><i>track</i>: default repositories to watch for changes upon server start<br /></p>
196
-
197
- <p><i>oncearound</i>: number of seconds before completing a check of every repo in<br />
198
- the watch list for changes<br /></p>
199
-
200
- <p><i>load hooks</i>: load hooks on server start. To see how to save hooks in the
201
- <br />
202
- client, see the <i>Working with hooks</i> section<br /></p>
203
-
204
- <p><i>load repos</i>: load repos on server start. To see how to save repos in the
205
- <br />
206
- client, see the <i>Shutting down and persistence between sessions</i> section.
207
- <br /></p>
208
-
209
- <p><i>desktop notification</i>: whether to notify of repo changes using libnotify
210
- <br />
211
- or growl. This is set to <i>on</i> by default. However, if no notification<br />
212
- system is found, it is ignored.</p>