apt_control 0.3.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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/notify'
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
- Listen.to(@dir, :filter => /\.changes$/) do |modified, added, removed|
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
@@ -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).notify ; end
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 ||= Notify::Jabber.new(:jid => config[:jabber_id], :logger => logger,
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
- notifier.message(message)
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
- control_file.distributions.each do |dist|
14
- dist.package_rules.each do |rule|
15
- included = apt_site.included_version(dist.name, rule.package_name)
16
- available = build_archive[rule.package_name]
17
-
18
- next unless available
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
- control_file.distributions.each do |dist|
13
- puts dist.name unless options[:machine_readable]
14
- dist.package_rules.each do |rule|
15
- included = apt_site.included_version(dist.name, rule.package_name)
16
- available = build_archive[rule.package_name]
17
-
18
- satisfied = included && rule.satisfied_by?(included)
19
- upgradeable = available && rule.upgradeable?(included, available)
20
-
21
- if options[:machine_readable]
22
- fields = [
23
- dist.name,
24
- rule.package_name,
25
- "(#{rule.restriction} #{rule.version})",
26
- "#{upgradeable ? 'U' : '.'}#{satisfied ? 'S' : '.'}",
27
- "included=#{included || '<none>'}",
28
- "available=#{available && available.join(', ') || '<none>'} "
29
- ]
30
- puts fields.join(' ')
31
- else
32
- puts " #{rule.package_name}"
33
- puts " rule - #{rule.restriction} #{rule.version}"
34
- puts " included - #{included}"
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 { control_file.watch { notify "Control file reloaded" } }
60
-
61
- notify("Watching for new packages in #{build_archive.dir}")
62
- build_archive.watch do |package, new_version|
63
- notify("new package: #{package.name} at #{new_version}")
64
-
65
- updated = control_file.distributions.map do |dist|
66
- rule = dist[package.name] or next
67
- included = apt_site.included_version(dist.name, package.name)
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
- end.compact
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
- if updated.size == 0
90
- notify("package #{package.name} could not be updated on any distributions")
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
- Listen.to(dir, :filter => /#{Regexp.quote(fname)}/) do |modified, added, removed|
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 upgradeable?(included, available)
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 upgradeable_to(available)
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
@@ -1,3 +1,3 @@
1
1
  module AptControl
2
- VERSION = '0.3.2'
2
+ VERSION = '0.4.0'
3
3
  end
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
- hash: 23
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
- date: 2013-05-27 00:00:00 Z
19
- dependencies:
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
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
24
- none: false
25
- requirements:
26
- - - ">="
27
- - !ruby/object:Gem::Version
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
- requirement: &id002 !ruby/object:Gem::Requirement
38
- none: false
39
- requirements:
40
- - - ">="
41
- - !ruby/object:Gem::Version
42
- hash: 3
43
- segments:
44
- - 0
45
- version: "0"
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
- requirement: &id003 !ruby/object:Gem::Requirement
52
- none: false
53
- requirements:
54
- - - ">="
55
- - !ruby/object:Gem::Version
56
- hash: 3
57
- segments:
58
- - 0
59
- version: "0"
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
- requirement: &id004 !ruby/object:Gem::Requirement
66
- none: false
67
- requirements:
68
- - - ">="
69
- - !ruby/object:Gem::Version
70
- hash: 3
71
- segments:
72
- - 0
73
- version: "0"
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
- requirement: &id005 !ruby/object:Gem::Requirement
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
- hash: 5
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
- requirement: &id006 !ruby/object:Gem::Requirement
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
- hash: 25
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
- requirement: &id007 !ruby/object:Gem::Requirement
110
- none: false
111
- requirements:
112
- - - ">="
113
- - !ruby/object:Gem::Version
114
- hash: 3
115
- segments:
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
- requirement: &id008 !ruby/object:Gem::Requirement
124
- none: false
125
- requirements:
126
- - - ">="
127
- - !ruby/object:Gem::Version
128
- hash: 3
129
- segments:
130
- - 0
131
- version: "0"
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
- version_requirements: *id008
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
- hash: 3
170
- segments:
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
-
@@ -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