apt_control 0.3.2 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/apt_control.rb +3 -1
- data/lib/apt_control/build_archive.rb +3 -3
- data/lib/apt_control/cli.rb +49 -4
- data/lib/apt_control/cli/include.rb +6 -15
- data/lib/apt_control/cli/status.rb +23 -27
- data/lib/apt_control/cli/watch.rb +58 -29
- data/lib/apt_control/control_file.rb +6 -6
- data/lib/apt_control/includer.rb +27 -0
- data/lib/apt_control/jabber.rb +117 -0
- data/lib/apt_control/package_states.rb +59 -0
- data/lib/apt_control/version.rb +1 -1
- metadata +130 -134
- data/lib/apt_control/notify.rb +0 -37
data/lib/apt_control.rb
CHANGED
@@ -6,10 +6,12 @@ require 'logger'
|
|
6
6
|
module AptControl
|
7
7
|
|
8
8
|
require 'apt_control/exec'
|
9
|
-
require 'apt_control/
|
9
|
+
require 'apt_control/jabber'
|
10
10
|
require 'apt_control/control_file'
|
11
11
|
require 'apt_control/apt_site'
|
12
12
|
require 'apt_control/build_archive'
|
13
|
+
require 'apt_control/package_states'
|
14
|
+
require 'apt_control/includer'
|
13
15
|
|
14
16
|
class Version
|
15
17
|
include Comparable
|
@@ -66,9 +66,9 @@ module AptControl
|
|
66
66
|
# watch the build directory, adding new packages and versions to the
|
67
67
|
# in-memory list as it sees them. Yields to the given block with the
|
68
68
|
# package and the new version
|
69
|
-
def watch(&block)
|
69
|
+
def watch(fs_listener_factory, &block)
|
70
70
|
@logger.info("Watching for new changes files in #{@dir}")
|
71
|
-
|
71
|
+
fs_listener_factory.new(@dir, /\.changes$/) do |modified, added, removed|
|
72
72
|
added.each do |fname|
|
73
73
|
begin
|
74
74
|
fname = File.basename(fname)
|
@@ -89,7 +89,7 @@ module AptControl
|
|
89
89
|
next
|
90
90
|
end
|
91
91
|
end
|
92
|
-
end
|
92
|
+
end.start.join
|
93
93
|
end
|
94
94
|
|
95
95
|
class Package
|
data/lib/apt_control/cli.rb
CHANGED
@@ -39,13 +39,17 @@ module AptControl
|
|
39
39
|
end
|
40
40
|
|
41
41
|
module Common
|
42
|
+
# FIXME tidy up with some meta magic
|
43
|
+
def package_states ; ancestor(Root).package_states ; end
|
44
|
+
def includer ; ancestor(Root).includer ; end
|
42
45
|
def apt_site ; ancestor(Root).apt_site ; end
|
43
46
|
def control_file ; ancestor(Root).control_file ; end
|
44
47
|
def build_archive ; ancestor(Root).build_archive ; end
|
45
|
-
def notifier ; ancestor(Root).
|
48
|
+
def notifier ; ancestor(Root).notifier ; end
|
46
49
|
def notify(msg) ; ancestor(Root).notify(msg) ; end
|
47
50
|
def validate_config! ; ancestor(Root).validate_config! ; end
|
48
51
|
def logger ; ancestor(Root).logger ; end
|
52
|
+
def fs_listener_factory ; ancestor(Root).fs_listener_factory ; end
|
49
53
|
|
50
54
|
def each_package_state(&block)
|
51
55
|
control_file.distributions.each do |dist|
|
@@ -75,6 +79,7 @@ module AptControl
|
|
75
79
|
config :jabber_id, "Jabber ID for notifications", :required => false
|
76
80
|
config :jabber_password, "Password for connecting to jabber server", :required => false
|
77
81
|
config :jabber_chatroom_id, "Jabber ID for chatroom to send notifications to", :required => false
|
82
|
+
config :disable_inotify, "Set to true to disable use of inotify", :required => false
|
78
83
|
|
79
84
|
description """
|
80
85
|
Move packages from an archive in to your reprepro style apt repository.
|
@@ -141,6 +146,12 @@ YAML file containing a single hash of key value/pairs for each option.
|
|
141
146
|
end
|
142
147
|
end
|
143
148
|
|
149
|
+
def package_states
|
150
|
+
@package_states ||= PackageStates.new(apt_site: apt_site,
|
151
|
+
build_archive: build_archive,
|
152
|
+
control_file: control_file)
|
153
|
+
end
|
154
|
+
|
144
155
|
def apt_site
|
145
156
|
@apt_site ||= AptSite.new(config[:apt_site_dir], logger)
|
146
157
|
end
|
@@ -154,14 +165,48 @@ YAML file containing a single hash of key value/pairs for each option.
|
|
154
165
|
end
|
155
166
|
|
156
167
|
def notifier
|
157
|
-
@notify ||=
|
168
|
+
@notify ||= Jabber.new(:jid => config[:jabber_id], :logger => logger,
|
158
169
|
:password => config[:jabber_password], :room_jid => config[:jabber_chatroom_id])
|
159
170
|
end
|
160
171
|
|
172
|
+
def includer
|
173
|
+
@includer ||= Includer.new(apt_site, build_archive)
|
174
|
+
end
|
175
|
+
|
176
|
+
class FSListenerFactory
|
177
|
+
|
178
|
+
attr_reader :disable_inotify
|
179
|
+
|
180
|
+
def initialize(options={})
|
181
|
+
@disable_inotify = options[:disable_inotify]
|
182
|
+
end
|
183
|
+
|
184
|
+
def new(dir, pattern, &on_change)
|
185
|
+
Listen.to(dir).filter(pattern).tap do |listener|
|
186
|
+
if disable_inotify
|
187
|
+
listener.force_polling(true)
|
188
|
+
listener.polling_fallback_message(false)
|
189
|
+
end
|
190
|
+
|
191
|
+
listener.change(&on_change)
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
def fs_listener_factory
|
197
|
+
@fs_listener_factory ||= FSListenerFactory.new(
|
198
|
+
disable_inotify: config[:disable_inotify].to_s == 'true')
|
199
|
+
end
|
200
|
+
|
161
201
|
def notify(message)
|
162
202
|
logger.info("notify: #{message}")
|
163
|
-
return unless config[:jabber_enabled]
|
164
|
-
|
203
|
+
return unless config[:jabber_enabled].to_s == 'true'
|
204
|
+
begin
|
205
|
+
notifier.send_message(message)
|
206
|
+
rescue => e
|
207
|
+
logger.error("Unable to send notification to jabber: #{e}")
|
208
|
+
logger.error(e)
|
209
|
+
end
|
165
210
|
end
|
166
211
|
end
|
167
212
|
end
|
@@ -10,21 +10,12 @@ that the control file will allow"""
|
|
10
10
|
def run
|
11
11
|
validate_config!
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
if rule.upgradeable?(included, available)
|
21
|
-
version = rule.upgradeable_to(available).max
|
22
|
-
if options[:noop]
|
23
|
-
puts "I want to upgrade from #{included} to version #{version} of #{rule.package_name}"
|
24
|
-
else
|
25
|
-
apt_site.include!(dist.name, build_archive.changes_fname(rule.package_name, version))
|
26
|
-
end
|
27
|
-
end
|
13
|
+
includer.perform_for_all(package_states) do |state, version|
|
14
|
+
if options[:noop]
|
15
|
+
puts "#{state.dist.name} #{state.package_name} #{state.included} => #{version}"
|
16
|
+
false
|
17
|
+
else
|
18
|
+
true
|
28
19
|
end
|
29
20
|
end
|
30
21
|
end
|
@@ -9,33 +9,29 @@ module AptControl::CLI
|
|
9
9
|
def run
|
10
10
|
validate_config!
|
11
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
|
-
puts " available - #{available && available.join(', ')}"
|
36
|
-
puts " satisfied - #{satisfied}"
|
37
|
-
puts " upgradeable - #{upgradeable}"
|
38
|
-
end
|
12
|
+
if options[:machine_readable]
|
13
|
+
package_states.each do |state|
|
14
|
+
fields = [
|
15
|
+
state.dist.name,
|
16
|
+
state.package_name,
|
17
|
+
"(#{state.rule.restriction} #{state.rule.version})",
|
18
|
+
"#{state.includeable? ? 'I' : '.'}#{state.satisfied? ? 'S' : '.'}",
|
19
|
+
"included=#{state.included || '<none>'}",
|
20
|
+
"available=#{state.available? ? state.available.join(', ') : '<none>'} "
|
21
|
+
]
|
22
|
+
puts fields.join(' ')
|
23
|
+
end
|
24
|
+
else
|
25
|
+
last_dist = nil
|
26
|
+
package_states.each do |state|
|
27
|
+
puts state.dist.name if last_dist != state.dist
|
28
|
+
last_dist = state.dist
|
29
|
+
puts " #{state.package_name}"
|
30
|
+
puts " rule - #{state.rule.restriction} #{state.rule.version}"
|
31
|
+
puts " included - #{state.included}"
|
32
|
+
puts " available - #{state.available.join(', ')}"
|
33
|
+
puts " satisfied - #{state.satisfied?}"
|
34
|
+
puts " includeable - #{state.includeable?}"
|
39
35
|
end
|
40
36
|
end
|
41
37
|
end
|
@@ -55,40 +55,69 @@ has the usual set of options for running as an init.d style daemon.
|
|
55
55
|
end
|
56
56
|
|
57
57
|
def start_watching
|
58
|
+
threads = [
|
59
|
+
watch_control_in_new_thread,
|
60
|
+
watch_build_archive_in_new_thread
|
61
|
+
]
|
62
|
+
|
63
|
+
notify("apt_control watcher is up, waiting for changes to control file and new packages...")
|
64
|
+
|
65
|
+
# these should never exit, so stop main thread exiting by joining to them
|
66
|
+
threads.each(&:join)
|
67
|
+
end
|
68
|
+
|
69
|
+
def watch_control_in_new_thread
|
58
70
|
# update the all the rules if the control file changes
|
59
|
-
Thread.new
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
if rule.upgradeable?(included, [new_version])
|
70
|
-
if options[:noop]
|
71
|
-
notify("package #{package.name} can be upgraded to #{new_version} on #{dist.name} (noop)")
|
72
|
-
else
|
73
|
-
# FIXME error handling here, please
|
74
|
-
begin
|
75
|
-
apt_site.include!(dist.name, build_archive.changes_fname(rule.package_name, new_version))
|
76
|
-
notify("included package #{package.name}-#{new_version} in #{dist.name}")
|
77
|
-
rescue => e
|
78
|
-
notify("Failed to include package #{package.name}-#{new_version}, check log for more details")
|
79
|
-
logger.error("failed to include package #{package.name}")
|
80
|
-
logger.error(e)
|
81
|
-
end
|
71
|
+
Thread.new do
|
72
|
+
begin
|
73
|
+
control_file.watch(fs_listener_factory) do
|
74
|
+
notify "Control file reloaded"
|
75
|
+
# FIXME need to do some kind of locking or actor style dev for this
|
76
|
+
# as it looks like there could be some concurrency bugs lurking
|
77
|
+
includer.perform_for_all(package_states) do |package_state, new_version|
|
78
|
+
notify("included package #{package_state.package_name}-#{new_version} in #{package_state.dist.name}")
|
79
|
+
true
|
82
80
|
end
|
83
|
-
dist.name
|
84
|
-
else
|
85
|
-
nil
|
86
81
|
end
|
87
|
-
|
82
|
+
ensure
|
83
|
+
logger.warn("control file watch loop exited")
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def watch_build_archive_in_new_thread
|
89
|
+
Thread.new do
|
90
|
+
begin
|
91
|
+
build_archive.watch(fs_listener_factory) do |package, new_version|
|
92
|
+
handle_new_package(package, new_version)
|
93
|
+
end
|
94
|
+
ensure
|
95
|
+
logger.warn("build archive watch loop exited")
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
88
99
|
|
89
|
-
|
90
|
-
|
100
|
+
def handle_new_package(package, new_version)
|
101
|
+
notify("new package: #{package.name} at #{new_version}")
|
102
|
+
|
103
|
+
matched_states = package_states.select {|s| s.package_name == package.name }
|
104
|
+
|
105
|
+
updated = matched_states.map do |state|
|
106
|
+
if state.includeable_to.max == new_version
|
107
|
+
begin
|
108
|
+
includer.perform_for(state, new_version, options[:noop])
|
109
|
+
notify("included package #{package.name}-#{new_version} in #{state.dist.name}")
|
110
|
+
state.dist.name
|
111
|
+
rescue => e
|
112
|
+
notify("Failed to include package #{package.name}-#{new_version}, check log for more details")
|
113
|
+
logger.error("failed to include package #{package.name}")
|
114
|
+
logger.error(e)
|
115
|
+
end
|
91
116
|
end
|
117
|
+
end.compact
|
118
|
+
|
119
|
+
if updated.size == 0
|
120
|
+
notify("package #{package.name} could not be updated on any distributions")
|
92
121
|
end
|
93
122
|
end
|
94
123
|
end
|
@@ -40,12 +40,12 @@ module AptControl
|
|
40
40
|
|
41
41
|
# Watch the control file for changes, rebuilding
|
42
42
|
# internal data structures when it does
|
43
|
-
def watch(&block)
|
43
|
+
def watch(fs_listener_factory, &block)
|
44
44
|
path = File.expand_path(@path)
|
45
|
-
@logger.info("Watching for changes to #{path}")
|
46
45
|
dir = File.dirname(path)
|
47
46
|
fname = File.basename(path)
|
48
|
-
|
47
|
+
@logger.info("Watching for changes to #{path}")
|
48
|
+
fs_listener_factory.new(dir, /#{Regexp.quote(fname)}/) do |modified, added, removed|
|
49
49
|
begin
|
50
50
|
@logger.info("Change to control file detected...")
|
51
51
|
inifile = IniFile.load(path)
|
@@ -60,7 +60,7 @@ module AptControl
|
|
60
60
|
@logger.error("Error reloading changes: #{e}")
|
61
61
|
@logger.error(e)
|
62
62
|
end
|
63
|
-
end
|
63
|
+
end.start.join
|
64
64
|
end
|
65
65
|
|
66
66
|
class PackageRule
|
@@ -111,14 +111,14 @@ module AptControl
|
|
111
111
|
|
112
112
|
# will return true if a) there is a higher version available than is
|
113
113
|
# included b) any of the available packages satisfy this rule
|
114
|
-
def
|
114
|
+
def includeable?(included, available)
|
115
115
|
return false unless higher_available?(included, available)
|
116
116
|
higher = available.select {|a| a > included }
|
117
117
|
return true if higher.any? {|a| satisfied_by?(a) }
|
118
118
|
end
|
119
119
|
|
120
120
|
# will return the subset of versions from available that satisfy this rule
|
121
|
-
def
|
121
|
+
def includeable_to(available)
|
122
122
|
available.select {|a| satisfied_by?(a) }
|
123
123
|
end
|
124
124
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module AptControl
|
2
|
+
|
3
|
+
# Wraps the common functionality involved in including the latest includeable
|
4
|
+
# package in an apt site
|
5
|
+
class Includer
|
6
|
+
def initialize(apt_site, build_archive)
|
7
|
+
@apt_site = apt_site
|
8
|
+
@build_archive = build_archive
|
9
|
+
end
|
10
|
+
|
11
|
+
def perform_for_all(package_states, &visitor)
|
12
|
+
package_states.each do |state|
|
13
|
+
next unless state.includeable?
|
14
|
+
|
15
|
+
version = state.includeable_to.max
|
16
|
+
perform = (block_given? && yield(state, version)) || true
|
17
|
+
|
18
|
+
perform_for(state, version) if perform
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def perform_for(state, version, noop=false)
|
23
|
+
changes_fname = @build_archive.changes_fname(state.package_name, version)
|
24
|
+
@apt_site.include!(state.dist.name, changes_fname) unless noop
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'xmpp4r/jid'
|
2
|
+
require 'xmpp4r/client'
|
3
|
+
require 'xmpp4r/muc'
|
4
|
+
require 'xmpp4r/muc/helper/simplemucclient'
|
5
|
+
|
6
|
+
module AptControl
|
7
|
+
class Jabber
|
8
|
+
include ::Jabber
|
9
|
+
|
10
|
+
def initialize(options)
|
11
|
+
@jid = options[:jid]
|
12
|
+
@password = options[:password]
|
13
|
+
@room_jid = options[:room_jid]
|
14
|
+
@logger = options[:logger]
|
15
|
+
|
16
|
+
swallow_errors { connect! } unless options[:defer_connect]
|
17
|
+
end
|
18
|
+
|
19
|
+
def send_message(msg)
|
20
|
+
if not_connected?
|
21
|
+
connect!
|
22
|
+
end
|
23
|
+
|
24
|
+
begin
|
25
|
+
attempt_reconnect do
|
26
|
+
@logger.info("sending message to chat room: #{msg}")
|
27
|
+
@muc.send(Message.new(nil, msg))
|
28
|
+
end
|
29
|
+
rescue JabberError => e
|
30
|
+
raise SendError.new("failed to send message to chat room", e)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# execute the block, swallow any Jabber::Error errors it raises, reporting
|
35
|
+
# them to the logger
|
36
|
+
def swallow_errors(jabber_errors_too=false, &block)
|
37
|
+
begin
|
38
|
+
yield(self)
|
39
|
+
rescue Error => e
|
40
|
+
@logger.error("swallowed error: #{e}")
|
41
|
+
@logger.error(e)
|
42
|
+
rescue JabberError => e
|
43
|
+
raise unless jabber_errors_too
|
44
|
+
@logger.error("swallowed error: #{e}")
|
45
|
+
@logger.error(e)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def connected?
|
50
|
+
@client && @client.is_connected? && @muc && @muc.active?
|
51
|
+
end
|
52
|
+
|
53
|
+
def not_connected? ; ! connected? ; end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def attempt_reconnect(&block)
|
58
|
+
begin
|
59
|
+
yield
|
60
|
+
rescue JabberError => e
|
61
|
+
@logger.error("swallowing jabber error: #{e}")
|
62
|
+
@logger.error(e)
|
63
|
+
@logger.error("attempting message send again...")
|
64
|
+
connect!
|
65
|
+
yield
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def connect!
|
70
|
+
# ::Jabber::debug = true
|
71
|
+
begin
|
72
|
+
swallow_errors { @client.disconnect if @client && @client.is_connected? }
|
73
|
+
|
74
|
+
@logger.info("Jabber connecting with jid #{@jid}")
|
75
|
+
@client = Client.new(JID.new(@jid))
|
76
|
+
@client.connect
|
77
|
+
@client.auth(@password)
|
78
|
+
rescue JabberError => e
|
79
|
+
raise ConnectionError.new("error connecting to client", e)
|
80
|
+
end
|
81
|
+
|
82
|
+
begin
|
83
|
+
swallow_errors { @muc.exit("reconnecting") if @muc && @muc.active? }
|
84
|
+
|
85
|
+
@muc = Jabber::MUC::SimpleMUCClient.new(@client)
|
86
|
+
@muc.join(JID.new(@room_jid))
|
87
|
+
@logger.info("joined room #{@room_jid}")
|
88
|
+
rescue JabberError => e
|
89
|
+
raise ConnectionError.new("error joining room", e)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# Thank you to http://rubyforge.org/projects/nestegg for the pattern
|
94
|
+
class Error < StandardError
|
95
|
+
|
96
|
+
attr_reader :cause
|
97
|
+
alias :wrapped_error :cause
|
98
|
+
|
99
|
+
def initialize(msg, cause=nil)
|
100
|
+
@cause = cause
|
101
|
+
super(msg)
|
102
|
+
end
|
103
|
+
|
104
|
+
def set_backtrace(bt)
|
105
|
+
if cause
|
106
|
+
bt << "cause: #{cause.class.name}: #{cause}"
|
107
|
+
bt.concat cause.backtrace
|
108
|
+
end
|
109
|
+
super(bt)
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
class ConnectionError < Error ; end
|
115
|
+
class SendError < Error ; end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module AptControl
|
2
|
+
class PackageStates
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
def initialize(options)
|
6
|
+
@apt_site = options.fetch(:apt_site)
|
7
|
+
@build_archive = options.fetch(:build_archive)
|
8
|
+
@control_file = options.fetch(:control_file)
|
9
|
+
end
|
10
|
+
|
11
|
+
# yield a package state for each entry in the control file
|
12
|
+
def each(&block)
|
13
|
+
@control_file.distributions.each do |dist|
|
14
|
+
dist.package_rules.each do |rule|
|
15
|
+
yield PackageState.new(dist: dist, rule: rule, apt_site: @apt_site,
|
16
|
+
build_archive: @build_archive)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Brings together the state of a particular package in a particular
|
23
|
+
# distribution
|
24
|
+
class PackageState
|
25
|
+
|
26
|
+
attr_reader :dist, :rule
|
27
|
+
|
28
|
+
def initialize(options)
|
29
|
+
@dist = options.fetch(:dist)
|
30
|
+
@rule = options.fetch(:rule)
|
31
|
+
@apt_site = options.fetch(:apt_site)
|
32
|
+
@build_archive = options.fetch(:build_archive)
|
33
|
+
end
|
34
|
+
|
35
|
+
def included
|
36
|
+
@included ||= @apt_site.included_version(dist.name, rule.package_name)
|
37
|
+
end
|
38
|
+
|
39
|
+
def available
|
40
|
+
@available ||= (@build_archive[rule.package_name] || [])
|
41
|
+
end
|
42
|
+
|
43
|
+
def package_name ; rule.package_name ; end
|
44
|
+
def included? ; !! included ; end
|
45
|
+
def available? ; available.any? ; end
|
46
|
+
|
47
|
+
def satisfied?
|
48
|
+
included? && rule.satisfied_by?(included)
|
49
|
+
end
|
50
|
+
|
51
|
+
def includeable?
|
52
|
+
available? && rule.includeable?(included, available)
|
53
|
+
end
|
54
|
+
|
55
|
+
def includeable_to
|
56
|
+
rule.includeable_to(available)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/lib/apt_control/version.rb
CHANGED
metadata
CHANGED
@@ -1,151 +1,159 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: apt_control
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.4.0
|
5
5
|
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 3
|
9
|
-
- 2
|
10
|
-
version: 0.3.2
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Nick Griffiths
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2013-06-10 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
21
15
|
name: popen4
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
hash: 3
|
29
|
-
segments:
|
30
|
-
- 0
|
31
|
-
version: "0"
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
32
22
|
type: :runtime
|
33
|
-
version_requirements: *id001
|
34
|
-
- !ruby/object:Gem::Dependency
|
35
|
-
name: climate
|
36
23
|
prerelease: false
|
37
|
-
|
38
|
-
none: false
|
39
|
-
requirements:
|
40
|
-
- -
|
41
|
-
- !ruby/object:Gem::Version
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: climate
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
46
38
|
type: :runtime
|
47
|
-
version_requirements: *id002
|
48
|
-
- !ruby/object:Gem::Dependency
|
49
|
-
name: inifile
|
50
39
|
prerelease: false
|
51
|
-
|
52
|
-
none: false
|
53
|
-
requirements:
|
54
|
-
- -
|
55
|
-
- !ruby/object:Gem::Version
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: inifile
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
60
54
|
type: :runtime
|
61
|
-
version_requirements: *id003
|
62
|
-
- !ruby/object:Gem::Dependency
|
63
|
-
name: xmpp4r
|
64
55
|
prerelease: false
|
65
|
-
|
66
|
-
none: false
|
67
|
-
requirements:
|
68
|
-
- -
|
69
|
-
- !ruby/object:Gem::Version
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: xmpp4r
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
74
70
|
type: :runtime
|
75
|
-
version_requirements: *id004
|
76
|
-
- !ruby/object:Gem::Dependency
|
77
|
-
name: listen
|
78
71
|
prerelease: false
|
79
|
-
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
73
|
none: false
|
81
|
-
requirements:
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: listen
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
82
83
|
- - ~>
|
83
|
-
- !ruby/object:Gem::Version
|
84
|
-
|
85
|
-
segments:
|
86
|
-
- 0
|
87
|
-
- 7
|
88
|
-
version: "0.7"
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '1.1'
|
89
86
|
type: :runtime
|
90
|
-
version_requirements: *id005
|
91
|
-
- !ruby/object:Gem::Dependency
|
92
|
-
name: rb-inotify
|
93
87
|
prerelease: false
|
94
|
-
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '1.1'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: rb-inotify
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
95
97
|
none: false
|
96
|
-
requirements:
|
98
|
+
requirements:
|
97
99
|
- - ~>
|
98
|
-
- !ruby/object:Gem::Version
|
99
|
-
|
100
|
-
segments:
|
101
|
-
- 0
|
102
|
-
- 9
|
103
|
-
version: "0.9"
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0.9'
|
104
102
|
type: :runtime
|
105
|
-
version_requirements: *id006
|
106
|
-
- !ruby/object:Gem::Dependency
|
107
|
-
name: rspec
|
108
103
|
prerelease: false
|
109
|
-
|
110
|
-
none: false
|
111
|
-
requirements:
|
112
|
-
- -
|
113
|
-
- !ruby/object:Gem::Version
|
114
|
-
|
115
|
-
|
116
|
-
- 0
|
117
|
-
version: "0"
|
118
|
-
type: :development
|
119
|
-
version_requirements: *id007
|
120
|
-
- !ruby/object:Gem::Dependency
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0.9'
|
110
|
+
- !ruby/object:Gem::Dependency
|
121
111
|
name: minitest
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
122
119
|
prerelease: false
|
123
|
-
|
124
|
-
none: false
|
125
|
-
requirements:
|
126
|
-
- -
|
127
|
-
- !ruby/object:Gem::Version
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ! '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: mocha
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ! '>='
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
132
134
|
type: :development
|
133
|
-
|
135
|
+
prerelease: false
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - ! '>='
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '0'
|
134
142
|
description:
|
135
|
-
email:
|
143
|
+
email:
|
136
144
|
- nicobrevin@gmail.com
|
137
|
-
executables:
|
145
|
+
executables:
|
138
146
|
- apt_control
|
139
147
|
extensions: []
|
140
|
-
|
141
148
|
extra_rdoc_files: []
|
142
|
-
|
143
|
-
files:
|
149
|
+
files:
|
144
150
|
- bin/apt_control
|
145
151
|
- lib/apt_control.rb
|
152
|
+
- lib/apt_control/jabber.rb
|
153
|
+
- lib/apt_control/package_states.rb
|
146
154
|
- lib/apt_control/cli.rb
|
147
|
-
- lib/apt_control/notify.rb
|
148
155
|
- lib/apt_control/version.rb
|
156
|
+
- lib/apt_control/includer.rb
|
149
157
|
- lib/apt_control/exec.rb
|
150
158
|
- lib/apt_control/cli/watch.rb
|
151
159
|
- lib/apt_control/cli/include.rb
|
@@ -155,38 +163,26 @@ files:
|
|
155
163
|
- lib/apt_control/control_file.rb
|
156
164
|
homepage: http://github.com/playlouder/apt_control
|
157
165
|
licenses: []
|
158
|
-
|
159
166
|
post_install_message:
|
160
167
|
rdoc_options: []
|
161
|
-
|
162
|
-
require_paths:
|
168
|
+
require_paths:
|
163
169
|
- lib
|
164
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
170
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
165
171
|
none: false
|
166
|
-
requirements:
|
167
|
-
- -
|
168
|
-
- !ruby/object:Gem::Version
|
169
|
-
|
170
|
-
|
171
|
-
- 0
|
172
|
-
version: "0"
|
173
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
172
|
+
requirements:
|
173
|
+
- - ! '>='
|
174
|
+
- !ruby/object:Gem::Version
|
175
|
+
version: '0'
|
176
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
174
177
|
none: false
|
175
|
-
requirements:
|
176
|
-
- -
|
177
|
-
- !ruby/object:Gem::Version
|
178
|
-
hash: 23
|
179
|
-
segments:
|
180
|
-
- 1
|
181
|
-
- 3
|
182
|
-
- 6
|
178
|
+
requirements:
|
179
|
+
- - ! '>='
|
180
|
+
- !ruby/object:Gem::Version
|
183
181
|
version: 1.3.6
|
184
182
|
requirements: []
|
185
|
-
|
186
183
|
rubyforge_project:
|
187
184
|
rubygems_version: 1.8.24
|
188
185
|
signing_key:
|
189
186
|
specification_version: 3
|
190
187
|
summary: Automatically manage an apt repository that changes a lot
|
191
188
|
test_files: []
|
192
|
-
|
data/lib/apt_control/notify.rb
DELETED
@@ -1,37 +0,0 @@
|
|
1
|
-
require 'stringio'
|
2
|
-
require 'xmpp4r/jid'
|
3
|
-
require 'xmpp4r/client'
|
4
|
-
require 'xmpp4r/muc'
|
5
|
-
require 'xmpp4r/muc/helper/simplemucclient'
|
6
|
-
|
7
|
-
module AptControl::Notify
|
8
|
-
|
9
|
-
class Jabber
|
10
|
-
include ::Jabber
|
11
|
-
|
12
|
-
def initialize(options={})
|
13
|
-
@jid = options[:jid]
|
14
|
-
@password = options[:password]
|
15
|
-
@room_jid = options[:room_jid]
|
16
|
-
@logger = options[:logger]
|
17
|
-
|
18
|
-
connect!
|
19
|
-
end
|
20
|
-
|
21
|
-
def connect!
|
22
|
-
# ::Jabber::debug = true
|
23
|
-
@logger.info("Jabber connecting with jid #{@jid}")
|
24
|
-
@client = Client.new(JID.new(@jid))
|
25
|
-
@client.connect
|
26
|
-
@client.auth(@password)
|
27
|
-
|
28
|
-
@muc = Jabber::MUC::SimpleMUCClient.new(@client)
|
29
|
-
@muc.join(JID.new(@room_jid))
|
30
|
-
@logger.info("joined room #{@room_jid}")
|
31
|
-
end
|
32
|
-
|
33
|
-
def message(msg)
|
34
|
-
@muc.send(Message.new(nil, msg))
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|