ripta-daemon-kit 0.1.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/History.txt +7 -0
  2. data/Manifest.txt +58 -0
  3. data/PostInstall.txt +6 -0
  4. data/README.textile +77 -0
  5. data/Rakefile +30 -0
  6. data/TODO.txt +24 -0
  7. data/app_generators/daemon_kit/USAGE +7 -0
  8. data/app_generators/daemon_kit/daemon_kit_generator.rb +121 -0
  9. data/app_generators/daemon_kit/templates/README +48 -0
  10. data/app_generators/daemon_kit/templates/Rakefile +4 -0
  11. data/app_generators/daemon_kit/templates/bin/daemon.erb +7 -0
  12. data/app_generators/daemon_kit/templates/config/boot.rb +52 -0
  13. data/app_generators/daemon_kit/templates/config/environment.rb +19 -0
  14. data/app_generators/daemon_kit/templates/config/environments/development.rb +0 -0
  15. data/app_generators/daemon_kit/templates/config/environments/production.rb +0 -0
  16. data/app_generators/daemon_kit/templates/config/environments/test.rb +0 -0
  17. data/app_generators/daemon_kit/templates/config/initializers/readme +11 -0
  18. data/app_generators/daemon_kit/templates/libexec/daemon.erb +18 -0
  19. data/bin/daemon_kit +19 -0
  20. data/daemon_generators/jabber/USAGE +5 -0
  21. data/daemon_generators/jabber/jabber_generator.rb +65 -0
  22. data/daemon_generators/jabber/templates/config/initializers/jabber.rb +8 -0
  23. data/daemon_generators/jabber/templates/config/jabber.yml +26 -0
  24. data/daemon_generators/jabber/templates/libexec/daemon.rb +27 -0
  25. data/lib/daemon_kit/application.rb +32 -0
  26. data/lib/daemon_kit/initializer.rb +249 -0
  27. data/lib/daemon_kit/jabber.rb +172 -0
  28. data/lib/daemon_kit/patches/force_kill_wait.rb +120 -0
  29. data/lib/daemon_kit/tasks/framework.rake +75 -0
  30. data/lib/daemon_kit/tasks.rb +2 -0
  31. data/lib/daemon_kit.rb +11 -0
  32. data/rubygems_generators/install_rspec/USAGE +5 -0
  33. data/rubygems_generators/install_rspec/install_rspec_generator.rb +57 -0
  34. data/rubygems_generators/install_rspec/templates/spec/spec.opts +1 -0
  35. data/rubygems_generators/install_rspec/templates/spec/spec_helper.rb +10 -0
  36. data/rubygems_generators/install_rspec/templates/spec.rb +11 -0
  37. data/rubygems_generators/install_rspec/templates/tasks/rspec.rake +21 -0
  38. data/script/console +10 -0
  39. data/script/destroy +14 -0
  40. data/script/generate +14 -0
  41. data/script/txt2html +71 -0
  42. data/spec/daemon_kit_spec.rb +7 -0
  43. data/spec/initializer_spec.rb +31 -0
  44. data/spec/spec.opts +1 -0
  45. data/spec/spec_helper.rb +30 -0
  46. data/tasks/rspec.rake +21 -0
  47. data/test/test_daemon-kit_generator.rb +67 -0
  48. data/test/test_generator_helper.rb +29 -0
  49. data/test/test_jabber_generator.rb +49 -0
  50. metadata +150 -0
