daemon-kit 0.1.7 → 0.1.7.4

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.
Files changed (80) hide show
  1. data/Configuration.txt +58 -0
  2. data/History.txt +24 -0
  3. data/Manifest.txt +50 -2
  4. data/PostInstall.txt +1 -1
  5. data/README.rdoc +7 -9
  6. data/Rakefile +2 -4
  7. data/TODO.txt +6 -5
  8. data/app_generators/daemon_kit/daemon_kit_generator.rb +5 -0
  9. data/app_generators/daemon_kit/templates/Rakefile +3 -1
  10. data/app_generators/daemon_kit/templates/bin/daemon.erb +1 -1
  11. data/app_generators/daemon_kit/templates/config/arguments.rb +12 -0
  12. data/app_generators/daemon_kit/templates/config/boot.rb +2 -2
  13. data/app_generators/daemon_kit/templates/script/console +3 -0
  14. data/app_generators/daemon_kit/templates/script/destroy +14 -0
  15. data/app_generators/daemon_kit/templates/script/generate +14 -0
  16. data/daemon_generators/amqp/templates/config/amqp.yml +5 -5
  17. data/daemon_generators/deploy_capistrano/deploy_capistrano_generator.rb +4 -23
  18. data/daemon_generators/deploy_capistrano/templates/USAGE +10 -0
  19. data/daemon_generators/deploy_capistrano/templates/config/deploy.rb +3 -1
  20. data/lib/daemon_kit.rb +33 -5
  21. data/lib/daemon_kit/amqp.rb +2 -1
  22. data/lib/daemon_kit/application.rb +136 -11
  23. data/lib/daemon_kit/arguments.rb +151 -0
  24. data/lib/daemon_kit/commands/console.rb +38 -0
  25. data/lib/daemon_kit/config.rb +1 -0
  26. data/lib/daemon_kit/console_daemon.rb +2 -0
  27. data/lib/daemon_kit/core_ext.rb +1 -0
  28. data/lib/daemon_kit/core_ext/string.rb +22 -0
  29. data/lib/daemon_kit/deployment/capistrano.rb +6 -9
  30. data/lib/daemon_kit/error_handlers/mail.rb +52 -15
  31. data/lib/daemon_kit/initializer.rb +95 -41
  32. data/lib/daemon_kit/pid_file.rb +61 -0
  33. data/lib/daemon_kit/tasks/environment.rake +5 -4
  34. data/lib/daemon_kit/tasks/framework.rake +15 -1
  35. data/lib/daemon_kit/tasks/god.rake +62 -0
  36. data/lib/daemon_kit/tasks/log.rake +8 -0
  37. data/lib/daemon_kit/tasks/monit.rake +29 -0
  38. data/spec/argument_spec.rb +51 -0
  39. data/spec/config_spec.rb +77 -0
  40. data/spec/daemon_kit_spec.rb +2 -2
  41. data/spec/error_handlers_spec.rb +23 -0
  42. data/spec/fixtures/env.yml +15 -0
  43. data/spec/fixtures/noenv.yml +4 -0
  44. data/spec/initializer_spec.rb +4 -3
  45. data/spec/spec_helper.rb +8 -11
  46. data/templates/god/god.erb +69 -0
  47. data/templates/monit/monit.erb +14 -0
  48. data/test/test_daemon-kit_generator.rb +6 -1
  49. data/test/test_deploy_capistrano_generator.rb +1 -2
  50. data/vendor/tmail-1.2.3/tmail.rb +5 -0
  51. data/vendor/tmail-1.2.3/tmail/address.rb +426 -0
  52. data/vendor/tmail-1.2.3/tmail/attachments.rb +46 -0
  53. data/vendor/tmail-1.2.3/tmail/base64.rb +46 -0
  54. data/vendor/tmail-1.2.3/tmail/compat.rb +41 -0
  55. data/vendor/tmail-1.2.3/tmail/config.rb +67 -0
  56. data/vendor/tmail-1.2.3/tmail/core_extensions.rb +63 -0
  57. data/vendor/tmail-1.2.3/tmail/encode.rb +581 -0
  58. data/vendor/tmail-1.2.3/tmail/header.rb +960 -0
  59. data/vendor/tmail-1.2.3/tmail/index.rb +9 -0
  60. data/vendor/tmail-1.2.3/tmail/interface.rb +1130 -0
  61. data/vendor/tmail-1.2.3/tmail/loader.rb +3 -0
  62. data/vendor/tmail-1.2.3/tmail/mail.rb +578 -0
  63. data/vendor/tmail-1.2.3/tmail/mailbox.rb +495 -0
  64. data/vendor/tmail-1.2.3/tmail/main.rb +6 -0
  65. data/vendor/tmail-1.2.3/tmail/mbox.rb +3 -0
  66. data/vendor/tmail-1.2.3/tmail/net.rb +248 -0
  67. data/vendor/tmail-1.2.3/tmail/obsolete.rb +132 -0
  68. data/vendor/tmail-1.2.3/tmail/parser.rb +1476 -0
  69. data/vendor/tmail-1.2.3/tmail/port.rb +379 -0
  70. data/vendor/tmail-1.2.3/tmail/quoting.rb +118 -0
  71. data/vendor/tmail-1.2.3/tmail/require_arch.rb +58 -0
  72. data/vendor/tmail-1.2.3/tmail/scanner.rb +49 -0
  73. data/vendor/tmail-1.2.3/tmail/scanner_r.rb +261 -0
  74. data/vendor/tmail-1.2.3/tmail/stringio.rb +280 -0
  75. data/vendor/tmail-1.2.3/tmail/utils.rb +337 -0
  76. data/vendor/tmail-1.2.3/tmail/version.rb +39 -0
  77. data/vendor/tmail.rb +13 -0
  78. metadata +57 -18
  79. data/daemon_generators/deploy_capistrano/USAGE +0 -5
  80. data/lib/daemon_kit/patches/force_kill_wait.rb +0 -120
