Class: AptControl::CLI::Watch

Inherits:
Object
  • Object
show all
Includes:
Common
Defined in:
lib/apt_control/cli/watch.rb

Instance Method Summary collapse

Methods included from Common

#apt_site, #build_archive, #control_file, #each_package_state, #fs_listener_factory, #jabber, #jabber_enabled?, #logger, #notify, #package_states, #validate_config!

Instance Method Details

#daemonize!Object



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/apt_control/cli/watch.rb', line 32

def daemonize!
  pidfile = options[:pidfile]

  if pidfile && File.exists?(pidfile)
    $stderr.puts("pidfile exists, not starting")
    exit 1
  end

  if uid = options[:setuid]
    logger.info("setting uid to #{uid}")
    begin
      Process::Sys.setuid(uid)
    rescue Errno::EPERM => e
      raise Climate::ExitException, "Could not setuid with #{uid}"
    end
  end

  pid = fork
  exit 0 unless pid.nil?

  File.open(pidfile, 'w') {|f| f.write(Process.pid) } if pidfile

  at_exit { File.delete(pidfile) if File.exists?(pidfile) } if pidfile
end

#handle_new_package(package, new_version) ⇒ Object



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/apt_control/cli/watch.rb', line 126

def handle_new_package(package, new_version)
  notify("new package: #{package.name} at #{new_version}")

  matched_states = package_states.select {|s| s.package_name == package.name }

  updated = matched_states.map do |state|
    if state.includeable_to.max == new_version
      begin
        new_include_cmd.perform_for(state, new_version, options[:noop])
        notify("included package #{package.name}-#{new_version} in #{state.dist.name}")
        state.dist.name
      rescue => e
        notify("Failed to include package #{package.name}-#{new_version}, check log for more details")
        logger.error("failed to include package #{package.name}")
        logger.error(e)
      end
    end
  end.compact

  if updated.size == 0
    notify("package #{package.name} could not be updated on any distributions")
  end
end

#new_include_cmdObject

for the watch command, we use the actor version of the apt_site so that reprepro operations are sequential



59
60
61
# File 'lib/apt_control/cli/watch.rb', line 59

def new_include_cmd
  super(apt_site: apt_site.actor)
end

#runObject



18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/apt_control/cli/watch.rb', line 18

def run
  validate_config!

  # hit these before we daemonize so we don't just background and die
  apt_site
  control_file
  build_archive

  daemonize! if options[:daemonize]

  start_watching
end

#start_aptbot_in_new_threadObject



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/apt_control/cli/watch.rb', line 76

def start_aptbot_in_new_thread
  Thread.new do
    begin
      bot = AptControl::Bot.new(
        jabber:         jabber.actor,
        command_start:  jabber.room_nick,
        package_states: package_states,
        include_cmd:    new_include_cmd,
        control_file:   control_file,
        logger:         logger)

      jabber.add_room_listener(bot.actor)
    rescue => e
      puts "got an error #{e}"
      puts e.backtrace
    end
  end
end

#start_watchingObject



63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/apt_control/cli/watch.rb', line 63

def start_watching
  threads = [
    watch_control_in_new_thread,
    watch_build_archive_in_new_thread,
    jabber_enabled? && start_aptbot_in_new_thread
  ].compact

  notify("apt_control watcher is up, waiting for changes to control file and new packages...")

  # these should never exit, so stop main thread exiting by joining to them
  threads.each(&:join)
end

#watch_build_archive_in_new_threadObject



114
115
116
117
118
119
120
121
122
123
124
# File 'lib/apt_control/cli/watch.rb', line 114

def watch_build_archive_in_new_thread
  Thread.new do
    begin
      build_archive.watch(fs_listener_factory) do |package, new_version|
        handle_new_package(package, new_version)
      end
    ensure
      logger.warn("build archive watch loop exited")
    end
  end
end

#watch_control_in_new_threadObject



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/apt_control/cli/watch.rb', line 95

def watch_control_in_new_thread
  # update the all the rules if the control file changes
  Thread.new do
    begin
      control_file.watch(fs_listener_factory) do
        notify "Control file reloaded"
        # FIXME need to do some kind of locking or actor style dev for this
        # as it looks like there could be some concurrency bugs lurking
        new_include_cmd.run(package_states) do |package_state, new_version|
          notify("included package #{package_state.package_name}-#{new_version} in #{package_state.dist.name}")
          true
        end
      end
    ensure
      logger.warn("control file watch loop exited")
    end
  end
end