logging 0.7.0 → 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,11 @@
1
+ == 0.7.1 / 2008-
2
+
3
+ 1 minor enhancement
4
+ - Removed dependency on the Lockfile gem (brought the ruby
5
+ file into the logging/stelan directory)
6
+ 1 bug fix
7
+ - Fixed bug with age based rolling: was not multi-process safe
8
+
1
9
  == 0.7.0 / 2008-02-12
2
10
 
3
11
  1 major enhancement
@@ -20,8 +20,11 @@ lib/logging/log_event.rb
20
20
  lib/logging/logger.rb
21
21
  lib/logging/repository.rb
22
22
  lib/logging/root_logger.rb
23
+ lib/logging/stelan/lockfile.rb
23
24
  lib/logging/utils.rb
25
+ tasks/ann.rake
24
26
  tasks/annotations.rake
27
+ tasks/bones.rake
25
28
  tasks/doc.rake
26
29
  tasks/gem.rake
27
30
  tasks/manifest.rake
data/README.txt CHANGED
@@ -1,21 +1,22 @@
1
1
  Logging
2
+ by Tim Pease
2
3
 
3
4
  * {Homepage}[http://logging.rubyforge.org/]
4
5
  * {Rubyforge Project}[http://rubyforge.org/projects/logging]
5
6
  * email tim dot pease at gmail dot com
6
7
 
7
- == DESCRIPTION:
8
+ == DESCRIPTION
8
9
 
9
10
  Logging is a flexible logging library for use in Ruby programs based on the
10
11
  design of Java's log4j library. It features a hierarchical logging system,
11
12
  custom level names, multiple output destinations per log event, custom
12
13
  formatting, and more.
13
14
 
14
- == INSTALL:
15
+ == INSTALL
15
16
 
16
17
  sudo gem install logging
17
18
 
18
- == EXAMPLE:
19
+ == EXAMPLE
19
20
 
20
21
  This example configures a logger to output messages in a format similar to the
21
22
  core ruby Logger class. Only log messages that are warnings or higher will be
@@ -35,8 +36,10 @@ file. Only log messages that are informational or higher will be logged.
35
36
  require 'logging'
36
37
 
37
38
  logger = Logging::Logger['example_logger']
38
- logger.add Logging::Appender.stdout
39
- logger.add Logging::Appenders::File.new('example.log')
39
+ logger.add_appenders(
40
+ Logging::Appender.stdout,
41
+ Logging::Appenders::File.new('example.log')
42
+ )
40
43
  logger.level = :info
41
44
 
42
45
  logger.debug "this debug message will not be output by the logger"
@@ -72,7 +75,7 @@ the recommended way of accomplishing this.
72
75
  end
73
76
  end
74
77
 
75
- == NOTES:
78
+ == NOTES
76
79
 
77
80
  Although Logging is intended to supersede Log4r, it is not a one-to-one
78
81
  replacement for the Log4r library. Most notably is the difference in namespaces
@@ -81,10 +84,10 @@ Logging::Appender and renaming Log4r::Formatter to Logging::Layout. These
81
84
  changes were meant to bring the Logging class names more in line with the Log4j
82
85
  class names.
83
86
 
84
- == REQUIREMENTS:
87
+ == REQUIREMENTS
85
88
 
86
89
  Logging does not depend on any other installed libraries or gems.
87
90
 
88
- == LICENSE:
91
+ == LICENSE
89
92
 
90
93
  Ruby
data/Rakefile CHANGED
@@ -18,11 +18,10 @@ PROJ.rdoc_dir = 'doc/rdoc'
18
18
  PROJ.rdoc_remote_dir = ''
19
19
  PROJ.version = Logging::VERSION
20
20
 
21
- PROJ.exclude << '^tags$' << '^tasks/archive' << '^coverage'
21
+ PROJ.exclude += %w[^tags$ ^tasks/archive ^coverage]
22
22
  PROJ.rdoc_exclude << '^data'
23
23
  PROJ.svn = true
24
24
 
25
25
  depend_on 'flexmock'
26
- depend_on 'lockfile'
27
26
 
28
27
  # EOF
@@ -1,4 +1,4 @@
1
- # $Id: logging.rb 98 2008-02-13 00:40:28Z tim_pease $
1
+ # $Id: logging.rb 105 2008-02-26 04:43:21Z tim_pease $
2
2
 
3
3
  # Equivalent to a header guard in C/C++
4
4
  # Used to prevent the class/module from being loaded more than once
@@ -12,7 +12,7 @@ unless defined? Logging
12
12
  module Logging
13
13
 
14
14
  # :stopdoc:
15
- VERSION = '0.7.0'
15
+ VERSION = '0.7.1'
16
16
  LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
17
17
  PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
18
18
  WIN32 = %r/djgpp|(cyg|ms|bcc)win|mingw/ =~ RUBY_PLATFORM
@@ -1,19 +1,6 @@
1
- # $Id: rolling_file.rb 97 2008-02-13 00:32:18Z tim_pease $
2
-
3
- begin
4
- require 'lockfile'
5
- rescue LoadError
6
- require 'rubygems'
7
- require 'lockfile'
8
- end
9
-
10
- # FIXME: bug when truncating a rolling file on create
11
- # If there is not log file in existence, it is created and then
12
- # immediately rolld resulting in two log files
13
- #
14
- # This appears to be because of rails -- creating the logfile and
15
- # then we replace the default logger with a rolling file appender. It
16
- # sees the already existing log file and happily rolls it right over.
1
+ # $Id: rolling_file.rb 106 2008-02-26 04:52:42Z tim_pease $
2
+
3
+ require Logging.libpath(*%w[logging stelan lockfile])
17
4
 
18
5
  module Logging::Appenders
19
6
 
@@ -88,7 +75,7 @@ module Logging::Appenders
88
75
  @size = opts.getopt(:size, :as => Integer)
89
76
 
90
77
  @lockfile = if opts.getopt(:safe, false) and !::Logging::WIN32
91
- Lockfile.new(
78
+ ::Logging::Lockfile.new(
92
79
  @fn + '.lck',
93
80
  :retries => 1,
94
81
  :timeout => 2
@@ -96,39 +83,38 @@ module Logging::Appenders
96
83
  end
97
84
 
98
85
  code = 'def sufficiently_aged?() false end'
86
+ @age_fn = @fn + '.age'
99
87
 
100
88
  case @age = opts.getopt(:age)
101
89
  when 'daily'
102
- @start_time = Time.now
90
+ FileUtils.touch(@age_fn) unless test(?f, @age_fn)
103
91
  code = <<-CODE
104
92
  def sufficiently_aged?
105
93
  now = Time.now
106
- if (now.day != @start_time.day) or (now - @start_time) > 86400
107
- @start_time = now
94
+ start = ::File.mtime(@age_fn)
95
+ if (now.day != start.day) or (now - start) > 86400
108
96
  return true
109
97
  end
110
98
  false
111
99
  end
112
100
  CODE
113
101
  when 'weekly'
114
- @start_time = Time.now
102
+ FileUtils.touch(@age_fn) unless test(?f, @age_fn)
115
103
  code = <<-CODE
116
104
  def sufficiently_aged?
117
- now = Time.now
118
- if (now - @start_time) > 604800
119
- @start_time = now
105
+ if (Time.now - ::File.mtime(@age_fn)) > 604800
120
106
  return true
121
107
  end
122
108
  false
123
109
  end
124
110
  CODE
125
111
  when 'monthly'
126
- @start_time = Time.now
112
+ FileUtils.touch(@age_fn) unless test(?f, @age_fn)
127
113
  code = <<-CODE
128
114
  def sufficiently_aged?
129
115
  now = Time.now
130
- if (now.month != @start_time.month) or (now - @start_time) > 2678400
131
- @start_time = now
116
+ start = ::File.mtime(@age_fn)
117
+ if (now.month != start.month) or (now - start) > 2678400
132
118
  return true
133
119
  end
134
120
  false
@@ -136,12 +122,10 @@ module Logging::Appenders
136
122
  CODE
137
123
  when Integer, String
138
124
  @age = Integer(@age)
139
- @start_time = Time.now
125
+ FileUtils.touch(@age_fn) unless test(?f, @age_fn)
140
126
  code = <<-CODE
141
127
  def sufficiently_aged?
142
- now = Time.now
143
- if (now - @start_time) > @age
144
- @start_time = now
128
+ if (Time.now - ::File.mtime(@age_fn)) > @age
145
129
  return true
146
130
  end
147
131
  false
@@ -264,6 +248,9 @@ module Logging::Appenders
264
248
 
265
249
  # finally reanme the base log file
266
250
  ::File.rename(@fn, sprintf(@logname_fmt, 1))
251
+
252
+ # touch the age file if needed
253
+ FileUtils.touch(@age_fn) if @age
267
254
  end
268
255
 
269
256
  # call-seq:
@@ -0,0 +1,530 @@
1
+ # $Id: lockfile.rb 101 2008-02-13 17:10:47Z tim_pease $
2
+
3
+ # This file was stolen with permission from Ara T. Howrad's gem of the same
4
+ # name. The only difference is the removal of Ara's vim folding turds and
5
+ # making the code work with Ruby1.9
6
+
7
+ unless(defined?($__logging_lockfile__) or defined?(Logging::Lockfile))
8
+
9
+ require 'socket'
10
+ require 'timeout'
11
+ require 'fileutils'
12
+
13
+ module Logging
14
+ class Lockfile
15
+
16
+ VERSION = '1.4.3'
17
+ def version() VERSION end
18
+
19
+ class LockError < StandardError; end
20
+ class StolenLockError < LockError; end
21
+ class StackingLockError < LockError; end
22
+ class StatLockError < LockError; end
23
+ class MaxTriesLockError < LockError; end
24
+ class TimeoutLockError < LockError; end
25
+ class NFSLockError < LockError; end
26
+ class UnLockError < LockError; end
27
+
28
+ class SleepCycle < Array
29
+ attr :min
30
+ attr :max
31
+ attr :range
32
+ attr :inc
33
+
34
+ def initialize( min, max, inc )
35
+ @min, @max, @inc = Float(min), Float(max), Float(inc)
36
+ @range = @max - @min
37
+ raise RangeError, "max(#{ @max }) <= min(#{ @min })" if @max <= @min
38
+ raise RangeError, "inc(#{ @inc }) > range(#{ @range })" if @inc > @range
39
+ raise RangeError, "inc(#{ @inc }) <= 0" if @inc <= 0
40
+ raise RangeError, "range(#{ @range }) <= 0" if @range <= 0
41
+ s = @min
42
+ push(s) and s += @inc while(s <= @max)
43
+ self[-1] = @max if self[-1] < @max
44
+ reset
45
+ end
46
+
47
+ def next
48
+ ret = self[@idx]
49
+ @idx = ((@idx + 1) % self.size)
50
+ ret
51
+ end
52
+
53
+ def reset
54
+ @idx = 0
55
+ end
56
+ end # class SleepCycle
57
+
58
+ HOSTNAME = Socket::gethostname
59
+
60
+ DEFAULT_RETRIES = nil # maximum number of attempts
61
+ DEFAULT_TIMEOUT = nil # the longest we will try
62
+ DEFAULT_MAX_AGE = 3600 # lockfiles older than this are stale
63
+ DEFAULT_SLEEP_INC = 2 # sleep cycle is this much longer each time
64
+ DEFAULT_MIN_SLEEP = 2 # shortest sleep time
65
+ DEFAULT_MAX_SLEEP = 32 # longest sleep time
66
+ DEFAULT_SUSPEND = 1800 # iff we steal a lock wait this long before we go on
67
+ DEFAULT_REFRESH = 8 # how often we touch/validate the lock
68
+ DEFAULT_DONT_CLEAN = false # iff we leave lock files lying around
69
+ DEFAULT_POLL_RETRIES = 16 # this many polls makes one 'try'
70
+ DEFAULT_POLL_MAX_SLEEP = 0.08 # the longest we'll sleep between polls
71
+ DEFAULT_DONT_SWEEP = false # if we cleanup after other process on our host
72
+ DEFAULT_DONT_USE_LOCK_ID = false # if we dump lock info into lockfile
73
+
74
+ DEFAULT_DEBUG = ENV['LOCKFILE_DEBUG'] || false
75
+
76
+ class << self
77
+ attr_accessor :retries
78
+ attr_accessor :max_age
79
+ attr_accessor :sleep_inc
80
+ attr_accessor :min_sleep
81
+ attr_accessor :max_sleep
82
+ attr_accessor :suspend
83
+ attr_accessor :timeout
84
+ attr_accessor :refresh
85
+ attr_accessor :debug
86
+ attr_accessor :dont_clean
87
+ attr_accessor :poll_retries
88
+ attr_accessor :poll_max_sleep
89
+ attr_accessor :dont_sweep
90
+ attr_accessor :dont_use_lock_id
91
+
92
+ def init
93
+ @retries = DEFAULT_RETRIES
94
+ @max_age = DEFAULT_MAX_AGE
95
+ @sleep_inc = DEFAULT_SLEEP_INC
96
+ @min_sleep = DEFAULT_MIN_SLEEP
97
+ @max_sleep = DEFAULT_MAX_SLEEP
98
+ @suspend = DEFAULT_SUSPEND
99
+ @timeout = DEFAULT_TIMEOUT
100
+ @refresh = DEFAULT_REFRESH
101
+ @dont_clean = DEFAULT_DONT_CLEAN
102
+ @poll_retries = DEFAULT_POLL_RETRIES
103
+ @poll_max_sleep = DEFAULT_POLL_MAX_SLEEP
104
+ @dont_sweep = DEFAULT_DONT_SWEEP
105
+ @dont_use_lock_id = DEFAULT_DONT_USE_LOCK_ID
106
+
107
+ @debug = DEFAULT_DEBUG
108
+
109
+ STDOUT.sync = true if @debug
110
+ STDERR.sync = true if @debug
111
+ end
112
+ end
113
+ self.init
114
+
115
+ attr :klass
116
+ attr :path
117
+ attr :opts
118
+ attr :locked
119
+ attr :thief
120
+ attr :dirname
121
+ attr :basename
122
+ attr :clean
123
+ attr :retries
124
+ attr :max_age
125
+ attr :sleep_inc
126
+ attr :min_sleep
127
+ attr :max_sleep
128
+ attr :suspend
129
+ attr :refresh
130
+ attr :timeout
131
+ attr :dont_clean
132
+ attr :poll_retries
133
+ attr :poll_max_sleep
134
+ attr :dont_sweep
135
+ attr :dont_use_lock_id
136
+
137
+ attr_accessor :debug
138
+
139
+ alias thief? thief
140
+ alias locked? locked
141
+ alias debug? debug
142
+
143
+ def self::create( path, *a, &b )
144
+ opts = {
145
+ 'retries' => 0,
146
+ 'min_sleep' => 0,
147
+ 'max_sleep' => 1,
148
+ 'sleep_inc' => 1,
149
+ 'max_age' => nil,
150
+ 'suspend' => 0,
151
+ 'refresh' => nil,
152
+ 'timeout' => nil,
153
+ 'poll_retries' => 0,
154
+ 'dont_clean' => true,
155
+ 'dont_sweep' => false,
156
+ 'dont_use_lock_id' => true
157
+ }
158
+ begin
159
+ new(path, opts).lock
160
+ rescue LockError
161
+ raise Errno::EEXIST, path
162
+ end
163
+ open(path, *a, &b)
164
+ end
165
+
166
+ def initialize( path, opts = {}, &block )
167
+ @klass = self.class
168
+ @path = path
169
+ @opts = opts
170
+
171
+ @retries = getopt 'retries' , @klass.retries
172
+ @max_age = getopt 'max_age' , @klass.max_age
173
+ @sleep_inc = getopt 'sleep_inc' , @klass.sleep_inc
174
+ @min_sleep = getopt 'min_sleep' , @klass.min_sleep
175
+ @max_sleep = getopt 'max_sleep' , @klass.max_sleep
176
+ @suspend = getopt 'suspend' , @klass.suspend
177
+ @timeout = getopt 'timeout' , @klass.timeout
178
+ @refresh = getopt 'refresh' , @klass.refresh
179
+ @dont_clean = getopt 'dont_clean' , @klass.dont_clean
180
+ @poll_retries = getopt 'poll_retries' , @klass.poll_retries
181
+ @poll_max_sleep = getopt 'poll_max_sleep' , @klass.poll_max_sleep
182
+ @dont_sweep = getopt 'dont_sweep' , @klass.dont_sweep
183
+ @dont_use_lock_id = getopt 'dont_use_lock_id' , @klass.dont_use_lock_id
184
+ @debug = getopt 'debug' , @klass.debug
185
+
186
+ @sleep_cycle = SleepCycle::new @min_sleep, @max_sleep, @sleep_inc
187
+
188
+ @clean = @dont_clean ? nil : lambda{ File::unlink @path rescue nil }
189
+ @dirname = File::dirname @path
190
+ @basename = File::basename @path
191
+ @thief = false
192
+ @locked = false
193
+
194
+ lock(&block) if block
195
+ end
196
+
197
+ def lock
198
+ raise StackingLockError, "<#{ @path }> is locked!" if @locked
199
+
200
+ sweep unless @dont_sweep
201
+
202
+ ret = nil
203
+
204
+ attempt do
205
+ begin
206
+ @sleep_cycle.reset
207
+ create_tmplock do |f|
208
+ begin
209
+ Timeout::timeout(@timeout) do
210
+ tmp_path = f.path
211
+ tmp_stat = f.lstat
212
+ n_retries = 0
213
+ trace{ "attempting to lock <#{ @path }>..." }
214
+ begin
215
+ i = 0
216
+ begin
217
+ trace{ "polling attempt <#{ i }>..." }
218
+ begin
219
+ File::link tmp_path, @path
220
+ rescue Errno::ENOENT
221
+ try_again!
222
+ end
223
+ lock_stat = File::lstat @path
224
+ raise StatLockError, "stat's do not agree" unless
225
+ tmp_stat.rdev == lock_stat.rdev and tmp_stat.ino == lock_stat.ino
226
+ trace{ "aquired lock <#{ @path }>" }
227
+ @locked = true
228
+ rescue => e
229
+ i += 1
230
+ unless i >= @poll_retries
231
+ t = [rand(@poll_max_sleep), @poll_max_sleep].min
232
+ trace{ "poll sleep <#{ t }>..." }
233
+ sleep t
234
+ retry
235
+ end
236
+ raise
237
+ end
238
+
239
+ rescue => e
240
+ n_retries += 1
241
+ trace{ "n_retries <#{ n_retries }>" }
242
+ case validlock?
243
+ when true
244
+ raise MaxTriesLockError, "surpased retries <#{ @retries }>" if
245
+ @retries and n_retries >= @retries
246
+ trace{ "found valid lock" }
247
+ sleeptime = @sleep_cycle.next
248
+ trace{ "sleep <#{ sleeptime }>..." }
249
+ sleep sleeptime
250
+ when false
251
+ trace{ "found invalid lock and removing" }
252
+ begin
253
+ File::unlink @path
254
+ @thief = true
255
+ warn "<#{ @path }> stolen by <#{ Process.pid }> at <#{ timestamp }>"
256
+ trace{ "i am a thief!" }
257
+ rescue Errno::ENOENT
258
+ end
259
+ trace{ "suspending <#{ @suspend }>" }
260
+ sleep @suspend
261
+ when nil
262
+ raise MaxTriesLockError, "surpased retries <#{ @retries }>" if
263
+ @retries and n_retries >= @retries
264
+ end
265
+ retry
266
+ end # begin
267
+ end # timeout
268
+ rescue Timeout::Error
269
+ raise TimeoutLockError, "surpassed timeout <#{ @timeout }>"
270
+ end # begin
271
+ end # create_tmplock
272
+
273
+ if block_given?
274
+ stolen = false
275
+ refresher = (@refresh ? new_refresher : nil)
276
+ begin
277
+ begin
278
+ ret = yield @path
279
+ rescue StolenLockError
280
+ stolen = true
281
+ raise
282
+ end
283
+ ensure
284
+ begin
285
+ refresher.kill if refresher and refresher.status
286
+ ensure
287
+ unlock unless stolen
288
+ end
289
+ end
290
+ else
291
+ ObjectSpace.define_finalizer self, @clean if @clean
292
+ ret = self
293
+ end
294
+ rescue Errno::ESTALE, Errno::EIO => e
295
+ raise(NFSLockError, errmsg(e))
296
+ end
297
+ end
298
+
299
+ return ret
300
+ end
301
+
302
+ def sweep
303
+ begin
304
+ glob = File::join(@dirname, ".*lck")
305
+ paths = Dir[glob]
306
+ paths.each do |path|
307
+ begin
308
+ basename = File::basename path
309
+ pat = %r/^\s*\.([^_]+)_([^_]+)/o
310
+ if pat.match(basename)
311
+ host, pid = $1, $2
312
+ else
313
+ next
314
+ end
315
+ host.gsub!(%r/^\.+|\.+$/,'')
316
+ quad = host.split %r/\./
317
+ host = quad.first
318
+ pat = %r/^\s*#{ host }/i
319
+ if pat.match(HOSTNAME) and %r/^\s*\d+\s*$/.match(pid)
320
+ unless alive?(pid)
321
+ trace{ "process <#{ pid }> on <#{ host }> is no longer alive" }
322
+ trace{ "sweeping <#{ path }>" }
323
+ FileUtils::rm_f path
324
+ else
325
+ trace{ "process <#{ pid }> on <#{ host }> is still alive" }
326
+ trace{ "ignoring <#{ path }>" }
327
+ end
328
+ else
329
+ trace{ "ignoring <#{ path }> generated by <#{ host }>" }
330
+ end
331
+ rescue
332
+ next
333
+ end
334
+ end
335
+ rescue => e
336
+ warn(errmsg(e))
337
+ end
338
+ end
339
+
340
+ def alive?( pid )
341
+ pid = Integer("#{ pid }")
342
+ begin
343
+ Process::kill 0, pid
344
+ true
345
+ rescue Errno::ESRCH
346
+ false
347
+ end
348
+ end
349
+
350
+ def unlock
351
+ raise UnLockError, "<#{ @path }> is not locked!" unless @locked
352
+ begin
353
+ File::unlink @path
354
+ rescue Errno::ENOENT
355
+ raise StolenLockError, @path
356
+ ensure
357
+ @thief = false
358
+ @locked = false
359
+ ObjectSpace.undefine_finalizer self if @clean
360
+ end
361
+ end
362
+
363
+ def new_refresher
364
+ Thread::new(Thread::current, @path, @refresh, @dont_use_lock_id) do |thread, path, refresh, dont_use_lock_id|
365
+ loop do
366
+ begin
367
+ touch path
368
+ trace{"touched <#{ path }> @ <#{ Time.now.to_f }>"}
369
+ unless dont_use_lock_id
370
+ loaded = load_lock_id(IO.read(path))
371
+ trace{"loaded <\n#{ loaded.inspect }\n>"}
372
+ raise unless loaded == @lock_id
373
+ end
374
+ sleep refresh
375
+ rescue Exception => e
376
+ trace{errmsg e}
377
+ thread.raise StolenLockError
378
+ Thread::exit
379
+ end
380
+ end
381
+ end
382
+ end
383
+
384
+ def validlock?
385
+ if @max_age
386
+ uncache @path rescue nil
387
+ begin
388
+ return((Time.now - File::stat(@path).mtime) < @max_age)
389
+ rescue Errno::ENOENT
390
+ return nil
391
+ end
392
+ else
393
+ exist = File::exist?(@path)
394
+ return(exist ? true : nil)
395
+ end
396
+ end
397
+
398
+ def uncache( file )
399
+ refresh = nil
400
+ begin
401
+ is_a_file = File === file
402
+ path = (is_a_file ? file.path : file.to_s)
403
+ stat = (is_a_file ? file.stat : File::stat(file.to_s))
404
+ refresh = tmpnam(File::dirname(path))
405
+ File::link path, refresh
406
+ File::chmod stat.mode, path
407
+ File::utime stat.atime, stat.mtime, path
408
+ ensure
409
+ begin
410
+ File::unlink refresh if refresh
411
+ rescue Errno::ENOENT
412
+ end
413
+ end
414
+ end
415
+
416
+ def create_tmplock
417
+ tmplock = tmpnam @dirname
418
+ begin
419
+ create(tmplock) do |f|
420
+ unless dont_use_lock_id
421
+ @lock_id = gen_lock_id
422
+ dumped = dump_lock_id
423
+ trace{"lock_id <\n#{ @lock_id.inspect }\n>"}
424
+ f.write dumped
425
+ f.flush
426
+ end
427
+ yield f
428
+ end
429
+ ensure
430
+ begin; File::unlink tmplock; rescue Errno::ENOENT; end if tmplock
431
+ end
432
+ end
433
+
434
+ def gen_lock_id
435
+ Hash[
436
+ 'host' => "#{ HOSTNAME }",
437
+ 'pid' => "#{ Process.pid }",
438
+ 'ppid' => "#{ Process.ppid }",
439
+ 'time' => timestamp
440
+ ]
441
+ end
442
+
443
+ def timestamp
444
+ time = Time.now
445
+ usec = time.usec.to_s
446
+ usec << '0' while usec.size < 6
447
+ "#{ time.strftime('%Y-%m-%d %H:%M:%S') }.#{ usec }"
448
+ end
449
+
450
+ def dump_lock_id lock_id = @lock_id
451
+ "host: %s\npid: %s\nppid: %s\ntime: %s\n" %
452
+ lock_id.values_at('host','pid','ppid','time')
453
+ end
454
+
455
+ def load_lock_id( buf )
456
+ lock_id = {}
457
+ kv = %r/([^:]+):(.*)/o
458
+ buf.each do |line|
459
+ m = kv.match line
460
+ k, v = m[1], m[2]
461
+ next unless m and k and v
462
+ lock_id[k.strip] = v.strip
463
+ end
464
+ lock_id
465
+ end
466
+
467
+ def tmpnam( dir, seed = File::basename($0) )
468
+ pid = Process.pid
469
+ time = Time.now
470
+ sec = time.to_i
471
+ usec = time.usec
472
+ "%s%s.%s_%d_%s_%d_%d_%d.lck" %
473
+ [dir, File::SEPARATOR, HOSTNAME, pid, seed, sec, usec, rand(sec)]
474
+ end
475
+
476
+ def create( path )
477
+ umask = nil
478
+ f = nil
479
+ begin
480
+ umask = File::umask 022
481
+ f = open path, File::WRONLY|File::CREAT|File::EXCL, 0644
482
+ ensure
483
+ File::umask umask if umask
484
+ end
485
+ return(block_given? ? begin; yield f; ensure; f.close; end : f)
486
+ end
487
+
488
+ def touch( path )
489
+ FileUtils.touch path
490
+ end
491
+
492
+ def getopt( key, default = nil )
493
+ [ key, key.to_s, key.to_s.intern ].each do |k|
494
+ return @opts[k] if @opts.has_key?(k)
495
+ end
496
+ return default
497
+ end
498
+
499
+ def to_str
500
+ @path
501
+ end
502
+ alias to_s to_str
503
+
504
+ def trace( s = nil )
505
+ STDERR.puts((s ? s : yield)) if @debug
506
+ end
507
+
508
+ def errmsg( e )
509
+ "%s (%s)\n%s\n" % [e.class, e.message, e.backtrace.join("\n")]
510
+ end
511
+
512
+ def attempt
513
+ ret = nil
514
+ loop{ break unless catch('attempt'){ ret = yield } == 'try_again' }
515
+ ret
516
+ end
517
+
518
+ def try_again!
519
+ throw 'attempt', 'try_again'
520
+ end
521
+ alias again! try_again!
522
+
523
+ def give_up!
524
+ throw 'attempt', 'give_up'
525
+ end
526
+ end # class Lockfile
527
+ end # module Logging
528
+
529
+ $__logging_lockfile__ = __FILE__
530
+ end
@@ -0,0 +1,76 @@
1
+ # $Id: ann.rake 105 2008-02-26 04:43:21Z tim_pease $
2
+
3
+ begin
4
+ require 'bones/smtp_tls'
5
+ rescue LoadError
6
+ require 'net/smtp'
7
+ end
8
+ require 'time'
9
+
10
+ namespace :ann do
11
+
12
+ file PROJ.ann_file do
13
+ puts "Generating #{PROJ.ann_file}"
14
+ File.open(PROJ.ann_file,'w') do |fd|
15
+ fd.puts("#{PROJ.name} version #{PROJ.version}")
16
+ fd.puts(" by #{Array(PROJ.authors).first}") if PROJ.authors
17
+ fd.puts(" #{PROJ.url}") if PROJ.url
18
+ fd.puts(" (the \"#{PROJ.release_name}\" release)") if PROJ.release_name
19
+ fd.puts
20
+ fd.puts("== DESCRIPTION")
21
+ fd.puts
22
+ fd.puts(PROJ.description)
23
+ fd.puts
24
+ fd.puts(PROJ.changes.sub(%r/^.*$/, '== CHANGES'))
25
+ fd.puts
26
+ PROJ.ann_paragraphs.each do |p|
27
+ fd.puts "== #{p.upcase}"
28
+ fd.puts
29
+ fd.puts paragraphs_of(PROJ.readme_file, p).join("\n\n")
30
+ fd.puts
31
+ end
32
+ fd.puts PROJ.ann_text if PROJ.ann_text
33
+ end
34
+ end
35
+
36
+ desc "Create an announcement file"
37
+ task :announcement => PROJ.ann_file
38
+
39
+ desc "Send an email announcement"
40
+ task :email => PROJ.ann_file do
41
+ from = PROJ.ann_email[:from] || PROJ.email
42
+ to = Array(PROJ.ann_email[:to])
43
+
44
+ ### build a mail header for RFC 822
45
+ rfc822msg = "From: #{from}\n"
46
+ rfc822msg << "To: #{to.join(',')}\n"
47
+ rfc822msg << "Subject: [ANN] #{PROJ.name} #{PROJ.version}"
48
+ rfc822msg << " (#{PROJ.release_name})" if PROJ.release_name
49
+ rfc822msg << "\n"
50
+ rfc822msg << "Date: #{Time.new.rfc822}\n"
51
+ rfc822msg << "Message-Id: "
52
+ rfc822msg << "<#{"%.8f" % Time.now.to_f}@#{PROJ.ann_email[:domain]}>\n\n"
53
+ rfc822msg << File.read(PROJ.ann_file)
54
+
55
+ params = [:server, :port, :domain, :acct, :passwd, :authtype].map do |key|
56
+ PROJ.ann_email[key]
57
+ end
58
+
59
+ params[3] = PROJ.email if params[3].nil?
60
+
61
+ if params[4].nil?
62
+ STDOUT.write "Please enter your e-mail password (#{params[3]}): "
63
+ params[4] = STDIN.gets.chomp
64
+ end
65
+
66
+ ### send email
67
+ Net::SMTP.start(*params) {|smtp| smtp.sendmail(rfc822msg, from, to)}
68
+ end
69
+ end # namespace :ann
70
+
71
+ desc 'Alias to ann:announcement'
72
+ task :ann => 'ann:announcement'
73
+
74
+ CLOBBER << PROJ.ann_file
75
+
76
+ # EOF
@@ -1,4 +1,4 @@
1
- # $Id: annotations.rake 87 2008-02-08 17:21:07Z tim_pease $
1
+ # $Id$
2
2
 
3
3
  if HAVE_BONES
4
4
 
@@ -0,0 +1,40 @@
1
+ # $Id: bones.rake 105 2008-02-26 04:43:21Z tim_pease $
2
+
3
+ require 'pp'
4
+ require 'stringio'
5
+
6
+ namespace :bones do
7
+
8
+ desc 'Show the PROJ open struct'
9
+ task :debug do |t|
10
+ atr = if ARGV.length == 2
11
+ t.application.top_level_tasks.pop
12
+ end
13
+ sio = StringIO.new
14
+ sep = "\n" + ' '*27
15
+ fmt = "%23s => %s"
16
+
17
+ if atr
18
+ PP.pp(PROJ.send(atr.to_sym), sio, 49)
19
+ sio.seek 0
20
+ val = sio.read
21
+ val = val.split("\n").join(sep)
22
+
23
+ puts fmt % [atr, val]
24
+ else
25
+ h = PROJ.instance_variable_get(:@table)
26
+ h.keys.map {|k| k.to_s}.sort.each do |k|
27
+ sio.truncate 0
28
+ PP.pp(h[k.to_sym], sio, 49)
29
+ sio.seek 0
30
+ val = sio.read
31
+ val = val.split("\n").join(sep)
32
+
33
+ puts fmt % [k, val]
34
+ end
35
+ end
36
+ end
37
+
38
+ end # namespace :bones
39
+
40
+ # EOF
@@ -31,7 +31,6 @@ namespace :doc do
31
31
  sh "#{RDOC} --ri -o ri ."
32
32
  end
33
33
 
34
- desc 'Remove ri products'
35
34
  task :clobber_ri do
36
35
  rm_r 'ri' rescue nil
37
36
  end
@@ -44,6 +43,6 @@ task :doc => 'doc:rdoc'
44
43
  desc 'Remove all build products'
45
44
  task :clobber => %w(doc:clobber_rdoc doc:clobber_ri)
46
45
 
47
- remove_desc_for_task %w(doc:clobber_rdoc doc:clobber_ri)
46
+ remove_desc_for_task %w(doc:clobber_rdoc)
48
47
 
49
48
  # EOF
@@ -12,6 +12,7 @@ namespace :gem do
12
12
  s.email = PROJ.email
13
13
  s.homepage = Array(PROJ.url).first
14
14
  s.rubyforge_project = PROJ.rubyforge_name
15
+ s.post_install_message = PROJ.post_install_message
15
16
 
16
17
  s.description = PROJ.description
17
18
 
@@ -62,9 +63,29 @@ namespace :gem do
62
63
  puts PROJ.spec.to_ruby
63
64
  end
64
65
 
65
- Rake::GemPackageTask.new(PROJ.spec) do |pkg|
66
+ pkg = Rake::PackageTask.new(PROJ.name, PROJ.version) do |pkg|
66
67
  pkg.need_tar = PROJ.need_tar
67
68
  pkg.need_zip = PROJ.need_zip
69
+ pkg.package_files += PROJ.spec.files
70
+ end
71
+ Rake::Task['gem:package'].instance_variable_set(:@full_comment, nil)
72
+
73
+ gem_file = if PROJ.spec.platform == Gem::Platform::RUBY
74
+ "#{pkg.package_name}.gem"
75
+ else
76
+ "#{pkg.package_name}-#{PROJ.spec.platform}.gem"
77
+ end
78
+
79
+ desc "Build the gem file #{gem_file}"
80
+ task :package => "#{pkg.package_dir}/#{gem_file}"
81
+
82
+ file "#{pkg.package_dir}/#{gem_file}" => [pkg.package_dir] + PROJ.spec.files do
83
+ when_writing("Creating GEM") {
84
+ Gem::Builder.new(PROJ.spec).build
85
+ verbose(true) {
86
+ mv gem_file, "#{pkg.package_dir}/#{gem_file}"
87
+ }
88
+ }
68
89
  end
69
90
 
70
91
  desc 'Install the gem'
@@ -74,9 +95,12 @@ namespace :gem do
74
95
 
75
96
  desc 'Uninstall the gem'
76
97
  task :uninstall do
77
- sh "#{SUDO} #{GEM} uninstall -v '#{PROJ.version}' -x #{PROJ.name}"
98
+ sh "#{SUDO} #{GEM} uninstall -v '#{PROJ.version}' -i -x #{PROJ.name}"
78
99
  end
79
100
 
101
+ desc 'Reinstall the gem'
102
+ task :reinstall => [:uninstall, :install]
103
+
80
104
  end # namespace :gem
81
105
 
82
106
  desc 'Alias to gem:package'
@@ -6,18 +6,11 @@ namespace :manifest do
6
6
 
7
7
  desc 'Verify the manifest'
8
8
  task :check do
9
- fn = 'Manifest.tmp'
10
- files = []
11
- exclude = Regexp.new(PROJ.exclude.join('|'))
12
- Find.find '.' do |path|
13
- path.sub! %r/^(\.\/|\/)/o, ''
14
- next unless test ?f, path
15
- next if path =~ exclude
16
- files << path
17
- end
9
+ fn = PROJ.manifest_file + '.tmp'
10
+ files = manifest_files
18
11
 
19
- File.open(fn, 'w') {|fp| fp.puts files.sort}
20
- lines = %x(#{DIFF} -du Manifest.txt #{fn}).split("\n")
12
+ File.open(fn, 'w') {|fp| fp.puts files}
13
+ lines = %x(#{DIFF} -du #{PROJ.manifest_file} #{fn}).split("\n")
21
14
  if HAVE_FACETS_ANSICODE and ENV.has_key?('TERM')
22
15
  lines.map! do |line|
23
16
  case line
@@ -34,19 +27,20 @@ namespace :manifest do
34
27
 
35
28
  desc 'Create a new manifest'
36
29
  task :create do
37
- fn = 'Manifest.txt'
38
- files = []
39
- exclude = Regexp.new(PROJ.exclude.join('|'))
40
- Find.find '.' do |path|
41
- path.sub! %r/^(\.\/|\/)/o, ''
42
- next unless test ?f, path
43
- next if path =~ exclude
44
- files << path
30
+ files = manifest_files
31
+ unless test(?f, PROJ.manifest_file)
32
+ files << PROJ.manifest_file
33
+ files.sort!
45
34
  end
35
+ File.open(PROJ.manifest_file, 'w') {|fp| fp.puts files}
36
+ end
46
37
 
47
- files << fn unless test ?f, fn
48
- File.open(fn, 'w') {|fp| fp.puts files.sort}
38
+ task :assert do
39
+ files = manifest_files
40
+ manifest = File.read(PROJ.manifest_file).split($/)
41
+ raise "ERROR: #{PROJ.manifest_file} is out of date" unless files == manifest
49
42
  end
43
+
50
44
  end # namespace :manifest
51
45
 
52
46
  desc 'Alias to manifest:check'
@@ -1,18 +1,30 @@
1
- # $Id$
1
+ # $Id: post_load.rake 105 2008-02-26 04:43:21Z tim_pease $
2
2
 
3
3
  # This file does not define any rake tasks. It is used to load some project
4
4
  # settings if they are not defined by the user.
5
5
 
6
- unless PROJ.changes
7
- PROJ.changes = paragraphs_of('History.txt', 0..1).join("\n\n")
8
- end
6
+ PROJ.rdoc_exclude << "^#{Regexp.escape(PROJ.manifest_file)}$"
7
+ PROJ.exclude << "^#{Regexp.escape(PROJ.ann_file)}$"
9
8
 
10
- unless PROJ.description
11
- PROJ.description = paragraphs_of('README.txt', 'description').join("\n\n")
12
- end
9
+ PROJ.exclude.flatten!
10
+ PROJ.rdoc_exclude.flatten!
11
+ PROJ.annotation_exclude.flatten!
13
12
 
14
- unless PROJ.summary
15
- PROJ.summary = PROJ.description.split('.').first
16
- end
13
+ PROJ.changes ||= paragraphs_of(PROJ.history_file, 0..1).join("\n\n")
14
+
15
+ PROJ.description ||= paragraphs_of(PROJ.readme_file, 'description').join("\n\n")
16
+
17
+ PROJ.summary ||= PROJ.description.split('.').first
18
+
19
+ PROJ.files ||=
20
+ if test(?f, PROJ.manifest_file)
21
+ files = File.readlines(PROJ.manifest_file).map {|fn| fn.chomp.strip}
22
+ files.delete ''
23
+ files
24
+ else [] end
25
+
26
+ PROJ.executables ||= PROJ.files.find_all {|fn| fn =~ %r/^bin/}
27
+
28
+ PROJ.rdoc_main ||= PROJ.readme_file
17
29
 
18
30
  # EOF
@@ -1,7 +1,8 @@
1
- # $Id: setup.rb 87 2008-02-08 17:21:07Z tim_pease $
1
+ # $Id: setup.rb 105 2008-02-26 04:43:21Z tim_pease $
2
2
 
3
3
  require 'rubygems'
4
4
  require 'rake'
5
+ require 'rake/clean'
5
6
  require 'fileutils'
6
7
  require 'ostruct'
7
8
 
@@ -17,6 +18,10 @@ PROJ.url = nil
17
18
  PROJ.version = ENV['VERSION'] || '0.0.0'
18
19
  PROJ.rubyforge_name = nil
19
20
  PROJ.exclude = %w(tmp$ bak$ ~$ CVS .svn/ ^pkg/ ^doc/)
21
+ PROJ.release_name = ENV['RELEASE']
22
+ PROJ.history_file = 'History.txt'
23
+ PROJ.manifest_file = 'Manifest.txt'
24
+ PROJ.readme_file = 'README.txt'
20
25
 
21
26
  # Rspec
22
27
  PROJ.specs = FileList['spec/**/*_spec.rb']
@@ -28,13 +33,16 @@ PROJ.test_file = 'test/all.rb'
28
33
  PROJ.test_opts = []
29
34
 
30
35
  # Rcov
36
+ PROJ.rcov_dir = 'coverage'
31
37
  PROJ.rcov_opts = ['--sort', 'coverage', '-T']
38
+ PROJ.rcov_threshold = 90.0
39
+ PROJ.rcov_threshold_exact = false
32
40
 
33
41
  # Rdoc
34
42
  PROJ.rdoc_opts = []
35
43
  PROJ.rdoc_include = %w(^lib/ ^bin/ ^ext/ .txt$)
36
- PROJ.rdoc_exclude = %w(extconf.rb$ ^Manifest.txt$)
37
- PROJ.rdoc_main = 'README.txt'
44
+ PROJ.rdoc_exclude = %w(extconf.rb$)
45
+ PROJ.rdoc_main = nil
38
46
  PROJ.rdoc_dir = 'doc'
39
47
  PROJ.rdoc_remote_dir = nil
40
48
 
@@ -45,16 +53,12 @@ PROJ.libs = []
45
53
  %w(lib ext).each {|dir| PROJ.libs << dir if test ?d, dir}
46
54
 
47
55
  # Gem Packaging
48
- PROJ.files =
49
- if test ?f, 'Manifest.txt'
50
- files = File.readlines('Manifest.txt').map {|fn| fn.chomp.strip}
51
- files.delete ''
52
- files
53
- else [] end
54
- PROJ.executables = PROJ.files.find_all {|fn| fn =~ %r/^bin/}
56
+ PROJ.files = nil
57
+ PROJ.executables = nil
55
58
  PROJ.dependencies = []
56
59
  PROJ.need_tar = true
57
60
  PROJ.need_zip = false
61
+ PROJ.post_install_message = nil
58
62
 
59
63
  # File Annotations
60
64
  PROJ.annotation_exclude = %w(^tasks/setup.rb$)
@@ -68,6 +72,21 @@ PROJ.svn_trunk = 'trunk'
68
72
  PROJ.svn_tags = 'tags'
69
73
  PROJ.svn_branches = 'branches'
70
74
 
75
+ # Announce
76
+ PROJ.ann_file = 'announcement.txt'
77
+ PROJ.ann_text = nil
78
+ PROJ.ann_paragraphs = []
79
+ PROJ.ann_email = {
80
+ :from => nil,
81
+ :to => %w(ruby-talk@ruby-lang.org),
82
+ :server => 'localhost',
83
+ :port => 25,
84
+ :domain => ENV['HOSTNAME'],
85
+ :acct => nil,
86
+ :passwd => nil,
87
+ :authtype => :plain
88
+ }
89
+
71
90
  # Load the other rake files in the tasks folder
72
91
  rakefiles = Dir.glob('tasks/*.rake').sort
73
92
  rakefiles.unshift(rakefiles.delete('tasks/post_load.rake')).compact!
@@ -100,8 +119,8 @@ SUDO = if WIN32 then ''
100
119
  else '' end
101
120
  end
102
121
 
103
- RCOV = WIN32 ? 'rcov.cmd' : 'rcov'
104
- GEM = WIN32 ? 'gem.cmd' : 'gem'
122
+ RCOV = WIN32 ? 'rcov.bat' : 'rcov'
123
+ GEM = WIN32 ? 'gem.bat' : 'gem'
105
124
 
106
125
  %w(rcov spec/rake/spectask rubyforge bones facets/ansicode).each do |lib|
107
126
  begin
@@ -150,7 +169,10 @@ def depend_on( name, version = nil )
150
169
  spec = Gem.source_index.find_name(name).last
151
170
  version = spec.version.to_s if version.nil? and !spec.nil?
152
171
 
153
- PROJ.dependencies << (version.nil? ? [name] : [name, ">= #{version}"])
172
+ PROJ.dependencies << case version
173
+ when nil; [name]
174
+ when %r/^\d/; [name, ">= #{version}"]
175
+ else [name, version] end
154
176
  end
155
177
 
156
178
  # Adds the given arguments to the include path if they are not already there
@@ -187,4 +209,19 @@ def in_directory( dir, &block )
187
209
  end
188
210
  end
189
211
 
212
+ # Scans the current working directory and creates a list of files that are
213
+ # candidates to be in the manifest.
214
+ #
215
+ def manifest_files
216
+ files = []
217
+ exclude = Regexp.new(PROJ.exclude.join('|'))
218
+ Find.find '.' do |path|
219
+ path.sub! %r/^(\.\/|\/)/o, ''
220
+ next unless test ?f, path
221
+ next if path =~ exclude
222
+ files << path
223
+ end
224
+ files.sort!
225
+ end
226
+
190
227
  # EOF
@@ -6,7 +6,7 @@ namespace :test do
6
6
 
7
7
  Rake::TestTask.new(:run) do |t|
8
8
  t.libs = PROJ.libs
9
- t.test_files = if test ?f, PROJ.test_file then [PROJ.test_file]
9
+ t.test_files = if test(?f, PROJ.test_file) then [PROJ.test_file]
10
10
  else PROJ.tests end
11
11
  t.ruby_opts += PROJ.ruby_opts
12
12
  t.ruby_opts += PROJ.test_opts
@@ -15,14 +15,14 @@ namespace :test do
15
15
  if HAVE_RCOV
16
16
  desc 'Run rcov on the unit tests'
17
17
  task :rcov => :clobber_rcov do
18
- opts = PROJ.rcov_opts.join(' ')
19
- files = if test ?f, PROJ.test_file then [PROJ.test_file]
18
+ opts = PROJ.rcov_opts.dup << '-o' << PROJ.rcov_dir
19
+ opts = opts.join(' ')
20
+ files = if test(?f, PROJ.test_file) then [PROJ.test_file]
20
21
  else PROJ.tests end
21
22
  files = files.join(' ')
22
23
  sh "#{RCOV} #{files} #{opts}"
23
24
  end
24
25
 
25
- desc 'Remove rcov products'
26
26
  task :clobber_rcov do
27
27
  rm_r 'coverage' rescue nil
28
28
  end
@@ -35,6 +35,4 @@ task :test => 'test:run'
35
35
 
36
36
  task :clobber => 'test:clobber_rcov' if HAVE_RCOV
37
37
 
38
- remove_desc_for_task %w(test:clobber_rcov)
39
-
40
38
  # EOF
@@ -1,4 +1,4 @@
1
- # $Id: test_rolling_file.rb 97 2008-02-13 00:32:18Z tim_pease $
1
+ # $Id: test_rolling_file.rb 105 2008-02-26 04:43:21Z tim_pease $
2
2
 
3
3
  require File.join(File.dirname(__FILE__), %w[.. setup])
4
4
 
@@ -109,8 +109,10 @@ module TestAppenders
109
109
  ap << "random message\n"
110
110
  assert_equal 2, Dir.glob(@glob).length
111
111
 
112
- t = ap.instance_variable_get :@start_time
113
- ap.instance_variable_set :@start_time, t - 3600 * 24
112
+ age_fn = @fn + '.age'
113
+ now = ::File.mtime(age_fn)
114
+ start = now - 3600 * 24
115
+ ::File.utime(start, start, age_fn)
114
116
 
115
117
  sleep 0.250
116
118
  ap << "yet another random message\n"
@@ -122,8 +124,8 @@ module TestAppenders
122
124
  ap << "random message\n"
123
125
  assert_equal 3, Dir.glob(@glob).length
124
126
 
125
- t = ap.instance_variable_get :@start_time
126
- ap.instance_variable_set :@start_time, t - 3600 * 24 * 7
127
+ start = now - 3600 * 24 * 7
128
+ ::File.utime(start, start, age_fn)
127
129
 
128
130
  sleep 0.250
129
131
  ap << "yet another random message\n"
@@ -135,8 +137,8 @@ module TestAppenders
135
137
  ap << "random message\n"
136
138
  assert_equal 4, Dir.glob(@glob).length
137
139
 
138
- t = ap.instance_variable_get :@start_time
139
- ap.instance_variable_set :@start_time, t - 3600 * 24 * 31
140
+ start = now - 3600 * 24 * 31
141
+ ::File.utime(start, start, age_fn)
140
142
 
141
143
  sleep 0.250
142
144
  ap << "yet another random message\n"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logging
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Pease
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-02-12 00:00:00 -07:00
12
+ date: 2008-02-25 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -21,15 +21,6 @@ dependencies:
21
21
  - !ruby/object:Gem::Version
22
22
  version: 0.8.0
23
23
  version:
24
- - !ruby/object:Gem::Dependency
25
- name: lockfile
26
- version_requirement:
27
- version_requirements: !ruby/object:Gem::Requirement
28
- requirements:
29
- - - ">="
30
- - !ruby/object:Gem::Version
31
- version: 1.4.3
32
- version:
33
24
  description: Logging is a flexible logging library for use in Ruby programs based on the design of Java's log4j library. It features a hierarchical logging system, custom level names, multiple output destinations per log event, custom formatting, and more.
34
25
  email: tim.pease@gmail.com
35
26
  executables: []
@@ -62,8 +53,11 @@ files:
62
53
  - lib/logging/logger.rb
63
54
  - lib/logging/repository.rb
64
55
  - lib/logging/root_logger.rb
56
+ - lib/logging/stelan/lockfile.rb
65
57
  - lib/logging/utils.rb
58
+ - tasks/ann.rake
66
59
  - tasks/annotations.rake
60
+ - tasks/bones.rake
67
61
  - tasks/doc.rake
68
62
  - tasks/gem.rake
69
63
  - tasks/manifest.rake