-
Notifications
You must be signed in to change notification settings - Fork 4
/
gemjour.rb
142 lines (108 loc) · 3.15 KB
/
gemjour.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
$:.unshift(File.dirname(__FILE__)) unless
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
require "dnssd"
require "set"
require "gemjour/version"
Thread.abort_on_exception = true
module Gemjour
Server = Struct.new(:name, :host, :port)
PORT = 8808
SERVICE = "_rubygems._tcp"
def self.usage
puts <<-HELP
Usage:
serve [<name>] [<port>]
Start up a gem server as <name> on <port>. <name> is your username
by default, and <port> is 8088. If you want to use the default <name>,
pass it as "".
install <server> <gem>
Installs <gem> from <server>. <server> is the name the server announces
itself as.
list
List all available gem servers.
show <server>
List all gems available from <server>
HELP
end
def self.find(name)
host = nil
waiting = Thread.current
service = DNSSD.browse(SERVICE) do |reply|
if name === reply.name
DNSSD.resolve(reply.name, reply.type, reply.domain) do |rr|
host = Server.new(reply.name, rr.target, rr.port)
waiting.run
end
end
end
sleep 5
service.stop
host
end
def self.list(name = nil)
return show(name) if name
hosts = []
waiting = Thread.current
service = DNSSD.browse(SERVICE) do |reply|
DNSSD.resolve(reply.name, reply.type, reply.domain) do |rr|
host = Server.new(reply.name, rr.target, rr.port)
unless hosts.include? host
puts "#{host.name} (#{host.host}:#{host.port})"
hosts << host
end
end
end
sleep 5
service.stop
end
def self.show(name)
host = find(name)
unless host
puts "ERROR: Unable to find server '#{name}'"
return
end
system "gem list -r --source=http://#{host.host}:#{host.port}"
end
def self._diff(name)
host = find(name)
unless host
puts "ERROR: Unable to find server named '#{name}'"
return
end
require "tempfile"
local_gems, remote_gems = Tempfile.new("local_gems"), Tempfile.new("remote_gems")
local_gems.print(`gem list --no-versions --no-verbose`)
local_gems.close
remote_gems.print(`gem list --no-versions --no-verbose -r --source=http://#{host.host}:#{host.port}`)
remote_gems.close
`diff -u #{local_gems.path} #{remote_gems.path}`
end
def self.diff(name)
puts _diff(name)
end
def self.install_diff(name)
gem_diff = _diff(name)
return unless gem_diff
gem_diff.scan(/^\+([\w_\-]+)/) do |match|
install(name, match)
end
end
def self.install(name, gem)
host = find(name)
unless host
puts "ERROR: Unable to find server named '#{user}'"
return
end
puts "Installing gem '#{gem}' from #{host.host}:#{host.port}"
system "gem install #{gem} -s http://#{host.host}:#{host.port}"
end
def self.serve(name="", port=PORT)
name = ENV['USER'] if name.empty?
tr = DNSSD::TextRecord.new
tr['description'] = "#{name}'s gem server"
DNSSD.register(name, SERVICE, "local", port, tr.encode) do |reply|
puts "Serving gems under name '#{name}'..."
end
system "gem server --port=#{port} -q > /dev/null 2>&1"
end
end