class PingPongPear
Constants
- SERVICE
- VERSION
Attributes
logger[R]
peers[R]
pull_requests[R]
Public Class Methods
new()
click to toggle source
# File lib/ping_pong_pear.rb, line 26 def initialize @pull_requests = Queue.new @send_pull_requests = [] @peers = Set.new @logger = Logger.new $stdout end
run(args)
click to toggle source
# File lib/ping_pong_pear.rb, line 14 def self.run args new.public_send args.first, *args.drop(1) rescue cmds = public_instance_methods(false).find_all { |x| instance_method(x).arity < 0 } $stderr.puts "USAGE: pingpongpear #{cmds}" exit 1 end
Public Instance Methods
clone(name, dir = nil)
click to toggle source
# File lib/ping_pong_pear.rb, line 82 def clone name, dir = nil browser = DNSSD::Service.browse SERVICE browser.each do |response| r = response.resolve if r.text_record['project'] == name url = "http://#{r.target}:#{r.port}" system "git clone #{Shellwords.escape(url)} #{dir || Shellwords.escape(name)}" break end end end
start(name = File.basename(Dir.pwd))
click to toggle source
# File lib/ping_pong_pear.rb, line 33 def start name = File.basename(Dir.pwd) post_commit_hook = '.git/hooks/post-commit' pidfile = '.git/pingpongpear.pid' if File.exist? pidfile raise "Another instance of Ping Pong Pear is running" else File.open(pidfile, 'w') { |f| f.write $$ } end File.open(post_commit_hook, 'w') { |f| f.write <<-eof #!/bin/sh git update-server-info kill -INFO $(cat #{pidfile}) eof } File.chmod 0755, post_commit_hook system "git update-server-info" at_exit { File.unlink pidfile File.unlink post_commit_hook } identifier = make_ident name logger.info "SEND THIS TO YOUR PEAR `git clone #{name}`" logger.info "CTRL-T sends pull requests to all peers" logger.debug "MY PROJECT NAME: #{name} IDENT: #{identifier}" server = start_server pull_requests http_port = server.listeners.map { |x| x.addr[1] }.first hostname = Socket.gethostname discover identifier, name, peers process_pull_requests pull_requests t = process_send_pull_requests @send_pull_requests trap('INFO') { send_pull_requests peers, hostname, http_port t.wakeup } advertise(identifier, name, hostname, http_port).each { |x| x } end
Private Instance Methods
advertise(ident, name, hostname, http_port)
click to toggle source
# File lib/ping_pong_pear.rb, line 113 def advertise ident, name, hostname, http_port txt = DNSSD::TextRecord.new 'project' => name DNSSD::Service.register ident, SERVICE, nil, http_port, hostname, txt end
discover(ident, name, peers)
click to toggle source
# File lib/ping_pong_pear.rb, line 122 def discover ident, name, peers browser = DNSSD::Service.browse SERVICE browser.async_each do |response| if response.flags.to_i > 0 logger.debug "SAW: #{response.name}" unless response.name == ident r = response.resolve if r.text_record['project'] == name logger.info "PEER: #{response.name}" peers << [response.name, r.target, r.port] end end else peers.delete_if { |id, _, _| id == response.name } logger.info "REMOVED: #{response.name}" end end end
make_ident(name)
click to toggle source
# File lib/ping_pong_pear.rb, line 118 def make_ident name "#{name} (#{SecureRandom.hex.slice(0, 4)})" end
process_pull_requests(pull_requests)
click to toggle source
# File lib/ping_pong_pear.rb, line 163 def process_pull_requests pull_requests Thread.new do while pr = pull_requests.pop url = "http://#{pr.join(':')}" logger.debug "git pull #{Shellwords.escape(url)}" system "git pull #{Shellwords.escape(url)}" end end end
process_send_pull_requests(requests)
click to toggle source
# File lib/ping_pong_pear.rb, line 147 def process_send_pull_requests requests Thread.new do loop do requests.each do |pr| host, port, http_host, http_port = *pr http = Net::HTTP.new host, port request = Net::HTTP::Post.new '/pull' request.set_form_data 'host' => http_host, 'port' => http_port http.request request end requests.clear Thread.stop end end end
send_pull_requests(peers, http_host, http_port)
click to toggle source
# File lib/ping_pong_pear.rb, line 141 def send_pull_requests peers, http_host, http_port peers.each do |_, host, port| @send_pull_requests << [host, port, http_host, http_port] end end
start_server(pull_requests)
click to toggle source
# File lib/ping_pong_pear.rb, line 96 def start_server pull_requests server = WEBrick::HTTPServer.new Port: 0, DocumentRoot: '.git', Logger: logger server.mount_proc '/pull' do |req, res| host = req.query['host'] port = req.query['port'] if host && port logger.info "ADDED PR: #{host}:#{port}" pull_requests << [host, port.to_i] end res.body = '' end Thread.new { server.start } server end