@@ -0,0 +1,32 @@
1
+ require 'daemons'
2
+
3
+ module DaemonKit
4
+
5
+ # Class responsible for making the daemons run and keep them running.
6
+ class Application
7
+
8
+ class << self
9
+
10
+ # Run the file as a daemon
11
+ def run( file )
12
+ raise DaemonNotFound.new( file ) unless File.exist?( file )
13
+
14
+ app_name = DaemonKit.configuration.daemon_name || File.basename( file )
15
+ options = { :backtrace => true, :log_output => true, :app_name => app_name, :dir_mode => :normal, :dir => "log" }
16
+
17
+ options[:multiple] = DaemonKit.configuration.multiple
18
+ options[:force_kill_wait] = DaemonKit.configuration.force_kill_wait if DaemonKit.configuration.force_kill_wait
19
+
20
+ Daemons.run( file, options )
21
+ end
22
+
23
+ # Call this from inside a daemonized process to complete the
24
+ # initialization process
25
+ def running!
26
+ DaemonKit::Initializer.continue!
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,249 @@
1
+ require 'logger'
2
+ require 'pathname'
3
+
4
+ DAEMON_ENV = (ENV['DAEMON_ENV'] || 'development').dup unless defined?(DAEMON_ENV)
5
+
6
+ $:.unshift File.dirname(__FILE__) + '/..'
7
+ require 'daemon_kit'
8
+
9
+ module DaemonKit
10
+
11
+ class << self
12
+
13
+ def logger
14
+ @logger
15
+ end
16
+
17
+ def logger=( logger )
18
+ @logger = logger
19
+ end
20
+
21
+ def configuration
22
+ @configuration
23
+ end
24
+
25
+ def configuration=( configuration )
26
+ @configuration = configuration
27
+ end
28
+
29
+ def trap( *args, &block )
30
+ self.configuration.trap( *args, &block )
31
+ end
32
+
33
+ end
34
+
35
+
36
+ # This class does all the nightmare work of setting up a working
37
+ # environment for your daemon.
38
+ class Initializer
39
+
40
+ attr_reader :configuration
41
+
42
+ def self.run( configuration = Configuration.new )
43
+ yield configuration if block_given?
44
+ initializer = new configuration
45
+ initializer.before_daemonize
46
+ initializer
47
+ end
48
+
49
+ def self.continue!
50
+ initializer = new DaemonKit.configuration
51
+ initializer.after_daemonize
52
+ end
53
+
54
+ def self.shutdown
55
+ DaemonKit.logger.warn "Shutting down"
56
+ exit
57
+ end
58
+
59
+ def initialize( configuration )
60
+ @configuration = configuration
61
+ end
62
+
63
+ def before_daemonize
64
+ DaemonKit.configuration = @configuration
65
+
66
+ set_load_path
67
+ load_gems
68
+ load_patches
69
+ load_environment
70
+ end
71
+
72
+ def after_daemonize
73
+ initialize_logger
74
+ initialize_signal_traps
75
+ end
76
+
77
+ def set_load_path
78
+ configuration.load_paths.each do |d|
79
+ $:.unshift( "#{DAEMON_ROOT}/#{d}" ) if File.directory?( "#{DAEMON_ROOT}/#{d}" )
80
+ end
81
+ end
82
+
83
+ def load_gems
84
+
85
+ end
86
+
87
+ def load_patches
88
+ if !!configuration.force_kill_wait
89
+ require 'daemon_kit/patches/force_kill_wait'
90
+ end
91
+ end
92
+
93
+ def load_environment
94
+ return if @environment_loaded
95
+ @environment_loaded = true
96
+
97
+ config = configuration
98
+
99
+ eval(IO.read(configuration.environment_path), binding, configuration.environment_path)
100
+
101
+ eval(IO.read(configuration.daemon_initializer), binding, configuration.daemon_initializer) if File.exist?( configuration.daemon_initializer )
102
+ end
103
+
104
+ def initialize_logger
105
+ return if DaemonKit.logger
106
+
107
+ unless logger = configuration.logger
108
+ logger = Logger.new( configuration.log_path )
109
+ logger.level = configuration.log_level
110
+ end
111
+
112
+ DaemonKit.logger = logger
113
+
114
+ configuration.trap("USR1") {
115
+ DaemonKit.logger.level = DaemonKit.logger.debug? ? Logger::INFO : Logger::DEBUG
116
+ DaemonKit.logger.info "Log level changed to #{DaemonKit.logger.debug? ? 'DEBUG' : 'INFO' }"
117
+ }
118
+ configuration.trap("USR2") {
119
+ DaemonKit.logger.level = Logger::DEBUG
120
+ DaemonKit.logger.info "Log level changed to DEBUG"
121
+ }
122
+
123
+ DaemonKit.logger.info "DaemonKit up and running in #{DAEMON_ENV} mode"
124
+ end
125
+
126
+ def initialize_signal_traps
127
+ term_proc = Proc.new { DaemonKit::Initializer.shutdown }
128
+ configuration.trap( 'INT', term_proc )
129
+ configuration.trap( 'TERM', term_proc )
130
+ end
131
+
132
+ end
133
+
134
+ # Holds our various configuration values
135
+ class Configuration
136
+ # Root to the daemon
137
+ attr_reader :root_path
138
+
139
+ # List of load paths
140
+ attr_accessor :load_paths
141
+
142
+ # The log level to use, defaults to DEBUG
143
+ attr_accessor :log_level
144
+
145
+ # Path to the log file, defaults to 'log/<environment>.log'
146
+ attr_accessor :log_path
147
+
148
+ # Provide a custom logger to use
149
+ attr_accessor :logger
150
+
151
+ # The application name
152
+ attr_accessor :daemon_name
153
+
154
+ # Allow multiple copies to run?
155
+ attr_accessor :multiple
156
+
157
+ # Use the force kill patch? Give the number of seconds
158
+ attr_accessor :force_kill_wait
159
+
160
+ # Collection of signal traps
161
+ attr_reader :signal_traps
162
+
163
+ def initialize
164
+ set_root_path!
165
+
166
+ self.load_paths = default_load_paths
167
+ self.log_level = default_log_level
168
+ self.log_path = default_log_path
169
+
170
+ self.multiple = false
171
+ self.force_kill_wait = false
172
+
173
+ @signal_traps = {}
174
+ end
175
+
176
+ def environment
177
+ ::DAEMON_ENV
178
+ end
179
+
180
+ # The path to the current environment's file (<tt>development.rb</tt>, etc.). By
181
+ # default the file is at <tt>config/environments/#{environment}.rb</tt>.
182
+ def environment_path
183
+ "#{root_path}/config/environments/#{environment}.rb"
184
+ end
185
+
186
+ def daemon_initializer
187
+ "#{root_path}/config/initializers/#{self.daemon_name}.rb"
188
+ end
189
+
190
+ # Add a trap for the specified signal, can be code block or a proc
191
+ def trap( signal, proc = nil, &block )
192
+ return if proc.nil? && !block_given?
193
+
194
+ unless @signal_traps.has_key?( signal )
195
+ set_trap( signal )
196
+ end
197
+
198
+ @signal_traps[signal].unshift( proc || block )
199
+ end
200
+
201
+ protected
202
+
203
+ def run_traps( signal )
204
+ DaemonKit.logger.info "Running signal traps for #{signal}"
205
+ self.signal_traps[ signal ].each { |trap| trap.call }
206
+ end
207
+
208
+ private
209
+
210
+ def set_trap( signal )
211
+ DaemonKit.logger.info "Setting up trap for #{signal}"
212
+ @signal_traps[ signal ] = []
213
+ Signal.trap( signal, Proc.new { self.run_traps( signal ) } )
214
+ end
215
+
216
+ def set_root_path!
217
+ raise "DAEMON_ROOT is not set" unless defined?(::DAEMON_ROOT)
218
+ raise "DAEMON_ROOT is not a directory" unless defined?(::DAEMON_ROOT)
219
+
220
+ @root_path =
221
+ # Pathname is incompatible with Windows, but Windows doesn't have
222
+ # real symlinks so File.expand_path is safe.
223
+ if RUBY_PLATFORM =~ /(:?mswin|mingw)/
224
+ File.expand_path(::DAEMON_ROOT)
225
+
226
+ # Otherwise use Pathname#realpath which respects symlinks.
227
+ else
228
+ Pathname.new(::DAEMON_ROOT).realpath.to_s
229
+ end
230
+
231
+ Object.const_set(:RELATIVE_DAEMON_ROOT, ::DAEMON_ROOT.dup) unless defined?(::RELATIVE_DAEMON_ROOT)
232
+ ::DAEMON_ROOT.replace @root_path
233
+ end
234
+
235
+ def default_load_paths
236
+ [ 'lib' ]
237
+ end
238
+
239
+ def default_log_path
240
+ File.join(root_path, 'log', "#{environment}.log")
241
+ end
242
+
243
+ def default_log_level
244
+ environment == 'production' ? Logger::INFO : Logger::DEBUG
245
+ end
246
+ end
247
+
248
+
249
+ end
@@ -0,0 +1,172 @@
1
+ require 'yaml'
2
+
3
+ module DaemonKit
4
+ # Thin wrapper around xmpp4r-simple, specifically designed to ease
5
+ # configuration of a jabber daemon and provide some added simplicity.
6
+ class Jabber
7
+
8
+ # Jabber connection
9
+ attr_reader :connection
10
+
11
+ @@instance = nil
12
+ @@message_handler = nil
13
+ @@presence_handler = nil
14
+ @@subscription_handler = nil
15
+
16
+ class << self
17
+
18
+ # Deliver a message to the specified jid.
19
+ def deliver( jid, message )
20
+ instance.connection.deliver( jid, message )
21
+ end
22
+
23
+ # Use this instead of initializing, keeps it singleton
24
+ def instance
25
+ @instance ||= (
26
+ config = YAML.load_file( "#{DAEMON_ROOT}/config/jabber.yml" )[DAEMON_ENV]
27
+ raise ArgumentError, "Missing Jabber configuration for #{DAEMON_ENV} environment" if config.nil?
28
+ new( config )
29
+ )
30
+ @instance.startup!
31
+ end
32
+ private :new
33
+
34
+ def run
35
+ DaemonKit.logger.info "Starting jabber loop"
36
+
37
+ loop do
38
+ process_messages
39
+ process_updates
40
+ process_subscriptions
41
+
42
+ begin
43
+ sleep 1
44
+ rescue Interrupt
45
+ DaemonKit.logger.warn "Jabber loop interrupted"
46
+ break
47
+ end
48
+ end
49
+ end
50
+
51
+ def process_messages
52
+ @message_handler ||= Proc.new { |m| DaemonKit.logger.info "Received message from #{m.from}: #{m.body}" }
53
+
54
+ instance.valid_messages { |m| @message_handler.call(m) }
55
+ end
56
+
57
+ def process_updates
58
+ @presence_handler ||= Proc.new { |friend, old_presence, new_presence|
59
+ DaemonKit.logger.debug "Received presence update: #{friend} went from #{old_presence} to #{new_presence}"
60
+ }
61
+
62
+ instance.connection.presence_updates { |friend, old_presence, new_presence|
63
+ @presence_handler.call(friend, old_presence, new_presence)
64
+ }
65
+
66
+ end
67
+
68
+ def process_subscriptions
69
+ @subscription_handler ||= Proc.new { |friend,presence| DaemonKit.logger.debug "Received presence update from #{friend}: #{presence}" }
70
+
71
+ instance.connection.subscription_requests { |friend,presence| @subscription_handler.call(friend,presence) }
72
+ end
73
+
74
+ def received_messages(&block)
75
+ @message_handler = block
76
+ end
77
+
78
+ def presence_updates(&block)
79
+ @presence_handler = block
80
+ end
81
+
82
+ def subscription_requests(&block)
83
+ @subscription_handler = block
84
+ end
85
+
86
+ end
87
+
88
+ def initialize( options = {} )
89
+ @jabber_id = options.delete("jabber_id")
90
+ @password = options.delete("password")
91
+ @resource = options.delete("resource") || 'daemon_kit'
92
+ @masters = options.delete("masters") || []
93
+ @supporters = options.delete("supporters") || []
94
+
95
+ raise ArgumentError if [ @jabber_id, @password ].any? { |a| a.nil? }
96
+ end
97
+
98
+ def startup!
99
+ return self if @booted
100
+
101
+ connect!
102
+ setup_roster!
103
+
104
+ DaemonKit.trap( 'INT', Proc.new { self.shutdown! } )
105
+ DaemonKit.trap( 'TERM', Proc.new { self.shutdown! } )
106
+
107
+ @booted = true
108
+
109
+ self
110
+ end
111
+
112
+ def shutdown!
113
+ DaemonKit.logger.warn "Disconnecting jabber connection"
114
+ self.connection.disconnect
115
+ end
116
+
117
+ def contacts
118
+ @masters + @supporters
119
+ end
120
+
121
+ def valid_messages(&block)
122
+ self.connection.received_messages.each do |message|
123
+ next unless valid_master?( message.from )
124
+
125
+ busy do
126
+ block.call message
127
+ end
128
+ end
129
+ end
130
+
131
+ def valid_master?( jid )
132
+ @masters.include?( jid.strip.to_s )
133
+ end
134
+
135
+ def busy(&block)
136
+ self.connection.status(:dnd, "Working...")
137
+ yield
138
+ self.connection.status(:chat, self.status_line )
139
+ end
140
+
141
+ def status_line
142
+ "#{DaemonKit.configuration.daemon_name} ready for instructions"
143
+ end
144
+
145
+ private
146
+
147
+ def connect!
148
+ jid = @jabber_id + '/' + @resource
149
+
150
+ @connection = ::Jabber::Simple.new( jid, @password, nil, self.status_line )
151
+ end
152
+
153
+ def setup_roster!
154
+ # cleanup the roster
155
+ self.connection.roster.items.each_pair do |jid, roster_item|
156
+ jid = jid.strip.to_s
157
+ unless self.contacts.include?( jid )
158
+ self.connection.remove( jid )
159
+ end
160
+ end
161
+
162
+ # add missing contacts
163
+ self.contacts.each do |jid|
164
+ unless self.connection.subscribed_to?( jid )
165
+ self.connection.add( jid )
166
+ #self.connection.accept_subscription( jid )
167
+ end
168
+ end
169
+ end
170
+
171
+ end
172
+ end
@@ -0,0 +1,120 @@
1
+ # Shamelessly taken from http://blog.rapleaf.com/dev/?p=19
2
+
3
+ require 'rubygems'
4
+ require 'daemons'
5
+ require 'timeout'
6
+
7
+ module Daemons
8
+
9
+ class ApplicationGroup
10
+
11
+ # We want to redefine find_applications to not rely on
12
+ # pidfiles (e.g. find application if pidfile is gone)
13
+ # We recreate the pid files if they're not there.
14
+ def find_applications(dir)
15
+ # Find pid_files, like original implementation
16
+ pid_files = PidFile.find_files(dir, app_name)
17
+ @monitor = Monitor.find(dir, app_name + '_monitor')
18
+ pid_files.reject! {|f| f =~ /_monitor.pid$/}
19
+
20
+ # Find the missing pids based on the UNIX pids
21
+ pidfile_pids = pid_files.map {|pf| PidFile.existing(pf).pid}
22
+ missing_pids = unix_pids - pidfile_pids
23
+
24
+ # Create pidfiles that are gone
25
+ if missing_pids.size > 0
26
+ puts "[daemons_ext]: #{missing_pids.size} missing pidfiles: " +
27
+ "#{missing_pids.inspect}... creating pid file(s)."
28
+ missing_pids.each do |pid|
29
+ pidfile = PidFile.new(dir, app_name, multiple)
30
+ pidfile.pid = pid # Doesn't seem to matter if it's a string or Fixnum
31
+ end
32
+ end
33
+
34
+ # Now get all the pid file again
35
+ pid_files = PidFile.find_files(dir, app_name)
36
+
37
+ return pid_files.map {|f|
38
+ app = Application.new(self, {}, PidFile.existing(f))
39
+ setup_app(app)
40
+ app
41
+ }
42
+ end
43
+
44
+ # Specify :force_kill_wait => (seconds to wait) and this method will
45
+ # block until the process is dead. It first sends a TERM signal, then
46
+ # a KILL signal (-9) if the process hasn't died after the wait time.
47
+ def stop_all(force = false)
48
+ @monitor.stop if @monitor
49
+
50
+ wait = options[:force_kill_wait].to_i
51
+ if wait > 0
52
+ puts "[daemons_ext]: Killing #{app_name} with force after #{wait} secs."
53
+
54
+ # Send term first, don't delete PID files.
55
+ @applications.each {|a| a.send_sig('TERM')}
56
+
57
+ begin
58
+ started_at = Time.now
59
+ Timeout::timeout(wait) do
60
+ num_pids = unix_pids.size
61
+ while num_pids > 0
62
+ time_left = wait - (Time.now - started_at)
63
+ puts "[daemons_ext]: Waiting #{time_left.round} secs on " +
64
+ "#{num_pids} #{app_name}(s)..."
65
+ sleep 1
66
+ num_pids = unix_pids.size
67
+ end
68
+ end
69
+ rescue Timeout::Error
70
+ @applications.each {|a| a.send_sig('KILL')}
71
+ ensure
72
+ # Delete Pidfiles
73
+ @applications.each {|a| a.zap!}
74
+ end
75
+
76
+ puts "[daemons_ext]: All #{app_name}(s) dead."
77
+ else
78
+ @applications.each {|a|
79
+ if force
80
+ begin; a.stop; rescue ::Exception; end
81
+ else
82
+ a.stop
83
+ end
84
+ }
85
+ end
86
+ end
87
+
88
+ private
89
+
90
+ # Find UNIX pids based on app_name. CAUTION: This has only been tested on
91
+ # Mac OS X and CentOS.
92
+ def unix_pids
93
+ pids = []
94
+ x = `ps auxw | grep -v grep | awk '{print $2, $11}' | grep #{app_name}`
95
+ if x && x.chomp!
96
+ processes = x.split(/\n/).compact
97
+ processes = processes.delete_if do |p|
98
+ pid, name = p.split(/\s/)
99
+ # We want to make sure that the first part of the process name matches
100
+ # so that app_name matches app_name_22
101
+ app_name != name[0..(app_name.length - 1)]
102
+ end
103
+ pids = processes.map {|p| p.split(/\s/)[0].to_i}
104
+ end
105
+
106
+ pids
107
+ end
108
+
109
+ end
110
+
111
+ class Application
112
+
113
+ # Send signal to the process, rescue if process deson't exist
114
+ def send_sig(sig)
115
+ Process.kill(sig, @pid.pid) rescue Errno::ESRCH
116
+ end
117
+
118
+ end
119
+
120
+ end
@@ -0,0 +1,75 @@
1
+ namespace :daemon_kit do
2
+ namespace :freeze do
3
+ desc "Lock this application to the current gem (by unpacking it into vendor/daemon_kit)"
4
+ task :gems do
5
+ deps = %w()
6
+ require 'rubygems'
7
+ require 'rubygems/gem_runner'
8
+
9
+ kit = (version = ENV['VERSION']) ?
10
+ Gem.cache.find_name('daemon-kit', "= #{version}").first :
11
+ Gem.cache.find_name('daemon-kit').sort_by { |g| g.version }.last
12
+
13
+ version ||= kit.version
14
+
15
+ unless kit
16
+ puts "No daemon_kit gem #{version} is installed. Do 'gem list daemon_kit' to see what you have available."
17
+ exit
18
+ end
19
+
20
+ puts "Freezing the gem for DaemonKit #{kit.version}"
21
+ rm_rf "vendor/daemon_kit"
22
+ mkdir_p "vendor/daemon_kit"
23
+
24
+ begin
25
+ chdir("vendor/daemon_kit") do
26
+ kit.dependencies.select { |g| deps.include? g.name }.each do |g|
27
+ Gem::GemRunner.new.run(["unpack", g.name, "--version", g.version_requirements.to_s])
28
+ mv(Dir.glob("#{g.name}*").first, g.name)
29
+ end
30
+
31
+ Gem::GemRunner.new.run(["unpack", "daemon-kit", "--version", "=#{version}"])
32
+ FileUtils.mv(Dir.glob("daemon-kit*").first, "daemon-kit")
33
+ end
34
+ rescue Exception
35
+ rm_rf "vendor/daemon_kit"
36
+ raise
37
+ end
38
+ end
39
+
40
+ desc 'Lock to latest edge daemon_kit'
41
+ task :edge do
42
+ require 'open-uri'
43
+ #version = ENV["RELEASE"] || "edge"
44
+ commits = "http://github.com/api/v1/yaml/kennethkalmer/daemon-kit/commits/master"
45
+ url = "http://github.com/kennethkalmer/daemon-kit/zipball/master"
46
+
47
+ rm_rf "vendor/daemon_kit"
48
+ mkdir_p "vendor/daemon_kit"
49
+
50
+ chdir 'vendor/daemon_kit' do
51
+ latest_revision = YAML.load(open(commits))["commits"].first["id"]
52
+
53
+ puts "Downloading DaemonKit from #{url}"
54
+ File.open('daemon-kit.zip', 'wb') do |dst|
55
+ open url do |src|
56
+ while chunk = src.read(4096)
57
+ dst << chunk
58
+ end
59
+ end
60
+ end
61
+
62
+ puts 'Unpacking DaemonKit'
63
+ rm_rf 'daemon-kit'
64
+ `unzip daemon-kit.zip`
65
+ FileUtils.mv(Dir.glob("kennethkalmer-daemon-kit*").first, "daemon-kit")
66
+ %w(daemon-kit.zip).each do |goner|
67
+ rm_f goner
68
+ end
69
+
70
+ touch "REVISION_#{latest_revision}"
71
+ end
72
+ end
73
+
74
+ end
75
+ end
@@ -0,0 +1,2 @@
1
+ # Load all the take tasks in the gem
2
+ Dir[File.join(File.dirname(__FILE__), '**/*.rake')].each { |rake| load rake }
data/lib/daemon_kit.rb ADDED
@@ -0,0 +1,11 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ require 'rubygems'
5
+
6
+ require 'daemon_kit/initializer'
7
+ require 'daemon_kit/application'
8
+
9
+ module DaemonKit
10
+ VERSION = '0.1.0.2'
11
+ end
@@ -0,0 +1,5 @@
1
+ Description:
2
+
3
+
4
+ Usage:
5
+