@@ -0,0 +1,495 @@
1
+ =begin rdoc
2
+
3
+ = Mailbox and Mbox interaction class
4
+
5
+ =end
6
+ #--
7
+ # Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
8
+ #
9
+ # Permission is hereby granted, free of charge, to any person obtaining
10
+ # a copy of this software and associated documentation files (the
11
+ # "Software"), to deal in the Software without restriction, including
12
+ # without limitation the rights to use, copy, modify, merge, publish,
13
+ # distribute, sublicense, and/or sell copies of the Software, and to
14
+ # permit persons to whom the Software is furnished to do so, subject to
15
+ # the following conditions:
16
+ #
17
+ # The above copyright notice and this permission notice shall be
18
+ # included in all copies or substantial portions of the Software.
19
+ #
20
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
+ #
28
+ # Note: Originally licensed under LGPL v2+. Using MIT license for Rails
29
+ # with permission of Minero Aoki.
30
+ #++
31
+
32
+ require 'tmail/port'
33
+ require 'socket'
34
+ require 'mutex_m'
35
+
36
+
37
+ unless [].respond_to?(:sort_by)
38
+ module Enumerable#:nodoc:
39
+ def sort_by
40
+ map {|i| [yield(i), i] }.sort {|a,b| a.first <=> b.first }.map {|i| i[1] }
41
+ end
42
+ end
43
+ end
44
+
45
+
46
+ module TMail
47
+
48
+ class MhMailbox
49
+
50
+ PORT_CLASS = MhPort
51
+
52
+ def initialize( dir )
53
+ edir = File.expand_path(dir)
54
+ raise ArgumentError, "not directory: #{dir}"\
55
+ unless FileTest.directory? edir
56
+ @dirname = edir
57
+ @last_file = nil
58
+ @last_atime = nil
59
+ end
60
+
61
+ def directory
62
+ @dirname
63
+ end
64
+
65
+ alias dirname directory
66
+
67
+ attr_accessor :last_atime
68
+
69
+ def inspect
70
+ "#<#{self.class} #{@dirname}>"
71
+ end
72
+
73
+ def close
74
+ end
75
+
76
+ def new_port
77
+ PORT_CLASS.new(next_file_name())
78
+ end
79
+
80
+ def each_port
81
+ mail_files().each do |path|
82
+ yield PORT_CLASS.new(path)
83
+ end
84
+ @last_atime = Time.now
85
+ end
86
+
87
+ alias each each_port
88
+
89
+ def reverse_each_port
90
+ mail_files().reverse_each do |path|
91
+ yield PORT_CLASS.new(path)
92
+ end
93
+ @last_atime = Time.now
94
+ end
95
+
96
+ alias reverse_each reverse_each_port
97
+
98
+ # old #each_mail returns Port
99
+ #def each_mail
100
+ # each_port do |port|
101
+ # yield Mail.new(port)
102
+ # end
103
+ #end
104
+
105
+ def each_new_port( mtime = nil, &block )
106
+ mtime ||= @last_atime
107
+ return each_port(&block) unless mtime
108
+ return unless File.mtime(@dirname) >= mtime
109
+
110
+ mail_files().each do |path|
111
+ yield PORT_CLASS.new(path) if File.mtime(path) > mtime
112
+ end
113
+ @last_atime = Time.now
114
+ end
115
+
116
+ private
117
+
118
+ def mail_files
119
+ Dir.entries(@dirname)\
120
+ .select {|s| /\A\d+\z/ === s }\
121
+ .map {|s| s.to_i }\
122
+ .sort\
123
+ .map {|i| "#{@dirname}/#{i}" }\
124
+ .select {|path| FileTest.file? path }
125
+ end
126
+
127
+ def next_file_name
128
+ unless n = @last_file
129
+ n = 0
130
+ Dir.entries(@dirname)\
131
+ .select {|s| /\A\d+\z/ === s }\
132
+ .map {|s| s.to_i }.sort\
133
+ .each do |i|
134
+ next unless FileTest.file? "#{@dirname}/#{i}"
135
+ n = i
136
+ end
137
+ end
138
+ begin
139
+ n += 1
140
+ end while FileTest.exist? "#{@dirname}/#{n}"
141
+ @last_file = n
142
+
143
+ "#{@dirname}/#{n}"
144
+ end
145
+
146
+ end # MhMailbox
147
+
148
+ MhLoader = MhMailbox
149
+
150
+
151
+ class UNIXMbox
152
+
153
+ class << self
154
+ alias newobj new
155
+ end
156
+
157
+ # Creates a new mailbox object that you can iterate through to collect the
158
+ # emails from with "each_port".
159
+ #
160
+ # You need to pass it a filename of a unix mailbox format file, the format of this
161
+ # file can be researched at this page at {wikipedia}[link:http://en.wikipedia.org/wiki/Mbox]
162
+ #
163
+ # ==== Parameters
164
+ #
165
+ # +filename+: The filename of the mailbox you want to open
166
+ #
167
+ # +tmpdir+: Can be set to override TMail using the system environment's temp dir. TMail will first
168
+ # use the temp dir specified by you (if any) or then the temp dir specified in the Environment's TEMP
169
+ # value then the value in the Environment's TMP value or failing all of the above, '/tmp'
170
+ #
171
+ # +readonly+: If set to false, each email you take from the mail box will be removed from the mailbox.
172
+ # default is *false* - ie, it *WILL* truncate your mailbox file to ZERO once it has read the emails out.
173
+ #
174
+ # ==== Options:
175
+ #
176
+ # None
177
+ #
178
+ # ==== Examples:
179
+ #
180
+ # # First show using readonly true:
181
+ #
182
+ # require 'ftools'
183
+ # File.size("../test/fixtures/mailbox")
184
+ # #=> 20426
185
+ #
186
+ # mailbox = TMail::UNIXMbox.new("../test/fixtures/mailbox", nil, true)
187
+ # #=> #<TMail::UNIXMbox:0x14a2aa8 @readonly=true.....>
188
+ #
189
+ # mailbox.each_port do |port|
190
+ # mail = TMail::Mail.new(port)
191
+ # puts mail.subject
192
+ # end
193
+ # #Testing mailbox 1
194
+ # #Testing mailbox 2
195
+ # #Testing mailbox 3
196
+ # #Testing mailbox 4
197
+ # require 'ftools'
198
+ # File.size?("../test/fixtures/mailbox")
199
+ # #=> 20426
200
+ #
201
+ # # Now show with readonly set to the default false
202
+ #
203
+ # mailbox = TMail::UNIXMbox.new("../test/fixtures/mailbox")
204
+ # #=> #<TMail::UNIXMbox:0x14a2aa8 @readonly=false.....>
205
+ #
206
+ # mailbox.each_port do |port|
207
+ # mail = TMail::Mail.new(port)
208
+ # puts mail.subject
209
+ # end
210
+ # #Testing mailbox 1
211
+ # #Testing mailbox 2
212
+ # #Testing mailbox 3
213
+ # #Testing mailbox 4
214
+ #
215
+ # File.size?("../test/fixtures/mailbox")
216
+ # #=> nil
217
+ def UNIXMbox.new( filename, tmpdir = nil, readonly = false )
218
+ tmpdir = ENV['TEMP'] || ENV['TMP'] || '/tmp'
219
+ newobj(filename, "#{tmpdir}/ruby_tmail_#{$$}_#{rand()}", readonly, false)
220
+ end
221
+
222
+ def UNIXMbox.lock( fname )
223
+ begin
224
+ f = File.open(fname, 'r+')
225
+ f.flock File::LOCK_EX
226
+ yield f
227
+ ensure
228
+ f.flock File::LOCK_UN
229
+ f.close if f and not f.closed?
230
+ end
231
+ end
232
+
233
+ def UNIXMbox.static_new( fname, dir, readonly = false )
234
+ newobj(fname, dir, readonly, true)
235
+ end
236
+
237
+ def initialize( fname, mhdir, readonly, static )
238
+ @filename = fname
239
+ @readonly = readonly
240
+ @closed = false
241
+
242
+ Dir.mkdir mhdir
243
+ @real = MhMailbox.new(mhdir)
244
+ @finalizer = UNIXMbox.mkfinal(@real, @filename, !@readonly, !static)
245
+ ObjectSpace.define_finalizer self, @finalizer
246
+ end
247
+
248
+ def UNIXMbox.mkfinal( mh, mboxfile, writeback_p, cleanup_p )
249
+ lambda {
250
+ if writeback_p
251
+ lock(mboxfile) {|f|
252
+ mh.each_port do |port|
253
+ f.puts create_from_line(port)
254
+ port.ropen {|r|
255
+ f.puts r.read
256
+ }
257
+ end
258
+ }
259
+ end
260
+ if cleanup_p
261
+ Dir.foreach(mh.dirname) do |fname|
262
+ next if /\A\.\.?\z/ === fname
263
+ File.unlink "#{mh.dirname}/#{fname}"
264
+ end
265
+ Dir.rmdir mh.dirname
266
+ end
267
+ }
268
+ end
269
+
270
+ # make _From line
271
+ def UNIXMbox.create_from_line( port )
272
+ sprintf 'From %s %s',
273
+ fromaddr(), TextUtils.time2str(File.mtime(port.filename))
274
+ end
275
+
276
+ def UNIXMbox.fromaddr(port)
277
+ h = HeaderField.new_from_port(port, 'Return-Path') ||
278
+ HeaderField.new_from_port(port, 'From') ||
279
+ HeaderField.new_from_port(port, 'EnvelopeSender') or return 'nobody'
280
+ a = h.addrs[0] or return 'nobody'
281
+ a.spec
282
+ end
283
+
284
+ def close
285
+ return if @closed
286
+
287
+ ObjectSpace.undefine_finalizer self
288
+ @finalizer.call
289
+ @finalizer = nil
290
+ @real = nil
291
+ @closed = true
292
+ @updated = nil
293
+ end
294
+
295
+ def each_port( &block )
296
+ close_check
297
+ update
298
+ @real.each_port(&block)
299
+ end
300
+
301
+ alias each each_port
302
+
303
+ def reverse_each_port( &block )
304
+ close_check
305
+ update
306
+ @real.reverse_each_port(&block)
307
+ end
308
+
309
+ alias reverse_each reverse_each_port
310
+
311
+ # old #each_mail returns Port
312
+ #def each_mail( &block )
313
+ # each_port do |port|
314
+ # yield Mail.new(port)
315
+ # end
316
+ #end
317
+
318
+ def each_new_port( mtime = nil )
319
+ close_check
320
+ update
321
+ @real.each_new_port(mtime) {|p| yield p }
322
+ end
323
+
324
+ def new_port
325
+ close_check
326
+ @real.new_port
327
+ end
328
+
329
+ private
330
+
331
+ def close_check
332
+ @closed and raise ArgumentError, 'accessing already closed mbox'
333
+ end
334
+
335
+ def update
336
+ return if FileTest.zero?(@filename)
337
+ return if @updated and File.mtime(@filename) < @updated
338
+ w = nil
339
+ port = nil
340
+ time = nil
341
+ UNIXMbox.lock(@filename) {|f|
342
+ begin
343
+ f.each do |line|
344
+ if /\AFrom / === line
345
+ w.close if w
346
+ File.utime time, time, port.filename if time
347
+
348
+ port = @real.new_port
349
+ w = port.wopen
350
+ time = fromline2time(line)
351
+ else
352
+ w.print line if w
353
+ end
354
+ end
355
+ ensure
356
+ if w and not w.closed?
357
+ w.close
358
+ File.utime time, time, port.filename if time
359
+ end
360
+ end
361
+ f.truncate(0) unless @readonly
362
+ @updated = Time.now
363
+ }
364
+ end
365
+
366
+ def fromline2time( line )
367
+ m = /\AFrom \S+ \w+ (\w+) (\d+) (\d+):(\d+):(\d+) (\d+)/.match(line) \
368
+ or return nil
369
+ Time.local(m[6].to_i, m[1], m[2].to_i, m[3].to_i, m[4].to_i, m[5].to_i)
370
+ end
371
+
372
+ end # UNIXMbox
373
+
374
+ MboxLoader = UNIXMbox
375
+
376
+
377
+ class Maildir
378
+
379
+ extend Mutex_m
380
+
381
+ PORT_CLASS = MaildirPort
382
+
383
+ @seq = 0
384
+ def Maildir.unique_number
385
+ synchronize {
386
+ @seq += 1
387
+ return @seq
388
+ }
389
+ end
390
+
391
+ def initialize( dir = nil )
392
+ @dirname = dir || ENV['MAILDIR']
393
+ raise ArgumentError, "not directory: #{@dirname}"\
394
+ unless FileTest.directory? @dirname
395
+ @new = "#{@dirname}/new"
396
+ @tmp = "#{@dirname}/tmp"
397
+ @cur = "#{@dirname}/cur"
398
+ end
399
+
400
+ def directory
401
+ @dirname
402
+ end
403
+
404
+ def inspect
405
+ "#<#{self.class} #{@dirname}>"
406
+ end
407
+
408
+ def close
409
+ end
410
+
411
+ def each_port
412
+ mail_files(@cur).each do |path|
413
+ yield PORT_CLASS.new(path)
414
+ end
415
+ end
416
+
417
+ alias each each_port
418
+
419
+ def reverse_each_port
420
+ mail_files(@cur).reverse_each do |path|
421
+ yield PORT_CLASS.new(path)
422
+ end
423
+ end
424
+
425
+ alias reverse_each reverse_each_port
426
+
427
+ def new_port
428
+ fname = nil
429
+ tmpfname = nil
430
+ newfname = nil
431
+
432
+ begin
433
+ fname = "#{Time.now.to_i}.#{$$}_#{Maildir.unique_number}.#{Socket.gethostname}"
434
+
435
+ tmpfname = "#{@tmp}/#{fname}"
436
+ newfname = "#{@new}/#{fname}"
437
+ end while FileTest.exist? tmpfname
438
+
439
+ if block_given?
440
+ File.open(tmpfname, 'w') {|f| yield f }
441
+ File.rename tmpfname, newfname
442
+ PORT_CLASS.new(newfname)
443
+ else
444
+ File.open(tmpfname, 'w') {|f| f.write "\n\n" }
445
+ PORT_CLASS.new(tmpfname)
446
+ end
447
+ end
448
+
449
+ def each_new_port
450
+ mail_files(@new).each do |path|
451
+ dest = @cur + '/' + File.basename(path)
452
+ File.rename path, dest
453
+ yield PORT_CLASS.new(dest)
454
+ end
455
+
456
+ check_tmp
457
+ end
458
+
459
+ TOO_OLD = 60 * 60 * 36 # 36 hour
460
+
461
+ def check_tmp
462
+ old = Time.now.to_i - TOO_OLD
463
+
464
+ each_filename(@tmp) do |full, fname|
465
+ if FileTest.file? full and
466
+ File.stat(full).mtime.to_i < old
467
+ File.unlink full
468
+ end
469
+ end
470
+ end
471
+
472
+ private
473
+
474
+ def mail_files( dir )
475
+ Dir.entries(dir)\
476
+ .select {|s| s[0] != ?. }\
477
+ .sort_by {|s| s.slice(/\A\d+/).to_i }\
478
+ .map {|s| "#{dir}/#{s}" }\
479
+ .select {|path| FileTest.file? path }
480
+ end
481
+
482
+ def each_filename( dir )
483
+ Dir.foreach(dir) do |fname|
484
+ path = "#{dir}/#{fname}"
485
+ if fname[0] != ?. and FileTest.file? path
486
+ yield path, fname
487
+ end
488
+ end
489
+ end
490
+
491
+ end # Maildir
492
+
493
+ MaildirLoader = Maildir
494
+
495
+ end # module TMail